[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