This API returns a variable would be tracked TODO: This API analyze single loop, not a nested loop. If there is an instruction (array access) in the outer loop, only the outer loop is analyzed If exist in inner loop, analyze only inner loop Nested loop support is required when analyzing ranges of array index.
| 133 | // If exist in inner loop, analyze only inner loop |
| 134 | // Nested loop support is required when analyzing ranges of array index. |
| 135 | Value *ArrayAnalyzer::getTrackingVariable(Loop &L) { |
| 136 | bool PositiveStride = false; |
| 137 | |
| 138 | auto LoopHeader = L.getHeader(); |
| 139 | assert(LoopHeader && "Unexpected Program State"); |
| 140 | |
| 141 | auto *F = LoopHeader->getParent(); |
| 142 | assert(F && "Unexpected Program State"); |
| 143 | |
| 144 | auto &SEA = FAM.getResult<ScalarEvolutionAnalysis>(*F); |
| 145 | auto *VariantV = getRelatedIndV(L, SEA); |
| 146 | auto *ExitCond = getLoopExitCond(L); |
| 147 | if (!ExitCond) |
| 148 | return nullptr; |
| 149 | assert(ExitCond->getNumOperands() > 1 && "Unexpected Program State"); |
| 150 | |
| 151 | auto *CmpOp0 = ExitCond->getOperand(0); |
| 152 | auto *CmpOp1 = ExitCond->getOperand(1); |
| 153 | |
| 154 | // For a variable dependent on the induction variable, |
| 155 | // use the Scalar Evolution to get a phinode(loop-variant) and step |
| 156 | if (VariantV) { |
| 157 | if (const auto *AR = dyn_cast<SCEVAddRecExpr>(SEA.getSCEV(VariantV))) { |
| 158 | const auto *Stride = AR->getStepRecurrence(SEA); |
| 159 | PositiveStride = SEA.isKnownPositive(Stride); |
| 160 | } |
| 161 | } else { |
| 162 | // For non induction variable, analyze loop termination |
| 163 | // to get the phinode(loop-variant) and step |
| 164 | // |
| 165 | // ex) while(size > 0) size -= getSize() |
| 166 | // |
| 167 | // The induction variable increases/decreases by a fixed amount. |
| 168 | // However the "size" is reduced by the external API's return value. |
| 169 | // So "size" is not induction variable. |
| 170 | // There is no induction variable in this loop |
| 171 | for (unsigned CmpOpNum = 0, E1 = ExitCond->getNumOperands(); CmpOpNum < E1; |
| 172 | CmpOpNum++) { |
| 173 | auto *PN = dyn_cast<PHINode>(ExitCond->getOperand(CmpOpNum)); |
| 174 | if (!PN) |
| 175 | continue; |
| 176 | |
| 177 | VariantV = ExitCond->getOperand(CmpOpNum); |
| 178 | |
| 179 | for (unsigned PnOpNum = 0, E2 = PN->getNumIncomingValues(); PnOpNum < E2; |
| 180 | PnOpNum++) { |
| 181 | if (!L.contains(PN->getIncomingBlock(PnOpNum))) |
| 182 | continue; |
| 183 | |
| 184 | auto *BO = dyn_cast<BinaryOperator>(PN->getIncomingValue(PnOpNum)); |
| 185 | if (!BO) |
| 186 | continue; |
| 187 | |
| 188 | if (BO->getOpcode() == Instruction::Add || |
| 189 | BO->getOpcode() == Instruction::Mul || |
| 190 | BO->getOpcode() == Instruction::FAdd || |
| 191 | BO->getOpcode() == Instruction::FMul) |
| 192 | PositiveStride = true; |
nothing calls this directly
no test coverage detected