[llvm] [VPlan] Update final exit value via VPlan. (PR #112147)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 31 03:29:34 PST 2024
================
@@ -8996,17 +8868,86 @@ static SetVector<VPIRInstruction *> collectUsersInExitBlocks(
return ExitUsersToFix;
}
+/// If \p Incoming is a user of a non-truncated induction, create recipes to
+/// compute the final value and update the user \p ExitIRI.
+static bool addInductionEndValue(
+ VPlan &Plan, VPIRInstruction *ExitIRI, VPValue *Incoming,
+ const MapVector<PHINode *, InductionDescriptor> &Inductions,
+ DenseMap<VPValue *, VPValue *> &EndValues, VPTypeAnalysis &TypeInfo) {
+ if ((isa<VPWidenIntOrFpInductionRecipe>(Incoming) &&
+ !cast<VPWidenIntOrFpInductionRecipe>(Incoming)->getTruncInst()) ||
+ isa<VPWidenPointerInductionRecipe>(Incoming) ||
+ (isa<Instruction>(Incoming->getUnderlyingValue()) &&
+ any_of(cast<Instruction>(Incoming->getUnderlyingValue())->users(),
+ [&Inductions](User *U) {
+ auto *P = dyn_cast<PHINode>(U);
+ return P && Inductions.contains(P);
+ }))) {
+ VPValue *IV;
+ if (auto *WideIV =
+ dyn_cast<VPWidenInductionRecipe>(Incoming->getDefiningRecipe()))
+ IV = WideIV;
+ else if (auto *WideIV =
+ dyn_cast<VPWidenInductionRecipe>(Incoming->getDefiningRecipe()
+ ->getOperand(0)
+ ->getDefiningRecipe()))
+ IV = WideIV;
+ else
+ IV = Incoming->getDefiningRecipe()->getOperand(1);
+ // Skip phi nodes already updated. This can be the case if 2 induction
+ // phis chase each other.
+ VPValue *EndValue = EndValues[IV];
+ if (any_of(cast<VPRecipeBase>(Incoming->getDefiningRecipe())->operands(),
+ IsaPred<VPWidenIntOrFpInductionRecipe,
+ VPWidenPointerInductionRecipe>)) {
+ ExitIRI->setOperand(0, EndValue);
+ return true;
+ }
+
+ VPBuilder B(Plan.getMiddleBlock()->getTerminator());
+ VPValue *Escape = nullptr;
+ auto *WideIV = cast<VPWidenInductionRecipe>(IV->getDefiningRecipe());
+ VPValue *Step = WideIV->getStepValue();
+ Type *ScalarTy = TypeInfo.inferScalarType(WideIV);
+ if (ScalarTy->isIntegerTy())
+ Escape =
+ B.createNaryOp(Instruction::Sub, {EndValue, Step}, {}, "ind.escape");
+ else if (ScalarTy->isPointerTy())
+ Escape = B.createPtrAdd(
+ EndValue,
+ B.createNaryOp(Instruction::Sub,
+ {Plan.getOrAddLiveIn(ConstantInt::get(
+ Step->getLiveInIRValue()->getType(), 0)),
+ Step}),
+ {}, "ind.escape");
+ else if (ScalarTy->isFloatingPointTy()) {
+ const auto &ID = WideIV->getInductionDescriptor();
+ Escape = B.createNaryOp(
+ ID.getInductionBinOp()->getOpcode() == Instruction::FAdd
+ ? Instruction::FSub
+ : Instruction::FAdd,
+ {EndValue, Step}, {ID.getInductionBinOp()->getFastMathFlags()});
+ } else {
+ llvm_unreachable("all possible induction types must be handled");
+ }
+ ExitIRI->setOperand(0, Escape);
+ return true;
+ }
+ return false;
+}
// Add exit values to \p Plan. Extracts are added for each entry in \p
// ExitUsersToFix if needed and their operands are updated. Returns true if all
// exit users can be handled, otherwise return false.
----------------
ayalz wrote:
Explain role of EndValues?
https://github.com/llvm/llvm-project/pull/112147
More information about the llvm-commits
mailing list