[llvm] [SCEV] Expose getGEPExpr without needing to pass GEPOperator* (NFC) (PR #164487)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 22 01:53:50 PDT 2025
https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/164487
>From 4774756c010b247076f1801e27d8017a849575f6 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 21 Oct 2025 20:55:31 +0100
Subject: [PATCH 1/2] [SCEV] Expose getGEPExpr without needing to pass
GEPOperator* (NFC)
Add a new getGEPExpr variant which is independent of GEPOperator*.
To be used to construct SCEVs for VPlan recipes in
https://github.com/llvm/llvm-project/pull/161276.
---
llvm/include/llvm/Analysis/ScalarEvolution.h | 3 +++
llvm/lib/Analysis/ScalarEvolution.cpp | 19 ++++++++++++++-----
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 3d3ec14796bc1..c419aed107464 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -640,6 +640,9 @@ class ScalarEvolution {
/// \p IndexExprs The expressions for the indices.
LLVM_ABI const SCEV *
getGEPExpr(GEPOperator *GEP, const SmallVectorImpl<const SCEV *> &IndexExprs);
+ LLVM_ABI const SCEV *getGEPExpr(
+ const SCEV *BaseExpr, const SmallVectorImpl<const SCEV *> &IndexExprs,
+ Type *SrcElementTy, SCEV::NoWrapFlags OffsetWrap = SCEV::FlagAnyWrap);
LLVM_ABI const SCEV *getAbsExpr(const SCEV *Op, bool IsNSW);
LLVM_ABI const SCEV *getMinMaxExpr(SCEVTypes Kind,
SmallVectorImpl<const SCEV *> &Operands);
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 6f7dd79032cfe..4856c51ee2a4a 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -3774,7 +3774,6 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
const SCEV *BaseExpr = getSCEV(GEP->getPointerOperand());
// getSCEV(Base)->getType() has the same address space as Base->getType()
// because SCEV::getType() preserves the address space.
- Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType());
GEPNoWrapFlags NW = GEP->getNoWrapFlags();
if (NW != GEPNoWrapFlags::none()) {
// We'd like to propagate flags from the IR to the corresponding SCEV nodes,
@@ -3793,7 +3792,16 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
if (NW.hasNoUnsignedWrap())
OffsetWrap = setFlags(OffsetWrap, SCEV::FlagNUW);
- Type *CurTy = GEP->getType();
+ return getGEPExpr(BaseExpr, IndexExprs, GEP->getSourceElementType(),
+ OffsetWrap);
+}
+
+const SCEV *
+ScalarEvolution::getGEPExpr(const SCEV *BaseExpr,
+ const SmallVectorImpl<const SCEV *> &IndexExprs,
+ Type *SrcElementTy, SCEV::NoWrapFlags OffsetWrap) {
+ Type *CurTy = BaseExpr->getType();
+ Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType());
bool FirstIter = true;
SmallVector<const SCEV *, 4> Offsets;
for (const SCEV *IndexExpr : IndexExprs) {
@@ -3812,7 +3820,7 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
if (FirstIter) {
assert(isa<PointerType>(CurTy) &&
"The first index of a GEP indexes a pointer");
- CurTy = GEP->getSourceElementType();
+ CurTy = SrcElementTy;
FirstIter = false;
} else {
CurTy = GetElementPtrInst::getTypeAtIndex(CurTy, (uint64_t)0);
@@ -3837,8 +3845,9 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
// Add the base address and the offset. We cannot use the nsw flag, as the
// base address is unsigned. However, if we know that the offset is
// non-negative, we can use nuw.
- bool NUW = NW.hasNoUnsignedWrap() ||
- (NW.hasNoUnsignedSignedWrap() && isKnownNonNegative(Offset));
+ bool NUW =
+ hasFlags(OffsetWrap, SCEV::FlagNUW) ||
+ (hasFlags(OffsetWrap, SCEV::FlagNSW) && isKnownNonNegative(Offset));
SCEV::NoWrapFlags BaseWrap = NUW ? SCEV::FlagNUW : SCEV::FlagAnyWrap;
auto *GEPExpr = getAddExpr(BaseExpr, Offset, BaseWrap);
assert(BaseExpr->getType() == GEPExpr->getType() &&
>From 790ea77bd14f10ceb2066fe707b29db92bd75de6 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 22 Oct 2025 09:49:33 +0100
Subject: [PATCH 2/2] !fixup pass GEPNoWrapFlags
---
llvm/include/llvm/Analysis/ScalarEvolution.h | 11 +++++----
llvm/lib/Analysis/ScalarEvolution.cpp | 24 ++++++++------------
2 files changed, 16 insertions(+), 19 deletions(-)
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index c419aed107464..04ea769bd06d1 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -638,11 +638,12 @@ class ScalarEvolution {
/// \p GEP The GEP. The indices contained in the GEP itself are ignored,
/// instead we use IndexExprs.
/// \p IndexExprs The expressions for the indices.
- LLVM_ABI const SCEV *
- getGEPExpr(GEPOperator *GEP, const SmallVectorImpl<const SCEV *> &IndexExprs);
- LLVM_ABI const SCEV *getGEPExpr(
- const SCEV *BaseExpr, const SmallVectorImpl<const SCEV *> &IndexExprs,
- Type *SrcElementTy, SCEV::NoWrapFlags OffsetWrap = SCEV::FlagAnyWrap);
+ LLVM_ABI const SCEV *getGEPExpr(GEPOperator *GEP,
+ ArrayRef<const SCEV *> IndexExprs);
+ LLVM_ABI const SCEV *getGEPExpr(const SCEV *BaseExpr,
+ ArrayRef<const SCEV *> IndexExprs,
+ Type *SrcElementTy,
+ GEPNoWrapFlags NW = GEPNoWrapFlags::none());
LLVM_ABI const SCEV *getAbsExpr(const SCEV *Op, bool IsNSW);
LLVM_ABI const SCEV *getMinMaxExpr(SCEVTypes Kind,
SmallVectorImpl<const SCEV *> &Operands);
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 4856c51ee2a4a..7597f3ad685a0 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -3768,9 +3768,8 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
return getOrCreateAddRecExpr(Operands, L, Flags);
}
-const SCEV *
-ScalarEvolution::getGEPExpr(GEPOperator *GEP,
- const SmallVectorImpl<const SCEV *> &IndexExprs) {
+const SCEV *ScalarEvolution::getGEPExpr(GEPOperator *GEP,
+ ArrayRef<const SCEV *> IndexExprs) {
const SCEV *BaseExpr = getSCEV(GEP->getPointerOperand());
// getSCEV(Base)->getType() has the same address space as Base->getType()
// because SCEV::getType() preserves the address space.
@@ -3786,20 +3785,18 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
NW = GEPNoWrapFlags::none();
}
+ return getGEPExpr(BaseExpr, IndexExprs, GEP->getSourceElementType(), NW);
+}
+
+const SCEV *ScalarEvolution::getGEPExpr(const SCEV *BaseExpr,
+ ArrayRef<const SCEV *> IndexExprs,
+ Type *SrcElementTy, GEPNoWrapFlags NW) {
SCEV::NoWrapFlags OffsetWrap = SCEV::FlagAnyWrap;
if (NW.hasNoUnsignedSignedWrap())
OffsetWrap = setFlags(OffsetWrap, SCEV::FlagNSW);
if (NW.hasNoUnsignedWrap())
OffsetWrap = setFlags(OffsetWrap, SCEV::FlagNUW);
- return getGEPExpr(BaseExpr, IndexExprs, GEP->getSourceElementType(),
- OffsetWrap);
-}
-
-const SCEV *
-ScalarEvolution::getGEPExpr(const SCEV *BaseExpr,
- const SmallVectorImpl<const SCEV *> &IndexExprs,
- Type *SrcElementTy, SCEV::NoWrapFlags OffsetWrap) {
Type *CurTy = BaseExpr->getType();
Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType());
bool FirstIter = true;
@@ -3845,9 +3842,8 @@ ScalarEvolution::getGEPExpr(const SCEV *BaseExpr,
// Add the base address and the offset. We cannot use the nsw flag, as the
// base address is unsigned. However, if we know that the offset is
// non-negative, we can use nuw.
- bool NUW =
- hasFlags(OffsetWrap, SCEV::FlagNUW) ||
- (hasFlags(OffsetWrap, SCEV::FlagNSW) && isKnownNonNegative(Offset));
+ bool NUW = NW.hasNoUnsignedWrap() ||
+ (NW.hasNoUnsignedSignedWrap() && isKnownNonNegative(Offset));
SCEV::NoWrapFlags BaseWrap = NUW ? SCEV::FlagNUW : SCEV::FlagAnyWrap;
auto *GEPExpr = getAddExpr(BaseExpr, Offset, BaseWrap);
assert(BaseExpr->getType() == GEPExpr->getType() &&
More information about the llvm-commits
mailing list