diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp index 641850b46bbd8..9b8efc020769c 100644 --- a/llvm/lib/Analysis/IVDescriptors.cpp +++ b/llvm/lib/Analysis/IVDescriptors.cpp @@ -15,6 +15,7 @@ #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/ScalarEvolutionPatternMatch.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Instructions.h" @@ -25,6 +26,7 @@ using namespace llvm; using namespace llvm::PatternMatch; +using namespace llvm::SCEVPatternMatch; #define DEBUG_TYPE "iv-descriptors" @@ -719,11 +721,12 @@ RecurrenceDescriptor::isFindIVPattern(RecurKind Kind, Loop *TheLoop, if (!SE.isSCEVable(Ty)) return std::nullopt; - auto *AR = dyn_cast(SE.getSCEV(V)); - if (!AR || AR->getLoop() != TheLoop) + auto *AR = SE.getSCEV(V); + const SCEV *Step; + if (!match(AR, m_scev_AffineAddRec(m_SCEV(), m_SCEV(Step), + m_SpecificLoop(TheLoop)))) return std::nullopt; - const SCEV *Step = AR->getStepRecurrence(SE); if ((isFindFirstIVRecurrenceKind(Kind) && !SE.isKnownNegative(Step)) || (isFindLastIVRecurrenceKind(Kind) && !SE.isKnownPositive(Step))) return std::nullopt; @@ -1396,8 +1399,8 @@ InductionDescriptor::InductionDescriptor(Value *Start, InductionKind K, } ConstantInt *InductionDescriptor::getConstIntStepValue() const { - if (isa(Step)) - return dyn_cast(cast(Step)->getValue()); + if (auto *C = dyn_cast(Step)) + return dyn_cast(C->getValue()); return nullptr; } @@ -1614,41 +1617,30 @@ bool InductionDescriptor::isInductionPHI( // Check that the PHI is consecutive. const SCEV *PhiScev = Expr ? Expr : SE->getSCEV(Phi); - const SCEVAddRecExpr *AR = dyn_cast(PhiScev); + const SCEV *Step; - if (!AR) { + // FIXME: We are currently matching the specific loop TheLoop; if it doesn't + // match, we should treat it as a uniform. Unfortunately, we don't currently + // know how to handled uniform PHIs. + if (!match(PhiScev, m_scev_AffineAddRec(m_SCEV(), m_SCEV(Step), + m_SpecificLoop(TheLoop)))) { LLVM_DEBUG(dbgs() << "LV: PHI is not a poly recurrence.\n"); return false; } - if (AR->getLoop() != TheLoop) { - // FIXME: We should treat this as a uniform. Unfortunately, we - // don't currently know how to handled uniform PHIs. - LLVM_DEBUG( - dbgs() << "LV: PHI is a recurrence with respect to an outer loop.\n"); - return false; - } - // This function assumes that InductionPhi is called only on Phi nodes // present inside loop headers. Check for the same, and throw an assert if // the current Phi is not present inside the loop header. - assert(Phi->getParent() == AR->getLoop()->getHeader() - && "Invalid Phi node, not present in loop header"); + assert(Phi->getParent() == TheLoop->getHeader() && + "Invalid Phi node, not present in loop header"); Value *StartValue = - Phi->getIncomingValueForBlock(AR->getLoop()->getLoopPreheader()); + Phi->getIncomingValueForBlock(TheLoop->getLoopPreheader()); - BasicBlock *Latch = AR->getLoop()->getLoopLatch(); + BasicBlock *Latch = TheLoop->getLoopLatch(); if (!Latch) return false; - const SCEV *Step = AR->getStepRecurrence(*SE); - // Calculate the pointer stride and check if it is consecutive. - // The stride may be a constant or a loop invariant integer value. - const SCEVConstant *ConstStep = dyn_cast(Step); - if (!ConstStep && !SE->isLoopInvariant(Step, TheLoop)) - return false; - if (PhiTy->isIntegerTy()) { BinaryOperator *BOp = dyn_cast(Phi->getIncomingValueForBlock(Latch));