[llvm] [VPlan] Simplify WidenGEP::execute (NFC) (PR #193543)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 30 02:56:22 PDT 2026
================
@@ -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()) &&
----------------
fhahn wrote:
I think in the past there was an attempt to remove the AllOperandsAreInvariant path altogether. what are the cases we fail to hoist it out of the loop if all operands are invariant?
https://github.com/llvm/llvm-project/pull/193543
More information about the llvm-commits
mailing list