-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SCEV] Add option to request use-specific SCEV for a GEP expr (WIP). #91964
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/fhahn/scevuse
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-backend-arm @llvm/pr-subscribers-llvm-analysis Author: Florian Hahn (fhahn) ChangesUse SCEVUse from #91961 to return a SCEVUse with use-specific no-wrap flags for GEP expr, when demanded. Clients need to opt-in, as the use-specific flags may not be valid in some contexts (e.g. backedge taken counts). Full diff: https://github.com/llvm/llvm-project/pull/91964.diff 8 Files Affected:
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 2859df9964555..4ca3dbc1c6703 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -653,7 +653,7 @@ class ScalarEvolution {
/// Return a SCEV expression for the full generality of the specified
/// expression.
- SCEVUse getSCEV(Value *V);
+ SCEVUse getSCEV(Value *V, bool UseCtx = false);
/// Return an existing SCEV for V if there is one, otherwise return nullptr.
SCEVUse getExistingSCEV(Value *V);
@@ -735,9 +735,11 @@ 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.
- SCEVUse getGEPExpr(GEPOperator *GEP, ArrayRef<const SCEV *> IndexExprs);
+ SCEVUse getGEPExpr(GEPOperator *GEP, ArrayRef<const SCEV *> IndexExprs,
+ bool UseCtx = false);
SCEVUse getGEPExpr(GEPOperator *GEP,
- const SmallVectorImpl<SCEVUse> &IndexExprs);
+ const SmallVectorImpl<SCEVUse> &IndexExprs,
+ bool UseCtx = false);
SCEVUse getAbsExpr(SCEVUse Op, bool IsNSW);
SCEVUse getMinMaxExpr(SCEVTypes Kind, ArrayRef<const SCEV *> Operands);
SCEVUse getMinMaxExpr(SCEVTypes Kind, SmallVectorImpl<SCEVUse> &Operands);
@@ -1783,11 +1785,11 @@ class ScalarEvolution {
/// We know that there is no SCEV for the specified value. Analyze the
/// expression recursively.
- SCEVUse createSCEV(Value *V);
+ SCEVUse createSCEV(Value *V, bool UseCtx = false);
/// We know that there is no SCEV for the specified value. Create a new SCEV
/// for \p V iteratively.
- SCEVUse createSCEVIter(Value *V);
+ SCEVUse createSCEVIter(Value *V, bool UseCtx = false);
/// Collect operands of \p V for which SCEV expressions should be constructed
/// first. Returns a SCEV directly if it can be constructed trivially for \p
/// V.
@@ -1826,7 +1828,7 @@ class ScalarEvolution {
Value *FalseVal);
/// Provide the special handling we need to analyze GEP SCEVs.
- SCEVUse createNodeForGEP(GEPOperator *GEP);
+ SCEVUse createNodeForGEP(GEPOperator *GEP, bool UseCtx = false);
/// Implementation code for getSCEVAtScope; called at most once for each
/// SCEV+Loop pair.
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 320be6f26fc0a..68f4ddd47d69a 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -2741,6 +2741,8 @@ SCEVUse ScalarEvolution::getAddExpr(SmallVectorImpl<SCEVUse> &Ops,
break;
// If we have an add, expand the add operands onto the end of the operands
// list.
+ // CommonFlags = maskFlags(CommonFlags, setFlags(Add->getNoWrapFlags(),
+ // static_cast<SCEV::NoWrapFlags>(Ops[Idx].getInt())));
Ops.erase(Ops.begin()+Idx);
append_range(Ops, Add->operands());
DeletedAdd = true;
@@ -3759,13 +3761,14 @@ SCEVUse ScalarEvolution::getAddRecExpr(SmallVectorImpl<SCEVUse> &Operands,
}
SCEVUse ScalarEvolution::getGEPExpr(GEPOperator *GEP,
- ArrayRef<const SCEV *> IndexExprs) {
- return getGEPExpr(GEP, SmallVector<SCEVUse>(IndexExprs));
+ ArrayRef<const SCEV *> IndexExprs,
+ bool UseCtx) {
+ return getGEPExpr(GEP, SmallVector<SCEVUse>(IndexExprs), UseCtx);
}
-SCEVUse
-ScalarEvolution::getGEPExpr(GEPOperator *GEP,
- const SmallVectorImpl<SCEVUse> &IndexExprs) {
+SCEVUse ScalarEvolution::getGEPExpr(GEPOperator *GEP,
+ const SmallVectorImpl<SCEVUse> &IndexExprs,
+ bool UseCtx) {
SCEVUse BaseExpr = getSCEV(GEP->getPointerOperand());
// getSCEV(Base)->getType() has the same address space as Base->getType()
// because SCEV::getType() preserves the address space.
@@ -3835,6 +3838,9 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP,
auto GEPExpr = getAddExpr(BaseExpr, Offset, BaseWrap);
assert(BaseExpr->getType() == GEPExpr->getType() &&
"GEP should not change type mid-flight.");
+ if (UseCtx && BaseWrap != SCEV::FlagNUW && GEP->isInBounds() &&
+ isKnownNonNegative(Offset))
+ GEPExpr = SCEVUse(&*GEPExpr, 2);
return GEPExpr;
}
@@ -4587,12 +4593,12 @@ void ScalarEvolution::insertValueToMap(Value *V, SCEVUse S) {
/// Return an existing SCEV if it exists, otherwise analyze the expression and
/// create a new one.
-SCEVUse ScalarEvolution::getSCEV(Value *V) {
+SCEVUse ScalarEvolution::getSCEV(Value *V, bool UseCtx) {
assert(isSCEVable(V->getType()) && "Value is not SCEVable!");
if (SCEVUse S = getExistingSCEV(V))
return S;
- return createSCEVIter(V);
+ return createSCEVIter(V, UseCtx);
}
SCEVUse ScalarEvolution::getExistingSCEV(Value *V) {
@@ -6283,14 +6289,14 @@ SCEVUse ScalarEvolution::createNodeForSelectOrPHI(Value *V, Value *Cond,
/// Expand GEP instructions into add and multiply operations. This allows them
/// to be analyzed by regular SCEV code.
-SCEVUse ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
+SCEVUse ScalarEvolution::createNodeForGEP(GEPOperator *GEP, bool UseCtx) {
assert(GEP->getSourceElementType()->isSized() &&
"GEP source element type must be sized");
SmallVector<SCEVUse, 4> IndexExprs;
for (Value *Index : GEP->indices())
IndexExprs.push_back(getSCEV(Index));
- return getGEPExpr(GEP, IndexExprs);
+ return getGEPExpr(GEP, IndexExprs, UseCtx);
}
APInt ScalarEvolution::getConstantMultipleImpl(SCEVUse S) {
@@ -7440,7 +7446,7 @@ bool ScalarEvolution::loopIsFiniteByAssumption(const Loop *L) {
return isFinite(L) || (isMustProgress(L) && loopHasNoSideEffects(L));
}
-SCEVUse ScalarEvolution::createSCEVIter(Value *V) {
+SCEVUse ScalarEvolution::createSCEVIter(Value *V, bool UseCtx) {
// Worklist item with a Value and a bool indicating whether all operands have
// been visited already.
using PointerTy = PointerIntPair<Value *, 1, bool>;
@@ -7459,7 +7465,7 @@ SCEVUse ScalarEvolution::createSCEVIter(Value *V) {
SCEVUse CreatedSCEV = nullptr;
// If all operands have been visited already, create the SCEV.
if (E.getInt()) {
- CreatedSCEV = createSCEV(CurV);
+ CreatedSCEV = createSCEV(CurV, UseCtx);
} else {
// Otherwise get the operands we need to create SCEV's for before creating
// the SCEV for CurV. If the SCEV for CurV can be constructed trivially,
@@ -7668,7 +7674,7 @@ SCEVUse ScalarEvolution::getOperandsToCreate(Value *V,
return nullptr;
}
-SCEVUse ScalarEvolution::createSCEV(Value *V) {
+SCEVUse ScalarEvolution::createSCEV(Value *V, bool UseCtx) {
if (!isSCEVable(V->getType()))
return getUnknown(V);
@@ -8077,7 +8083,7 @@ SCEVUse ScalarEvolution::createSCEV(Value *V) {
break;
case Instruction::GetElementPtr:
- return createNodeForGEP(cast<GEPOperator>(U));
+ return createNodeForGEP(cast<GEPOperator>(U), UseCtx);
case Instruction::PHI:
return createNodeForPHI(cast<PHINode>(U));
@@ -13621,8 +13627,8 @@ void ScalarEvolution::print(raw_ostream &OS) const {
if (isSCEVable(I.getType()) && !isa<CmpInst>(I)) {
OS << I << '\n';
OS << " --> ";
- SCEVUse SV = SE.getSCEV(&I);
- SV->print(OS);
+ SCEVUse SV = SE.getSCEV(&I, /*UseCtx=*/true);
+ SV.print(OS);
if (!isa<SCEVCouldNotCompute>(SV)) {
OS << " U: ";
SE.getUnsignedRange(SV).print(OS);
diff --git a/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll b/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
index 6ededf2477711..a80c0f4ebc5ea 100644
--- a/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
+++ b/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
@@ -42,7 +42,7 @@ define void @f(ptr %A, i32 %N) {
; CHECK-NEXT: %tmp19 = select i1 %tmp14, i64 0, i64 %tmp17
; CHECK-NEXT: --> (-3 + (3 smax {0,+,1}<nuw><nsw><%bb1>))<nsw> U: [0,2147483645) S: [0,2147483645) Exits: (-3 + (3 smax (zext i32 (0 smax %N) to i64)))<nsw> LoopDispositions: { %bb1: Computable }
; CHECK-NEXT: %tmp21 = getelementptr inbounds i32, ptr %A, i64 %tmp19
-; CHECK-NEXT: --> (-12 + (4 * (3 smax {0,+,1}<nuw><nsw><%bb1>))<nuw><nsw> + %A) U: full-set S: full-set Exits: (-12 + (4 * (3 smax (zext i32 (0 smax %N) to i64)))<nuw><nsw> + %A) LoopDispositions: { %bb1: Computable }
+; CHECK-NEXT: --> (-12 + (4 * (3 smax {0,+,1}<nuw><nsw><%bb1>))<nuw><nsw> + %A)(u nuw) U: full-set S: full-set Exits: (-12 + (4 * (3 smax (zext i32 (0 smax %N) to i64)))<nuw><nsw> + %A) LoopDispositions: { %bb1: Computable }
; CHECK-NEXT: %tmp23 = add nuw nsw i32 %i.0, 1
; CHECK-NEXT: --> {1,+,1}<nuw><%bb1> U: [1,-2147483647) S: [1,-2147483647) Exits: (1 + (0 smax %N))<nuw> LoopDispositions: { %bb1: Computable }
; CHECK-NEXT: Determining loop execution counts for: @f
diff --git a/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll b/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
index bd2ffddf396fe..4e13de3a2a09c 100644
--- a/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
+++ b/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
@@ -209,11 +209,11 @@ define void @f3(ptr %x_addr, ptr %y_addr, ptr %tmp_addr) {
; CHECK-NEXT: %sunkaddr3 = mul i64 %add4.zext, 4
; CHECK-NEXT: --> (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> U: [0,17179869169) S: [0,17179869181)
; CHECK-NEXT: %sunkaddr4 = getelementptr inbounds i8, ptr @tmp_addr, i64 %sunkaddr3
-; CHECK-NEXT: --> ((4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT: --> ((4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %sunkaddr5 = getelementptr inbounds i8, ptr %sunkaddr4, i64 4096
-; CHECK-NEXT: --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT: --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %addr4.cast = bitcast ptr %sunkaddr5 to ptr
-; CHECK-NEXT: --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT: --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %addr4.incr = getelementptr i32, ptr %addr4.cast, i64 1
; CHECK-NEXT: --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %add5 = add i32 %mul, 5
@@ -223,11 +223,11 @@ define void @f3(ptr %x_addr, ptr %y_addr, ptr %tmp_addr) {
; CHECK-NEXT: %sunkaddr0 = mul i64 %add5.zext, 4
; CHECK-NEXT: --> (4 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw>)<nuw><nsw> U: [4,17179869173) S: [4,17179869185)
; CHECK-NEXT: %sunkaddr1 = getelementptr inbounds i8, ptr @tmp_addr, i64 %sunkaddr0
-; CHECK-NEXT: --> (4 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT: --> (4 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %sunkaddr2 = getelementptr inbounds i8, ptr %sunkaddr1, i64 4096
-; CHECK-NEXT: --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT: --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %addr5.cast = bitcast ptr %sunkaddr2 to ptr
-; CHECK-NEXT: --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
+; CHECK-NEXT: --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: Determining loop execution counts for: @f3
;
entry:
diff --git a/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll b/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll
index e13a8976bf5ac..20ebcd6158e98 100644
--- a/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll
+++ b/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll
@@ -96,7 +96,7 @@ define void @pointer_iv_nowrap(ptr %startptr, ptr %endptr) local_unnamed_addr {
; CHECK-LABEL: 'pointer_iv_nowrap'
; CHECK-NEXT: Classifying expressions for: @pointer_iv_nowrap
; CHECK-NEXT: %init = getelementptr inbounds i8, ptr %startptr, i64 2000
-; CHECK-NEXT: --> (2000 + %startptr) U: full-set S: full-set
+; CHECK-NEXT: --> (2000 + %startptr)(u nuw) U: full-set S: full-set
; CHECK-NEXT: %iv = phi ptr [ %init, %entry ], [ %iv.next, %loop ]
; CHECK-NEXT: --> {(2000 + %startptr),+,1}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %iv.next = getelementptr inbounds i8, ptr %iv, i64 1
diff --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
index e784d25385980..72f59682b023a 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
@@ -192,7 +192,7 @@ define void @ptrtoint_of_gep(ptr %in, ptr %out0) {
; X64-LABEL: 'ptrtoint_of_gep'
; X64-NEXT: Classifying expressions for: @ptrtoint_of_gep
; X64-NEXT: %in_adj = getelementptr inbounds i8, ptr %in, i64 42
-; X64-NEXT: --> (42 + %in) U: full-set S: full-set
+; X64-NEXT: --> (42 + %in)(u nuw) U: full-set S: full-set
; X64-NEXT: %p0 = ptrtoint ptr %in_adj to i64
; X64-NEXT: --> (42 + (ptrtoint ptr %in to i64)) U: full-set S: full-set
; X64-NEXT: Determining loop execution counts for: @ptrtoint_of_gep
@@ -200,7 +200,7 @@ define void @ptrtoint_of_gep(ptr %in, ptr %out0) {
; X32-LABEL: 'ptrtoint_of_gep'
; X32-NEXT: Classifying expressions for: @ptrtoint_of_gep
; X32-NEXT: %in_adj = getelementptr inbounds i8, ptr %in, i64 42
-; X32-NEXT: --> (42 + %in) U: full-set S: full-set
+; X32-NEXT: --> (42 + %in)(u nuw) U: full-set S: full-set
; X32-NEXT: %p0 = ptrtoint ptr %in_adj to i64
; X32-NEXT: --> (zext i32 (42 + (ptrtoint ptr %in to i32)) to i64) U: [0,4294967296) S: [0,4294967296)
; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_gep
diff --git a/llvm/test/Analysis/ScalarEvolution/sdiv.ll b/llvm/test/Analysis/ScalarEvolution/sdiv.ll
index e01f84fb2226e..ce531a967f634 100644
--- a/llvm/test/Analysis/ScalarEvolution/sdiv.ll
+++ b/llvm/test/Analysis/ScalarEvolution/sdiv.ll
@@ -18,7 +18,7 @@ define dso_local void @_Z4loopi(i32 %width) local_unnamed_addr #0 {
; CHECK-NEXT: %idxprom = sext i32 %rem to i64
; CHECK-NEXT: --> ({0,+,1}<nuw><nsw><%for.cond> /u 2) U: [0,2147483648) S: [0,2147483648) Exits: ((zext i32 %width to i64) /u 2) LoopDispositions: { %for.cond: Computable }
; CHECK-NEXT: %arrayidx = getelementptr inbounds [2 x i32], ptr %storage, i64 0, i64 %idxprom
-; CHECK-NEXT: --> ((4 * ({0,+,1}<nuw><nsw><%for.cond> /u 2))<nuw><nsw> + %storage) U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: ((4 * ((zext i32 %width to i64) /u 2))<nuw><nsw> + %storage) LoopDispositions: { %for.cond: Computable }
+; CHECK-NEXT: --> ((4 * ({0,+,1}<nuw><nsw><%for.cond> /u 2))<nuw><nsw> + %storage)(u nuw) U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: ((4 * ((zext i32 %width to i64) /u 2))<nuw><nsw> + %storage) LoopDispositions: { %for.cond: Computable }
; CHECK-NEXT: %1 = load i32, ptr %arrayidx, align 4
; CHECK-NEXT: --> %1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
; CHECK-NEXT: %call = call i32 @_Z3adji(i32 %1)
diff --git a/llvm/test/Analysis/ScalarEvolution/srem.ll b/llvm/test/Analysis/ScalarEvolution/srem.ll
index ff898c963d0dc..6ea3921880a2d 100644
--- a/llvm/test/Analysis/ScalarEvolution/srem.ll
+++ b/llvm/test/Analysis/ScalarEvolution/srem.ll
@@ -18,7 +18,7 @@ define dso_local void @_Z4loopi(i32 %width) local_unnamed_addr #0 {
; CHECK-NEXT: %idxprom = sext i32 %rem to i64
; CHECK-NEXT: --> (zext i1 {false,+,true}<%for.cond> to i64) U: [0,2) S: [0,2) Exits: (zext i1 (trunc i32 %width to i1) to i64) LoopDispositions: { %for.cond: Computable }
; CHECK-NEXT: %arrayidx = getelementptr inbounds [2 x i32], ptr %storage, i64 0, i64 %idxprom
-; CHECK-NEXT: --> ((4 * (zext i1 {false,+,true}<%for.cond> to i64))<nuw><nsw> + %storage) U: [4,-7) S: [-9223372036854775808,9223372036854775805) Exits: ((4 * (zext i1 (trunc i32 %width to i1) to i64))<nuw><nsw> + %storage) LoopDispositions: { %for.cond: Computable }
+; CHECK-NEXT: --> ((4 * (zext i1 {false,+,true}<%for.cond> to i64))<nuw><nsw> + %storage)(u nuw) U: [4,-7) S: [-9223372036854775808,9223372036854775805) Exits: ((4 * (zext i1 (trunc i32 %width to i1) to i64))<nuw><nsw> + %storage) LoopDispositions: { %for.cond: Computable }
; CHECK-NEXT: %1 = load i32, ptr %arrayidx, align 4
; CHECK-NEXT: --> %1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
; CHECK-NEXT: %call = call i32 @_Z3adji(i32 %1)
|
8999663
to
3a3232d
Compare
7b4f33b
to
6104124
Compare
6104124
to
4b0c62b
Compare
4b0c62b
to
352daca
Compare
352daca
to
45b5e62
Compare
This patch introduces SCEVUse, which is a tagged pointer containing the used const SCEV *, plus extra bits to store NUW/NSW flags that are only valid at the specific use. This was suggested by @nikic as an alternative to llvm#90742. This patch just updates most SCEV infrastructure to operate on SCEVUse instead of const SCEV *. It does not introduce any code that makes use of the use-specific flags yet which I'll share as follow-ups. Note that this should be NFC, but currently there's at least one case where it is not (turn-to-invariant.ll), which I'll investigate once we agree on the overall direction. This PR at the moment also contains a commit that updates various SCEV clients to use `const SCEV *` instead of `const auto *`, to prepare for this patch. This reduces the number of changes needed, as SCEVUse will automatically convert to `const SCEV *`. This is a safe default, as it just drops the use-specific flags for the expression (it will not drop any use-specific flags for any of its operands though). This probably SCEVUse could probably also be used to address mis-compiles due to equivalent AddRecs modulo flags result in an AddRec with incorrect flags for some uses of some phis, e.g. the one llvm#80430 attempted to fix Compile-time impact: stage1-O3: +0.06% stage1-ReleaseThinLTO: +0.07% stage1-ReleaseLTO-g: +0.07% stage2-O3: +0.11% https://llvm-compile-time-tracker.com/compare.php?from=ce055843e2be9643bd58764783a7bb69f6db8c9a&to=8c7f4e9e154ebc4862c4e2716cedc3c688352d7c&stat=instructions:u
45b5e62
to
a777a0e
Compare
Use SCEVUse from llvm#91961 to return a SCEVUse with use-specific no-wrap flags for GEP expr, when demanded. Clients need to opt-in, as the use-specific flags may not be valid in some contexts (e.g. backedge taken counts).
9b5d058
to
fc6e2c8
Compare
bcc33a2
to
a15daba
Compare
f3905cd
to
6eeb7f7
Compare
Use SCEVUse from #91961 to return a SCEVUse with use-specific no-wrap flags for GEP expr, when demanded.
Clients need to opt-in, as the use-specific flags may not be valid in some contexts (e.g. backedge taken counts).