| 71 | } |
| 72 | |
| 73 | bool LoopAnalyzer::handleUser(StackFrame &Frame, llvm::Value &User, |
| 74 | std::stack<StackFrame> &DefUseChains, |
| 75 | std::set<llvm::Value *> &VisitedNodes) { |
| 76 | Value *Def = Frame.Value; |
| 77 | ArgFlow &DefFlow = Frame.AnalysisResult; |
| 78 | auto &A = DefFlow.getLLVMArg(); |
| 79 | |
| 80 | if (!isa<Instruction>(&User)) |
| 81 | return false; |
| 82 | |
| 83 | if (auto *ICI = dyn_cast<ICmpInst>(&User)) { |
| 84 | auto *F = A.getParent(); |
| 85 | auto *BB = ICI->getParent(); |
| 86 | if (!F || !BB) |
| 87 | return false; |
| 88 | |
| 89 | auto &LI = FAM.getResult<LoopAnalysis>(*F); |
| 90 | auto *L = LI.getLoopFor(BB); |
| 91 | if (!L) |
| 92 | return false; |
| 93 | |
| 94 | if (isUsedAsInitializer(*ICI, *L, VisitedNodes)) |
| 95 | return false; |
| 96 | |
| 97 | auto *ExitCond = getLoopExitCond(*L); |
| 98 | if (!ExitCond || ExitCond != ICI) |
| 99 | return false; |
| 100 | |
| 101 | llvm::Value *Op = ExitCond->getOperand(0); |
| 102 | if (Op != Def) |
| 103 | Op = ExitCond->getOperand(1); |
| 104 | if (Op != Def) |
| 105 | return false; |
| 106 | if (!L->isLoopInvariant(Op)) { |
| 107 | return false; |
| 108 | } |
| 109 | |
| 110 | DefFlow.LoopExit = true; |
| 111 | DefFlow.LoopDepth = LI.getLoopDepth(BB); |
| 112 | return true; |
| 113 | } |
| 114 | |
| 115 | if (auto *CB = dyn_cast<CallBase>(&User)) { |
| 116 | auto *CF = util::getCalledFunction(*CB, Solver); |
| 117 | if (!CF) |
| 118 | return false; |
| 119 | if (CF == A.getParent()) |
| 120 | return false; |
| 121 | |
| 122 | for (auto &Param : CF->args()) { |
| 123 | auto *CallArg = CB->getArgOperand(Param.getArgNo()); |
| 124 | if (CallArg != Def) |
| 125 | continue; |
| 126 | if (!CallArg) |
| 127 | continue; |
| 128 | |
| 129 | analyze(Param); |
| 130 | auto &CallAF = getOrCreateArgFlow(Param); |
nothing calls this directly
no test coverage detected