[llvm] [VPlan] Get GEP wrap flags from VPInstructions (NFCI). (PR #195730)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Mon May 4 13:58:26 PDT 2026
https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/195730
>From f7e9e95f082f1a8176e69ee0b27e9fa02769076f Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Fri, 1 May 2026 20:39:53 +0100
Subject: [PATCH] [VPlan] Get GEP wrap flags from VPInstructions (NFCI).
Add helper to retrieve GEP no-wrap flags from VPInstructions, looking
through zero-index GEPs and pointer casts, like Value::stripPointerCasts.
Removes an access to underlying IR.
---
.../Transforms/Vectorize/LoopVectorize.cpp | 16 ++++++----------
llvm/lib/Transforms/Vectorize/VPlanUtils.cpp | 19 +++++++++++++++++++
llvm/lib/Transforms/Vectorize/VPlanUtils.h | 4 ++++
3 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 78163b5fe35d5..ebbaec83fdc6b 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -6423,25 +6423,21 @@ VPRecipeBase *VPRecipeBuilder::tryToWidenMemory(VPInstruction *VPI,
VPValue *Ptr = VPI->getOpcode() == Instruction::Load ? VPI->getOperand(0)
: VPI->getOperand(1);
if (Consecutive) {
- auto *GEP = dyn_cast<GetElementPtrInst>(
- Ptr->getUnderlyingValue()->stripPointerCasts());
+ GEPNoWrapFlags Flags = vputils::getGEPFlagsForPtr(Ptr);
VPSingleDefRecipe *VectorPtr;
if (Reverse) {
// When folding the tail, we may compute an address that we don't in the
// original scalar loop: drop the GEP no-wrap flags in this case.
// Otherwise preserve existing flags without no-unsigned-wrap, as we will
// emit negative indices.
- GEPNoWrapFlags Flags =
- CM.foldTailByMasking() || !GEP
- ? GEPNoWrapFlags::none()
- : GEP->getNoWrapFlags().withoutNoUnsignedWrap();
+ GEPNoWrapFlags ReverseFlags = CM.foldTailByMasking()
+ ? GEPNoWrapFlags::none()
+ : Flags.withoutNoUnsignedWrap();
VectorPtr = new VPVectorEndPointerRecipe(
Ptr, &Plan.getVF(), getLoadStoreType(I),
- /*Stride*/ -1, Flags, VPI->getDebugLoc());
+ /*Stride*/ -1, ReverseFlags, VPI->getDebugLoc());
} else {
- VectorPtr = new VPVectorPointerRecipe(Ptr, getLoadStoreType(I),
- GEP ? GEP->getNoWrapFlags()
- : GEPNoWrapFlags::none(),
+ VectorPtr = new VPVectorPointerRecipe(Ptr, getLoadStoreType(I), Flags,
VPI->getDebugLoc());
}
Builder.setInsertPoint(VPI);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp b/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
index a60b490a69ce6..af25df3965773 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
@@ -138,6 +138,25 @@ static bool poisonGuaranteesUB(const VPValue *V) {
return false;
}
+GEPNoWrapFlags vputils::getGEPFlagsForPtr(VPValue *Ptr) {
+ // Like IR stripPointerCasts, look through GEPs with all-zero indices and
+ // casts to find a root GEP VPInstruction.
+ while (auto *PtrVPI = dyn_cast<VPInstruction>(Ptr)) {
+ unsigned Opcode = PtrVPI->getOpcode();
+ if (Opcode == Instruction::GetElementPtr) {
+ if (any_of(drop_begin(PtrVPI->operands()),
+ [](VPValue *Op) { return !match(Op, m_ZeroInt()); }))
+ return PtrVPI->getGEPNoWrapFlags();
+ Ptr = PtrVPI->getOperand(0);
+ continue;
+ }
+ if (Opcode != Instruction::BitCast && Opcode != Instruction::AddrSpaceCast)
+ break;
+ Ptr = PtrVPI->getOperand(0);
+ }
+ return GEPNoWrapFlags::none();
+}
+
const SCEV *vputils::getSCEVExprForVPValue(const VPValue *V,
PredicatedScalarEvolution &PSE,
const Loop *L) {
diff --git a/llvm/lib/Transforms/Vectorize/VPlanUtils.h b/llvm/lib/Transforms/Vectorize/VPlanUtils.h
index cf54b2b6ac963..ac3a1005c8f24 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUtils.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanUtils.h
@@ -155,6 +155,10 @@ template <typename RecipeTy> static RecipeTy *findUserOf(VPValue *V) {
/// nullptr if not found.
VPInstruction *findCanonicalIVIncrement(VPlan &Plan);
+/// Returns the GEP nowrap flags for \p Ptr, looking through pointer casts
+/// mirroring Value::stripPointerCasts.
+GEPNoWrapFlags getGEPFlagsForPtr(VPValue *Ptr);
+
/// Find the ComputeReductionResult recipe for \p PhiR, looking through selects
/// inserted for predicated reductions or tail folding.
VPInstruction *findComputeReductionResult(VPReductionPHIRecipe *PhiR);
More information about the llvm-commits
mailing list