Index: llvm/lib/Analysis/IVDescriptors.cpp =================================================================== --- llvm/lib/Analysis/IVDescriptors.cpp +++ llvm/lib/Analysis/IVDescriptors.cpp @@ -1299,21 +1299,14 @@ return nullptr; } -bool InductionDescriptor::isFPInductionPHI(PHINode *Phi, const Loop *TheLoop, - ScalarEvolution *SE, - InductionDescriptor &D) { - - // Here we only handle FP induction variables. - assert(Phi->getType()->isFloatingPointTy() && "Unexpected Phi type"); - - if (TheLoop->getHeader() != Phi->getParent()) - return false; - - // The loop may have multiple entrances or multiple exits; we can analyze - // this phi if it has a unique entry value and a unique backedge value. +// Check that the loop has a unique entry value and a unique backedge value and +// initialize StartValue and BEValue with these values from the Phi. +static bool getStartAndBEValues(Value *&StartValue, Value *&BEValue, + const Loop *TheLoop, PHINode *Phi) { + // We can analyze this phi if it has a unique entry value and a unique + // backedge value. if (Phi->getNumIncomingValues() != 2) return false; - Value *BEValue = nullptr, *StartValue = nullptr; if (TheLoop->contains(Phi->getIncomingBlock(0))) { BEValue = Phi->getIncomingValue(0); StartValue = Phi->getIncomingValue(1); @@ -1323,7 +1316,22 @@ BEValue = Phi->getIncomingValue(1); StartValue = Phi->getIncomingValue(0); } + return true; +} +bool InductionDescriptor::isFPInductionPHI(PHINode *Phi, const Loop *TheLoop, + ScalarEvolution *SE, + InductionDescriptor &D) { + + // Here we only handle FP induction variables. + assert(Phi->getType()->isFloatingPointTy() && "Unexpected Phi type"); + + if (TheLoop->getHeader() != Phi->getParent()) + return false; + + Value *BEValue = nullptr, *StartValue = nullptr; + if (!getStartAndBEValues(StartValue, BEValue, TheLoop, Phi)) + return false; BinaryOperator *BOp = dyn_cast(BEValue); if (!BOp) return false; @@ -1505,6 +1513,10 @@ PHINode *Phi, const Loop *TheLoop, ScalarEvolution *SE, InductionDescriptor &D, const SCEV *Expr, SmallVectorImpl *CastsToIgnore) { + + if (TheLoop->getHeader() != Phi->getParent()) + return false; + Type *PhiTy = Phi->getType(); // We only handle integer and pointer inductions variables. if (!PhiTy->isIntegerTy() && !PhiTy->isPointerTy()) @@ -1527,8 +1539,9 @@ return false; } - Value *StartValue = - Phi->getIncomingValueForBlock(AR->getLoop()->getLoopPreheader()); + Value *BEValue = nullptr, *StartValue = nullptr; + if (!getStartAndBEValues(StartValue, BEValue, TheLoop, Phi)) + return false; BasicBlock *Latch = AR->getLoop()->getLoopLatch(); if (!Latch) Index: llvm/lib/Transforms/Utils/LoopUtils.cpp =================================================================== --- llvm/lib/Transforms/Utils/LoopUtils.cpp +++ llvm/lib/Transforms/Utils/LoopUtils.cpp @@ -1243,20 +1243,6 @@ return true; } -/// Checks if it is safe to call InductionDescriptor::isInductionPHI for \p Phi, -/// and returns true if this Phi is an induction phi in the loop. When -/// isInductionPHI returns true, \p ID will be also be set by isInductionPHI. -static bool checkIsIndPhi(PHINode *Phi, Loop *L, ScalarEvolution *SE, - InductionDescriptor &ID) { - if (!Phi) - return false; - if (!L->getLoopPreheader()) - return false; - if (Phi->getParent() != L->getHeader()) - return false; - return InductionDescriptor::isInductionPHI(Phi, L, SE, ID); -} - int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, ScalarEvolution *SE, const TargetTransformInfo *TTI, @@ -1317,7 +1303,7 @@ InductionDescriptor ID; PHINode *IndPhi = dyn_cast(Inst); if (IndPhi) { - if (!checkIsIndPhi(IndPhi, L, SE, ID)) + if (!InductionDescriptor::isInductionPHI(IndPhi, L, SE, ID)) continue; // This is an induction PHI. Check that the only users are PHI // nodes, and induction variable update binary operators. @@ -1338,7 +1324,9 @@ continue; if (llvm::any_of(Inst->users(), [&](User *U) { PHINode *Phi = dyn_cast(U); - if (Phi != PN && !checkIsIndPhi(Phi, L, SE, ID)) + if (!Phi) + return true; + if (Phi != PN && !InductionDescriptor::isInductionPHI(Phi, L, SE, ID)) return true; return false; }))