bool InductionDescriptor::isInductionPHI(PHINode *Phi, const Loop *TheLoop, PredicatedScalarEvolution &PSE, InductionDescriptor &D, bool Assume) { Type *PhiTy = Phi->getType(); // Handle integer and pointer inductions variables. // Now we handle also FP induction but not trying to make a // recurrent expression from the PHI node in-place. if (!PhiTy->isIntegerTy() && !PhiTy->isPointerTy() && !PhiTy->isFloatTy() && !PhiTy->isDoubleTy() && !PhiTy->isHalfTy()) return false; if (PhiTy->isFloatingPointTy()) return isFPInductionPHI(Phi, TheLoop, PSE.getSE(), D); const SCEV *PhiScev = PSE.getSCEV(Phi); const auto *AR = dyn_cast<SCEVAddRecExpr>(PhiScev); // We need this expression to be an AddRecExpr. if (Assume && !AR) AR = PSE.getAsAddRec(Phi); if (!AR) { DEBUG(dbgs() << "LV: PHI is not a poly recurrence.\n"); return false; } return isInductionPHI(Phi, TheLoop, PSE.getSE(), D, AR); }
bool InductionDescriptor::isInductionPHI(PHINode *Phi, const Loop *TheLoop, PredicatedScalarEvolution &PSE, InductionDescriptor &D, bool Assume) { Type *PhiTy = Phi->getType(); // Handle integer and pointer inductions variables. // Now we handle also FP induction but not trying to make a // recurrent expression from the PHI node in-place. if (!PhiTy->isIntegerTy() && !PhiTy->isPointerTy() && !PhiTy->isFloatTy() && !PhiTy->isDoubleTy() && !PhiTy->isHalfTy()) return false; if (PhiTy->isFloatingPointTy()) return isFPInductionPHI(Phi, TheLoop, PSE.getSE(), D); const SCEV *PhiScev = PSE.getSCEV(Phi); const auto *AR = dyn_cast<SCEVAddRecExpr>(PhiScev); // We need this expression to be an AddRecExpr. if (Assume && !AR) AR = PSE.getAsAddRec(Phi); if (!AR) { LLVM_DEBUG(dbgs() << "LV: PHI is not a poly recurrence.\n"); return false; } // Record any Cast instructions that participate in the induction update const auto *SymbolicPhi = dyn_cast<SCEVUnknown>(PhiScev); // If we started from an UnknownSCEV, and managed to build an addRecurrence // only after enabling Assume with PSCEV, this means we may have encountered // cast instructions that required adding a runtime check in order to // guarantee the correctness of the AddRecurrence respresentation of the // induction. if (PhiScev != AR && SymbolicPhi) { SmallVector<Instruction *, 2> Casts; if (getCastsForInductionPHI(PSE, SymbolicPhi, AR, Casts)) return isInductionPHI(Phi, TheLoop, PSE.getSE(), D, AR, &Casts); } return isInductionPHI(Phi, TheLoop, PSE.getSE(), D, AR); }
bool InductionDescriptor::isInductionPHI(PHINode *Phi, PredicatedScalarEvolution &PSE, InductionDescriptor &D, bool Assume) { Type *PhiTy = Phi->getType(); // We only handle integer and pointer inductions variables. if (!PhiTy->isIntegerTy() && !PhiTy->isPointerTy()) return false; const SCEV *PhiScev = PSE.getSCEV(Phi); const auto *AR = dyn_cast<SCEVAddRecExpr>(PhiScev); // We need this expression to be an AddRecExpr. if (Assume && !AR) AR = PSE.getAsAddRec(Phi); if (!AR) { DEBUG(dbgs() << "LV: PHI is not a poly recurrence.\n"); return false; } return isInductionPHI(Phi, PSE.getSE(), D, AR); }
/// This function is called when we suspect that the update-chain of a phi node /// (whose symbolic SCEV expression sin \p PhiScev) contains redundant casts, /// that can be ignored. (This can happen when the PSCEV rewriter adds a runtime /// predicate P under which the SCEV expression for the phi can be the /// AddRecurrence \p AR; See createAddRecFromPHIWithCast). We want to find the /// cast instructions that are involved in the update-chain of this induction. /// A caller that adds the required runtime predicate can be free to drop these /// cast instructions, and compute the phi using \p AR (instead of some scev /// expression with casts). /// /// For example, without a predicate the scev expression can take the following /// form: /// (Ext ix (Trunc iy ( Start + i*Step ) to ix) to iy) /// /// It corresponds to the following IR sequence: /// %for.body: /// %x = phi i64 [ 0, %ph ], [ %add, %for.body ] /// %casted_phi = "ExtTrunc i64 %x" /// %add = add i64 %casted_phi, %step /// /// where %x is given in \p PN, /// PSE.getSCEV(%x) is equal to PSE.getSCEV(%casted_phi) under a predicate, /// and the IR sequence that "ExtTrunc i64 %x" represents can take one of /// several forms, for example, such as: /// ExtTrunc1: %casted_phi = and %x, 2^n-1 /// or: /// ExtTrunc2: %t = shl %x, m /// %casted_phi = ashr %t, m /// /// If we are able to find such sequence, we return the instructions /// we found, namely %casted_phi and the instructions on its use-def chain up /// to the phi (not including the phi). static bool getCastsForInductionPHI(PredicatedScalarEvolution &PSE, const SCEVUnknown *PhiScev, const SCEVAddRecExpr *AR, SmallVectorImpl<Instruction *> &CastInsts) { assert(CastInsts.empty() && "CastInsts is expected to be empty."); auto *PN = cast<PHINode>(PhiScev->getValue()); assert(PSE.getSCEV(PN) == AR && "Unexpected phi node SCEV expression"); const Loop *L = AR->getLoop(); // Find any cast instructions that participate in the def-use chain of // PhiScev in the loop. // FORNOW/TODO: We currently expect the def-use chain to include only // two-operand instructions, where one of the operands is an invariant. // createAddRecFromPHIWithCasts() currently does not support anything more // involved than that, so we keep the search simple. This can be // extended/generalized as needed. auto getDef = [&](const Value *Val) -> Value * { const BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Val); if (!BinOp) return nullptr; Value *Op0 = BinOp->getOperand(0); Value *Op1 = BinOp->getOperand(1); Value *Def = nullptr; if (L->isLoopInvariant(Op0)) Def = Op1; else if (L->isLoopInvariant(Op1)) Def = Op0; return Def; }; // Look for the instruction that defines the induction via the // loop backedge. BasicBlock *Latch = L->getLoopLatch(); if (!Latch) return false; Value *Val = PN->getIncomingValueForBlock(Latch); if (!Val) return false; // Follow the def-use chain until the induction phi is reached. // If on the way we encounter a Value that has the same SCEV Expr as the // phi node, we can consider the instructions we visit from that point // as part of the cast-sequence that can be ignored. bool InCastSequence = false; auto *Inst = dyn_cast<Instruction>(Val); while (Val != PN) { // If we encountered a phi node other than PN, or if we left the loop, // we bail out. if (!Inst || !L->contains(Inst)) { return false; } auto *AddRec = dyn_cast<SCEVAddRecExpr>(PSE.getSCEV(Val)); if (AddRec && PSE.areAddRecsEqualWithPreds(AddRec, AR)) InCastSequence = true; if (InCastSequence) { // Only the last instruction in the cast sequence is expected to have // uses outside the induction def-use chain. if (!CastInsts.empty()) if (!Inst->hasOneUse()) return false; CastInsts.push_back(Inst); } Val = getDef(Val); if (!Val) return false; Inst = dyn_cast<Instruction>(Val); } return InCastSequence; }