[llvm] 6cc18a8 - [VPlan] Support more GEP-like recipes in getSCEVExprForVPValue (NFCI)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 18 14:21:48 PST 2026


Author: Florian Hahn
Date: 2026-01-18T22:20:25Z
New Revision: 6cc18a8e4338dbbeb29b4a57af89e0cc0aca7be9

URL: https://github.com/llvm/llvm-project/commit/6cc18a8e4338dbbeb29b4a57af89e0cc0aca7be9
DIFF: https://github.com/llvm/llvm-project/commit/6cc18a8e4338dbbeb29b4a57af89e0cc0aca7be9.diff

LOG: [VPlan] Support more GEP-like recipes in getSCEVExprForVPValue (NFCI)

Support VPWidenGEPRecipe, VPInstructions and VPRelpicateRecipe with
GEP-like opcodes in getSCEVExprForVPValue via a new matcher binding
source element type and operands.

This is used in code paths when computing SCEV expressions in the
VPlan-based cost model, which should produce costs matching the legacy
cost model.

Added: 
    

Modified: 
    llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
    llvm/lib/Transforms/Vectorize/VPlanUtils.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
index 148ee4119f372..09c3722961246 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
@@ -963,6 +963,56 @@ struct live_in_vpvalue {
 
 inline live_in_vpvalue m_LiveIn() { return live_in_vpvalue(); }
 
+/// Match a GEP recipe (VPWidenGEPRecipe, VPInstruction, or VPReplicateRecipe)
+/// and bind the source element type and operands.
+struct GetElementPtr_match {
+  Type *&SourceElementType;
+  ArrayRef<VPValue *> &Operands;
+
+  GetElementPtr_match(Type *&SourceElementType, ArrayRef<VPValue *> &Operands)
+      : SourceElementType(SourceElementType), Operands(Operands) {}
+
+  template <typename ITy> bool match(ITy *V) const {
+    return matchRecipeAndBind<VPWidenGEPRecipe>(V) ||
+           matchRecipeAndBind<VPInstruction>(V) ||
+           matchRecipeAndBind<VPReplicateRecipe>(V);
+  }
+
+private:
+  template <typename RecipeTy> bool matchRecipeAndBind(const VPValue *V) const {
+    auto *DefR = dyn_cast<RecipeTy>(V);
+    if (!DefR)
+      return false;
+
+    if constexpr (std::is_same_v<RecipeTy, VPWidenGEPRecipe>) {
+      SourceElementType = DefR->getSourceElementType();
+    } else if (DefR->getOpcode() == Instruction::GetElementPtr) {
+      SourceElementType = cast<GetElementPtrInst>(DefR->getUnderlyingInstr())
+                              ->getSourceElementType();
+    } else if constexpr (std::is_same_v<RecipeTy, VPInstruction>) {
+      if (DefR->getOpcode() == VPInstruction::PtrAdd) {
+        // PtrAdd is a byte-offset GEP with i8 element type.
+        LLVMContext &Ctx = DefR->getParent()->getPlan()->getContext();
+        SourceElementType = Type::getInt8Ty(Ctx);
+      } else {
+        return false;
+      }
+    } else {
+      return false;
+    }
+
+    Operands = ArrayRef<VPValue *>(DefR->op_begin(), DefR->op_end());
+    return true;
+  }
+};
+
+/// Match a GEP recipe with any number of operands and bind source element type
+/// and operands.
+inline GetElementPtr_match m_GetElementPtr(Type *&SourceElementType,
+                                           ArrayRef<VPValue *> &Operands) {
+  return GetElementPtr_match(SourceElementType, Operands);
+}
+
 template <typename SubPattern_t> struct OneUse_match {
   SubPattern_t SubPattern;
 

diff  --git a/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp b/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
index 795d137a3f47c..4873075a771c4 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
@@ -234,6 +234,15 @@ const SCEV *vputils::getSCEVExprForVPValue(const VPValue *V,
       return SE.getSMinExpr(Ops[0], Ops[1]);
     });
 
+  ArrayRef<VPValue *> Ops;
+  Type *SourceElementType;
+  if (match(V, m_GetElementPtr(SourceElementType, Ops))) {
+    const SCEV *GEPExpr = CreateSCEV(Ops, [&](ArrayRef<const SCEV *> Ops) {
+      return SE.getGEPExpr(Ops.front(), Ops.drop_front(), SourceElementType);
+    });
+    return PSE.getPredicatedSCEV(GEPExpr);
+  }
+
   // TODO: Support constructing SCEVs for more recipes as needed.
   const VPRecipeBase *DefR = V->getDefiningRecipe();
   const SCEV *Expr = TypeSwitch<const VPRecipeBase *, const SCEV *>(DefR)
@@ -279,26 +288,6 @@ const SCEV *vputils::getSCEVExprForVPValue(const VPValue *V,
           return SE.getCouldNotCompute();
         return SE.getTruncateOrSignExtend(IV, Step->getType());
       })
-      .Case<VPReplicateRecipe>([&SE, &PSE, L](const VPReplicateRecipe *R) {
-        if (R->getOpcode() != Instruction::GetElementPtr)
-          return SE.getCouldNotCompute();
-
-        const SCEV *Base = getSCEVExprForVPValue(R->getOperand(0), PSE, L);
-        if (isa<SCEVCouldNotCompute>(Base))
-          return SE.getCouldNotCompute();
-
-        SmallVector<const SCEV *> IndexExprs;
-        for (VPValue *Index : drop_begin(R->operands())) {
-          const SCEV *IndexExpr = getSCEVExprForVPValue(Index, PSE, L);
-          if (isa<SCEVCouldNotCompute>(IndexExpr))
-            return SE.getCouldNotCompute();
-          IndexExprs.push_back(IndexExpr);
-        }
-
-        Type *SrcElementTy = cast<GetElementPtrInst>(R->getUnderlyingInstr())
-                                 ->getSourceElementType();
-        return SE.getGEPExpr(Base, IndexExprs, SrcElementTy);
-      })
       .Default(
           [&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); });
 


        


More information about the llvm-commits mailing list