[llvm] [VPlan] Simplify WidenGEP::execute (NFC) (PR #193543)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 30 02:19:12 PDT 2026


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/193543

>From 917c2bcc6586872d7f75f12b1167def4cdcdc416 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Wed, 22 Apr 2026 18:05:07 +0100
Subject: [PATCH] [VPlan] Simplify WidenGEP::execute (NFC)

Simplify WidenGEP::execute in a non-functional way. In particular,
broadcasts are automatically inserted now, and VF cannot be scalar due
to the assert on top.
---
 llvm/lib/Transforms/Vectorize/VPlan.h         |  8 ---
 .../lib/Transforms/Vectorize/VPlanRecipes.cpp | 65 +++++--------------
 2 files changed, 16 insertions(+), 57 deletions(-)

diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index da9f9965b75ce..71643bff12a05 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -2087,14 +2087,6 @@ class VPHistogramRecipe : public VPRecipeBase {
 class LLVM_ABI_FOR_TEST VPWidenGEPRecipe : public VPRecipeWithIRFlags {
   Type *SourceElementTy;
 
-  bool isPointerLoopInvariant() const {
-    return getOperand(0)->isDefinedOutsideLoopRegions();
-  }
-
-  bool isIndexLoopInvariant(unsigned I) const {
-    return getOperand(I + 1)->isDefinedOutsideLoopRegions();
-  }
-
 public:
   VPWidenGEPRecipe(GetElementPtrInst *GEP, ArrayRef<VPValue *> Operands,
                    const VPIRFlags &Flags = {},
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index fd8aae55bc45a..2539f4564d00f 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -2621,65 +2621,32 @@ bool VPWidenGEPRecipe::usesFirstLaneOnly(const VPValue *Op) const {
 
 void VPWidenGEPRecipe::execute(VPTransformState &State) {
   assert(State.VF.isVector() && "not widening");
-  // Construct a vector GEP by widening the operands of the scalar GEP as
-  // necessary. We mark the vector GEP 'inbounds' if appropriate. A GEP
-  // results in a vector of pointers when at least one operand of the GEP
-  // is vector-typed. Thus, to keep the representation compact, we only use
-  // vector-typed operands for loop-varying values.
-
+  auto Ops = to_vector(map_range(operands(), [&](VPValue *Op) {
+    return State.get(Op, Op->isDefinedOutsideLoopRegions());
+  }));
+  auto *GEP = State.Builder.CreateGEP(getSourceElementType(), Ops.front(),
+                                      drop_begin(Ops), "", getGEPNoWrapFlags());
   bool AllOperandsAreInvariant = all_of(operands(), [](VPValue *Op) {
     return Op->isDefinedOutsideLoopRegions();
   });
-  if (AllOperandsAreInvariant) {
-    // If we are vectorizing, but the GEP has only loop-invariant operands,
-    // the GEP we build (by only using vector-typed operands for
-    // loop-varying values) would be a scalar pointer. Thus, to ensure we
-    // produce a vector of pointers, we need to either arbitrarily pick an
-    // operand to broadcast, or broadcast a clone of the original GEP.
-    // Here, we broadcast a clone of the original.
-
-    SmallVector<Value *> Ops;
-    for (unsigned I = 0, E = getNumOperands(); I != E; I++)
-      Ops.push_back(State.get(getOperand(I), VPLane(0)));
-
-    auto *NewGEP =
-        State.Builder.CreateGEP(getSourceElementType(), Ops[0], drop_begin(Ops),
-                                "", getGEPNoWrapFlags());
-    Value *Splat = State.Builder.CreateVectorSplat(State.VF, NewGEP);
-    State.set(this, Splat);
-    return;
-  }
-
-  // If the GEP has at least one loop-varying operand, we are sure to
-  // produce a vector of pointers unless VF is scalar.
-  // The pointer operand of the new GEP. If it's loop-invariant, we
-  // won't broadcast it.
-  auto *Ptr = State.get(getOperand(0), isPointerLoopInvariant());
-
-  // Collect all the indices for the new GEP. If any index is
-  // loop-invariant, we won't broadcast it.
-  SmallVector<Value *, 4> Indices;
-  for (unsigned I = 1, E = getNumOperands(); I < E; I++) {
-    VPValue *Operand = getOperand(I);
-    Indices.push_back(State.get(Operand, isIndexLoopInvariant(I - 1)));
-  }
-
-  // Create the new GEP. Note that this GEP may be a scalar if VF == 1,
-  // but it should be a vector, otherwise.
-  auto *NewGEP = State.Builder.CreateGEP(getSourceElementType(), Ptr, Indices,
-                                         "", getGEPNoWrapFlags());
-  assert((State.VF.isScalar() || NewGEP->getType()->isVectorTy()) &&
-         "NewGEP is not a pointer vector");
-  State.set(this, NewGEP);
+  assert((AllOperandsAreInvariant || GEP->getType()->isVectorTy()) &&
+         "GEP expected to be of vector type except when all operands are "
+         "invariant");
+  State.set(this, GEP, AllOperandsAreInvariant);
 }
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 void VPWidenGEPRecipe::printRecipe(raw_ostream &O, const Twine &Indent,
                                    VPSlotTracker &SlotTracker) const {
+  bool IsPointerLoopInvariant = getOperand(0)->isDefinedOutsideLoopRegions();
+  auto IsIndexLoopInvariant = [this](unsigned I) {
+    return getOperand(I + 1)->isDefinedOutsideLoopRegions();
+  };
+
   O << Indent << "WIDEN-GEP ";
-  O << (isPointerLoopInvariant() ? "Inv" : "Var");
+  O << (IsPointerLoopInvariant ? "Inv" : "Var");
   for (size_t I = 0; I < getNumOperands() - 1; ++I)
-    O << "[" << (isIndexLoopInvariant(I) ? "Inv" : "Var") << "]";
+    O << "[" << (IsIndexLoopInvariant(I) ? "Inv" : "Var") << "]";
 
   O << " ";
   printAsOperand(O, SlotTracker);



More information about the llvm-commits mailing list