[llvm] [VPlan] Guard VPPartialReductionRecipe::computeCost() against ilist sentinel(#148389) (PR #148555)

Shashi Shankar via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 13 16:21:45 PDT 2025


https://github.com/shashi1687 created https://github.com/llvm/llvm-project/pull/148555

`VPValue::getDefiningRecipe()` can return the ilist sentinel for live-in
values.  Dereferencing that sentinel trips the “dyn_cast on a non-existent
value” assertion (PR #148389).

* Collapse sentinel → nullptr with a small helper.
* Replace plain `isa`/`dyn_cast` with `isa_and_present` / `dyn_cast_if_present`.
* Keep old behaviour for non-sentinel recipes, so the chosen VF doesn’t change.

Added lit test `Transforms/LoopVectorize/pr148389-sentinel.ll`.

Fixes: #148389

>From f8905edecb1a3a304136edbc055e057d6858524f Mon Sep 17 00:00:00 2001
From: Shashi Shankar <shashishankar1687 at gmail.com>
Date: Mon, 14 Jul 2025 01:16:51 +0200
Subject: [PATCH] [VPlan] Guard VPPartialReductionRecipe::computeCost against
 ilist sentinel (#148389)

---
 .../lib/Transforms/Vectorize/VPlanRecipes.cpp | 30 ++++++++++++-------
 .../LoopVectorize/PR148389-sentinel.ll        | 27 +++++++++++++++++
 2 files changed, 46 insertions(+), 11 deletions(-)
 create mode 100644 llvm/test/Transforms/LoopVectorize/PR148389-sentinel.ll

diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 3c367664a0988..fc918c669df12 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -296,24 +296,32 @@ bool VPRecipeBase::isScalarCast() const {
 InstructionCost
 VPPartialReductionRecipe::computeCost(ElementCount VF,
                                       VPCostContext &Ctx) const {
+  // -----------------------------------------------------------------------
+  // Helpers that treat an ilist *sentinel* exactly like `nullptr`.
+  // -----------------------------------------------------------------------
+  auto safe = [](VPRecipeBase *R) -> VPRecipeBase * {
+    return isa_and_present<VPRecipeBase>(R) ? R : nullptr;
+   };
+
   std::optional<unsigned> Opcode;
-  VPValue *Op = getOperand(0);
-  VPRecipeBase *OpR = Op->getDefiningRecipe();
+  VPValue       *Op  = getOperand(0);
+  VPRecipeBase  *OpR = safe(Op->getDefiningRecipe());
 
   // If the partial reduction is predicated, a select will be operand 0
   using namespace llvm::VPlanPatternMatch;
   if (match(getOperand(1), m_Select(m_VPValue(), m_VPValue(Op), m_VPValue()))) {
-    OpR = Op->getDefiningRecipe();
+    OpR = safe(Op->getDefiningRecipe());
   }
 
   Type *InputTypeA = nullptr, *InputTypeB = nullptr;
   TTI::PartialReductionExtendKind ExtAType = TTI::PR_None,
                                   ExtBType = TTI::PR_None;
 
-  auto GetExtendKind = [](VPRecipeBase *R) {
+  auto GetExtendKind = [&](VPRecipeBase *R) {
+    R = safe(R);
     if (!R)
       return TTI::PR_None;
-    auto *WidenCastR = dyn_cast<VPWidenCastRecipe>(R);
+    auto *WidenCastR = dyn_cast_if_present<VPWidenCastRecipe>(R);
     if (!WidenCastR)
       return TTI::PR_None;
     if (WidenCastR->getOpcode() == Instruction::CastOps::ZExt)
@@ -328,11 +336,11 @@ VPPartialReductionRecipe::computeCost(ElementCount VF,
   auto HandleWiden = [&](VPWidenRecipe *Widen) {
     if (match(Widen,
               m_Binary<Instruction::Sub>(m_SpecificInt(0), m_VPValue(Op)))) {
-      Widen = dyn_cast<VPWidenRecipe>(Op->getDefiningRecipe());
+      Widen = dyn_cast_if_present<VPWidenRecipe>(safe(Op->getDefiningRecipe()));
     }
     Opcode = Widen->getOpcode();
-    VPRecipeBase *ExtAR = Widen->getOperand(0)->getDefiningRecipe();
-    VPRecipeBase *ExtBR = Widen->getOperand(1)->getDefiningRecipe();
+    VPRecipeBase *ExtAR = safe(Widen->getOperand(0)->getDefiningRecipe());
+    VPRecipeBase *ExtBR = safe(Widen->getOperand(1)->getDefiningRecipe());
     InputTypeA = Ctx.Types.inferScalarType(ExtAR ? ExtAR->getOperand(0)
                                                  : Widen->getOperand(0));
     InputTypeB = Ctx.Types.inferScalarType(ExtBR ? ExtBR->getOperand(0)
@@ -341,7 +349,7 @@ VPPartialReductionRecipe::computeCost(ElementCount VF,
     ExtBType = GetExtendKind(ExtBR);
   };
 
-  if (isa<VPWidenCastRecipe>(OpR)) {
+  if (isa_and_present<VPWidenCastRecipe>(OpR)) {
     InputTypeA = Ctx.Types.inferScalarType(OpR->getOperand(0));
     ExtAType = GetExtendKind(OpR);
   } else if (isa<VPReductionPHIRecipe>(OpR)) {
@@ -351,9 +359,9 @@ VPPartialReductionRecipe::computeCost(ElementCount VF,
       ExtAType = GetExtendKind(RedPhiOp1R);
     } else if (auto Widen = dyn_cast<VPWidenRecipe>(RedPhiOp1R))
       HandleWiden(Widen);
-  } else if (auto Widen = dyn_cast<VPWidenRecipe>(OpR)) {
+  } else if (auto Widen = dyn_cast_if_present<VPWidenRecipe>(OpR)) {
     HandleWiden(Widen);
-  } else if (auto Reduction = dyn_cast<VPPartialReductionRecipe>(OpR)) {
+  } else if (auto Reduction = dyn_cast_if_present<VPReductionRecipe>(OpR)) {
     return Reduction->computeCost(VF, Ctx);
   }
   auto *PhiType = Ctx.Types.inferScalarType(getOperand(1));
diff --git a/llvm/test/Transforms/LoopVectorize/PR148389-sentinel.ll b/llvm/test/Transforms/LoopVectorize/PR148389-sentinel.ll
new file mode 100644
index 0000000000000..d0c7392302275
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/PR148389-sentinel.ll
@@ -0,0 +1,27 @@
+; RUN: opt -passes=loop-vectorize -mcpu=grace -S %s -o /dev/null
+; REQUIRES: aarch64-registered-target
+
+; Reduced from GitHub issue #148389.
+; The test just needs to run – if the pass crashes the test will fail.
+
+define void @h(ptr %e, ptr %f, i8 %d) {
+entry:
+  br label %body
+body:
+  %i   = phi i16 [0, %entry], [%inc, %latch]
+  %idx = sext i16 %i to i64
+  %eelt = getelementptr [1 x i16], ptr %e, i64 %idx, i64 %idx
+  %eval = load i16, ptr %eelt
+  %felt = getelementptr [7 x i8],  ptr %f, i64 %idx, i64 %idx
+  %fval = load i8,  ptr %felt
+  %cmp  = icmp eq i8 %d, 0
+  br i1 %cmp, label %update, label %latch
+update:
+  br label %latch
+latch:
+  %inc  = add nuw nsw i16 %i, 1
+  %exit = icmp eq i16 %inc, 17
+  br i1 %exit, label %exit.block, label %body
+exit.block:
+  ret void
+}



More information about the llvm-commits mailing list