From 4774756c010b247076f1801e27d8017a849575f6 Mon Sep 17 00:00:00 2001 From: Florian Hahn 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 &IndexExprs); + LLVM_ABI const SCEV *getGEPExpr( + const SCEV *BaseExpr, const SmallVectorImpl &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 &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 &IndexExprs, + Type *SrcElementTy, SCEV::NoWrapFlags OffsetWrap) { + Type *CurTy = BaseExpr->getType(); + Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType()); bool FirstIter = true; SmallVector Offsets; for (const SCEV *IndexExpr : IndexExprs) { @@ -3812,7 +3820,7 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP, if (FirstIter) { assert(isa(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 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 &IndexExprs); - LLVM_ABI const SCEV *getGEPExpr( - const SCEV *BaseExpr, const SmallVectorImpl &IndexExprs, - Type *SrcElementTy, SCEV::NoWrapFlags OffsetWrap = SCEV::FlagAnyWrap); + LLVM_ABI const SCEV *getGEPExpr(GEPOperator *GEP, + ArrayRef IndexExprs); + LLVM_ABI const SCEV *getGEPExpr(const SCEV *BaseExpr, + ArrayRef 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 &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 &Operands, return getOrCreateAddRecExpr(Operands, L, Flags); } -const SCEV * -ScalarEvolution::getGEPExpr(GEPOperator *GEP, - const SmallVectorImpl &IndexExprs) { +const SCEV *ScalarEvolution::getGEPExpr(GEPOperator *GEP, + ArrayRef 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 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 &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() &&