[llvm] [SCEV] Fold sext-AddRec on positive step (PR #217422)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 19 11:22:12 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
@llvm/pr-subscribers-llvm-transforms
Author: Ramkumar Ramachandra (artagnon)
<details>
<summary>Changes</summary>
We mirror the zext-AddRec case for sext, by pushing the sext into the AddRec when certain conditions are satisfied, including a positive step. This results in many improvements.
-- 8< --
Based on https://github.com/llvm/llvm-project/pull/217362.
---
Patch is 83.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/217422.diff
29 Files Affected:
- (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+25-89)
- (modified) llvm/test/Analysis/ScalarEvolution/incorrect-nsw.ll (+3-3)
- (modified) llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll (+3-3)
- (modified) llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll (+35-7)
- (modified) llvm/test/Analysis/ScalarEvolution/sext-mul.ll (+4-4)
- (modified) llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll (+10-10)
- (modified) llvm/test/Transforms/IndVarSimplify/X86/overflow-intrinsics.ll (+2-2)
- (modified) llvm/test/Transforms/IndVarSimplify/backedge-on-min-max.ll (+2-2)
- (modified) llvm/test/Transforms/IndVarSimplify/floating-point-iv.ll (+1-1)
- (modified) llvm/test/Transforms/IndVarSimplify/infer-poison-flags.ll (+1-1)
- (modified) llvm/test/Transforms/IndVarSimplify/loop-predication.ll (+8-8)
- (modified) llvm/test/Transforms/IndVarSimplify/pointer-loop-guards.ll (+1-1)
- (modified) llvm/test/Transforms/IndVarSimplify/pr57247.ll (+1-1)
- (modified) llvm/test/Transforms/IndVarSimplify/strengthen-overflow.ll (+2-2)
- (modified) llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll (+3-3)
- (modified) llvm/test/Transforms/LoopStrengthReduce/X86/2012-01-13-phielim.ll (+1-1)
- (modified) llvm/test/Transforms/LoopStrengthReduce/X86/pr17473.ll (+36-2)
- (modified) llvm/test/Transforms/LoopVectorize/RISCV/strided-access-wide-stride.ll (+9-14)
- (modified) llvm/test/Transforms/LoopVectorize/RISCV/tail-folding-iv-outside-user.ll (+3-20)
- (modified) llvm/test/Transforms/LoopVectorize/X86/replicating-load-store-costs.ll (+1-4)
- (modified) llvm/test/Transforms/LoopVectorize/alias-mask-data-tail-folding-style.ll (+1-6)
- (modified) llvm/test/Transforms/LoopVectorize/div-exact.ll (+4-12)
- (modified) llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll (+6-16)
- (modified) llvm/test/Transforms/LoopVectorize/first-order-recurrence-dead-instructions.ll (+3-26)
- (modified) llvm/test/Transforms/LoopVectorize/interleaved-accesses-dead-member.ll (+2-10)
- (modified) llvm/test/Transforms/LoopVectorize/iv_outside_user.ll (+2-7)
- (modified) llvm/test/Transforms/LoopVectorize/pointer-induction.ll (+6-16)
- (modified) llvm/test/Transforms/LoopVectorize/simplify-logic.ll (+8-40)
- (modified) llvm/test/Transforms/LoopVectorize/widen-intrinsic-tail-fold.ll (+6-38)
``````````diff
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 52a03d2cad62d..6bec4b0283ee6 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -1972,7 +1972,7 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(SCEVUse Op, Type *Ty,
if (AR->hasNoSignedWrap()) {
Start = getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Depth + 1);
Step = getSignExtendExpr(Step, Ty, Depth + 1);
- return getAddRecExpr(Start, Step, L, SCEV::FlagNSW);
+ return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
}
}
@@ -2044,96 +2044,39 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(SCEVUse Op, Type *Ty,
// operands (often constants). This allows analysis of something like
// this: for (signed char X = 0; X < 100; ++X) { int Y = X; }
if (match(Op, m_scev_AffineAddRec(m_SCEV(Start), m_SCEV(Step), m_Loop(L)))) {
+ // Redo the AddRec check, computing nsw this time.
const auto *AR = cast<SCEVAddRecExpr>(Op);
- unsigned BitWidth = getTypeSizeInBits(AR->getType());
-
- // The no-signed-wrap case is handled before the uniquing lookup above.
-
- // Check whether the backedge-taken count is SCEVCouldNotCompute.
- // Note that this serves two purposes: It filters out loops that are
- // simply not analyzable, and it covers the case where this code is
- // being called from within backedge-taken count analysis, such that
- // attempting to ask for the backedge-taken count would likely result
- // in infinite recursion. In the later case, the analysis code will
- // cope with a conservative value, and it will take care to purge
- // that value once it has finished.
- const SCEV *MaxBECount = getConstantMaxBackedgeTakenCount(L);
- if (!isa<SCEVCouldNotCompute>(MaxBECount)) {
- // Manually compute the final value for AR, checking for
- // overflow.
-
- // Check whether the backedge-taken count can be losslessly casted to
- // the addrec's type. The count is always unsigned.
- const SCEV *CastedMaxBECount =
- getTruncateOrZeroExtend(MaxBECount, Start->getType(), Depth);
- const SCEV *RecastedMaxBECount = getTruncateOrZeroExtend(
- CastedMaxBECount, MaxBECount->getType(), Depth);
- if (MaxBECount == RecastedMaxBECount) {
- Type *WideTy = IntegerType::get(getContext(), BitWidth * 2);
- // Check whether Start+Step*MaxBECount has no signed overflow.
- const SCEV *SMul =
- getMulExpr(CastedMaxBECount, Step, SCEV::FlagAnyWrap, Depth + 1);
- const SCEV *SAdd = getSignExtendExpr(
- getAddExpr(Start, SMul, SCEV::FlagAnyWrap, Depth + 1), WideTy,
- Depth + 1);
- const SCEV *WideStart = getSignExtendExpr(Start, WideTy, Depth + 1);
- const SCEV *WideMaxBECount =
- getZeroExtendExpr(CastedMaxBECount, WideTy, Depth + 1);
- const SCEV *OperandExtendedAdd =
- getAddExpr(WideStart,
- getMulExpr(WideMaxBECount,
- getSignExtendExpr(Step, WideTy, Depth + 1),
- SCEV::FlagAnyWrap, Depth + 1),
- SCEV::FlagAnyWrap, Depth + 1);
- if (SAdd == OperandExtendedAdd) {
- // Cache knowledge of AR NSW, which is propagated to this AddRec.
- setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNSW);
- // Return the expression with the addrec on the outside.
- Start =
- getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Depth + 1);
- Step = getSignExtendExpr(Step, Ty, Depth + 1);
- return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
- }
- // Similar to above, only this time treat the step value as unsigned.
- // This covers loops that count up with an unsigned step.
- OperandExtendedAdd =
- getAddExpr(WideStart,
- getMulExpr(WideMaxBECount,
- getZeroExtendExpr(Step, WideTy, Depth + 1),
- SCEV::FlagAnyWrap, Depth + 1),
- SCEV::FlagAnyWrap, Depth + 1);
- if (SAdd == OperandExtendedAdd) {
- // If AR wraps around then
- //
- // abs(Step) * MaxBECount > unsigned-max(AR->getType())
- // => SAdd != OperandExtendedAdd
- //
- // Thus (AR is not NW => SAdd != OperandExtendedAdd) <=>
- // (SAdd == OperandExtendedAdd => AR is NW)
-
- setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNW);
-
- // Return the expression with the addrec on the outside.
- Start =
- getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Depth + 1);
- Step = getZeroExtendExpr(Step, Ty, Depth + 1);
- return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
- }
- }
- }
-
+ inferNoWrapViaConstantRanges(AR);
auto NewFlags = proveNoSignedWrapViaInduction(AR);
+ if (!hasFlags(NewFlags, SCEV::FlagNSW) &&
+ proveNoWrapByVaryingStart<SCEVSignExtendExpr>(Start, Step, L))
+ NewFlags |= SCEV::FlagNSW;
setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), NewFlags);
+
+ // If the operand is an affine AddRec with the no-signed-wrap flag, the
+ // sign-extension distributes over the recurrence.
if (AR->hasNoSignedWrap()) {
- // Same as nsw case above - duplicated here to avoid a compile time
- // issue. It's not clear that the order of checks does matter, but
- // it's one of two issue possible causes for a change which was
- // reverted. Be conservative for the moment.
Start = getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Depth + 1);
Step = getSignExtendExpr(Step, Ty, Depth + 1);
return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
}
+ // For a positive step, we can extend the operands iff doing so only
+ // traverses values in the range sext([0,UINT_MIN]).
+ if (isKnownPositive(Step)) {
+ unsigned BitWidth = getTypeSizeInBits(AR->getType());
+ const SCEV *N =
+ getConstant(APInt::getMinValue(BitWidth) - getSignedRangeMax(Step));
+ if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, AR, N) ||
+ isKnownOnEveryIteration(ICmpInst::ICMP_ULT, AR, N)) {
+ setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNW);
+ Start =
+ getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Depth + 1);
+ Step = getZeroExtendExpr(Step, Ty, Depth + 1);
+ return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
+ }
+ }
+
// sext({C,+,Step}) --> (sext(D) + sext({C-D,+,Step}))<nuw><nsw>
// if D + (C - D + Step * n) could be proven to not signed wrap
// where D maximizes the number of trailing zeros of (C - D + Step * n)
@@ -2149,13 +2092,6 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(SCEVUse Op, Type *Ty,
Depth + 1);
}
}
-
- if (proveNoWrapByVaryingStart<SCEVSignExtendExpr>(Start, Step, L)) {
- setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR), SCEV::FlagNSW);
- Start = getExtendAddRecStart<SCEVSignExtendExpr>(AR, Ty, this, Depth + 1);
- Step = getSignExtendExpr(Step, Ty, Depth + 1);
- return getAddRecExpr(Start, Step, L, AR->getNoWrapFlags());
- }
}
// If the input value is provably positive and we could not simplify
diff --git a/llvm/test/Analysis/ScalarEvolution/incorrect-nsw.ll b/llvm/test/Analysis/ScalarEvolution/incorrect-nsw.ll
index f7edf493c64c4..1490c6710bced 100644
--- a/llvm/test/Analysis/ScalarEvolution/incorrect-nsw.ll
+++ b/llvm/test/Analysis/ScalarEvolution/incorrect-nsw.ll
@@ -3,13 +3,13 @@
define void @bad.nsw() {
; CHECK-LABEL: Classifying expressions for: @bad.nsw
; CHECK-LABEL: Classifying expressions for: @bad.nsw
- entry:
+ entry:
br label %loop
loop:
%i = phi i8 [ -1, %entry ], [ %i.inc, %loop ]
; CHECK: %i = phi i8 [ -1, %entry ], [ %i.inc, %loop ]
-; CHECK-NEXT: --> {-1,+,-128}<nw><%loop>
+; CHECK-NEXT: --> {-1,+,-128}<%loop>
; CHECK-NOT: --> {-1,+,-128}<nsw><%loop>
%counter = phi i8 [ 0, %entry ], [ %counter.inc, %loop ]
@@ -22,5 +22,5 @@ define void @bad.nsw() {
br i1 %continue, label %exit, label %loop
exit:
- ret void
+ ret void
}
diff --git a/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll b/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
index 6ededf2477711..73a20f03548ba 100644
--- a/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
+++ b/llvm/test/Analysis/ScalarEvolution/min-max-exprs.ll
@@ -26,13 +26,13 @@ define void @f(ptr %A, i32 %N) {
; CHECK-NEXT: %tmp3 = add nuw nsw i32 %i.0, 3
; CHECK-NEXT: --> {3,+,1}<nuw><%bb1> U: [3,-2147483645) S: [3,-2147483645) Exits: (3 + (0 smax %N))<nuw> LoopDispositions: { %bb1: Computable }
; CHECK-NEXT: %tmp5 = sext i32 %tmp3 to i64
-; CHECK-NEXT: --> (sext i32 {3,+,1}<nuw><%bb1> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: (sext i32 (3 + (0 smax %N))<nuw> to i64) LoopDispositions: { %bb1: Computable }
+; CHECK-NEXT: --> {3,+,1}<nuw><%bb1> U: [3,2147483651) S: [3,2147483651) Exits: (3 + (zext i32 (0 smax %N) to i64))<nuw><nsw> LoopDispositions: { %bb1: Computable }
; CHECK-NEXT: %tmp6 = sext i32 %N to i64
; CHECK-NEXT: --> (sext i32 %N to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: (sext i32 %N to i64) LoopDispositions: { %bb1: Invariant }
; CHECK-NEXT: %tmp9 = select i1 %tmp4, i64 %tmp5, i64 %tmp6
-; CHECK-NEXT: --> ((sext i32 {3,+,1}<nuw><%bb1> to i64) smin (sext i32 %N to i64)) U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: ((sext i32 (3 + (0 smax %N))<nuw> to i64) smin (sext i32 %N to i64)) LoopDispositions: { %bb1: Computable }
+; CHECK-NEXT: --> ((sext i32 %N to i64) smin {3,+,1}<nuw><nsw><%bb1>) U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: ((sext i32 %N to i64) smin (3 + (zext i32 (0 smax %N) to i64))<nuw><nsw>) LoopDispositions: { %bb1: Computable }
; CHECK-NEXT: %tmp11 = getelementptr inbounds i32, ptr %A, i64 %tmp9
-; CHECK-NEXT: --> ((4 * ((sext i32 {3,+,1}<nuw><%bb1> to i64) smin (sext i32 %N to i64)))<nsw> + %A) U: full-set S: full-set Exits: ((4 * ((sext i32 (3 + (0 smax %N))<nuw> to i64) smin (sext i32 %N to i64)))<nsw> + %A) LoopDispositions: { %bb1: Computable }
+; CHECK-NEXT: --> ((4 * ((sext i32 %N to i64) smin {3,+,1}<nuw><nsw><%bb1>))<nsw> + %A) U: full-set S: full-set Exits: ((4 * ((sext i32 %N to i64) smin (3 + (zext i32 (0 smax %N) to i64))<nuw><nsw>))<nsw> + %A) LoopDispositions: { %bb1: Computable }
; CHECK-NEXT: %tmp12 = load i32, ptr %tmp11, align 4
; CHECK-NEXT: --> %tmp12 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb1: Variant }
; CHECK-NEXT: %tmp13 = shl nsw i32 %tmp12, 1
diff --git a/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll b/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll
index 572b3f7271b88..b5d05a31356b6 100644
--- a/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll
+++ b/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll
@@ -1,17 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -disable-output "-passes=print<scalar-evolution>" 2>&1 | FileCheck %s
-; CHECK: %tmp3 = sext i8 %tmp2 to i32
-; CHECK: --> (sext i8 {0,+,1}<nuw><%bb1> to i32) U: [-128,128) S: [-128,128) Exits: -1
-; CHECK: %tmp4 = mul i32 %tmp3, %i.02
-; CHECK: --> ((sext i8 {0,+,1}<nuw><%bb1> to i32) * {0,+,1}<nuw><nsw><%bb>) U: [-3968,3938) S: [-3968,3938) Exits: {0,+,-1}<nsw><%bb>
-
-; These sexts are not foldable.
-
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64"
@table = common global [32 x [256 x i32]] zeroinitializer, align 32 ; <ptr> [#uses=2]
define i32 @main() nounwind {
+; CHECK-LABEL: 'main'
+; CHECK-NEXT: Classifying expressions for: @main
+; CHECK-NEXT: %i.02 = phi i32 [ %tmp10, %bb4 ], [ 0, %bb.nph3 ]
+; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%bb> U: [0,32) S: [0,32) Exits: 31 LoopDispositions: { %bb: Computable, %bb1: Invariant }
+; CHECK-NEXT: %j.01 = phi i32 [ %tmp8, %bb2 ], [ 0, %bb.nph ]
+; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%bb1> U: [0,256) S: [0,256) Exits: 255 LoopDispositions: { %bb1: Computable, %bb: Uniform }
+; CHECK-NEXT: %tmp2 = trunc i32 %j.01 to i8
+; CHECK-NEXT: --> {0,+,1}<%bb1> U: full-set S: full-set Exits: -1 LoopDispositions: { %bb1: Computable, %bb: Uniform }
+; CHECK-NEXT: %tmp3 = sext i8 %tmp2 to i32
+; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%bb1> U: [0,256) S: [0,256) Exits: 255 LoopDispositions: { %bb1: Computable, %bb: Uniform }
+; CHECK-NEXT: %tmp4 = mul i32 %tmp3, %i.02
+; CHECK-NEXT: --> {0,+,{0,+,1}<nuw><nsw><%bb>}<%bb1> U: [0,7906) S: [0,7906) Exits: {0,+,255}<nuw><nsw><%bb> LoopDispositions: { %bb1: Computable, %bb: Variant }
+; CHECK-NEXT: %tmp5 = sext i32 %i.02 to i64
+; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%bb> U: [0,32) S: [0,32) Exits: {0,+,1}<nuw><nsw><%bb> LoopDispositions: { %bb1: Invariant, %bb: Computable }
+; CHECK-NEXT: %tmp6 = sext i32 %j.01 to i64
+; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%bb1> U: [0,256) S: [0,256) Exits: 255 LoopDispositions: { %bb1: Computable, %bb: Uniform }
+; CHECK-NEXT: %tmp7 = getelementptr [32 x [256 x i32]], ptr @table, i64 0, i64 %tmp5, i64 %tmp6
+; CHECK-NEXT: --> {{\{\{}}@table,+,1024}<nw><%bb>,+,4}<nw><%bb1> U: [32,-35) S: [-9223372036854775808,9223372036854775805) Exits: {(1020 + @table)<nuw>,+,1024}<nuw><%bb> LoopDispositions: { %bb1: Computable, %bb: Variant }
+; CHECK-NEXT: %tmp8 = add i32 %j.01, 1
+; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%bb1> U: [1,257) S: [1,257) Exits: 256 LoopDispositions: { %bb1: Computable, %bb: Uniform }
+; CHECK-NEXT: %tmp10 = add i32 %i.02, 1
+; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%bb> U: [1,33) S: [1,33) Exits: 32 LoopDispositions: { %bb: Computable, %bb1: Invariant }
+; CHECK-NEXT: %tmp12 = load i32, ptr getelementptr ([32 x [256 x i32]], ptr @table, i64 0, i64 9, i64 132), align 16
+; CHECK-NEXT: --> %tmp12 U: full-set S: full-set
+; CHECK-NEXT: Determining loop execution counts for: @main
+; CHECK-NEXT: Loop %bb1: backedge-taken count is i32 255
+; CHECK-NEXT: Loop %bb1: constant max backedge-taken count is i32 255
+; CHECK-NEXT: Loop %bb1: symbolic max backedge-taken count is i32 255
+; CHECK-NEXT: Loop %bb1: Trip multiple is 256
+; CHECK-NEXT: Loop %bb: backedge-taken count is i32 31
+; CHECK-NEXT: Loop %bb: constant max backedge-taken count is i32 31
+; CHECK-NEXT: Loop %bb: symbolic max backedge-taken count is i32 31
+; CHECK-NEXT: Loop %bb: Trip multiple is 32
+;
entry:
br i1 false, label %bb5, label %bb.nph3
diff --git a/llvm/test/Analysis/ScalarEvolution/sext-mul.ll b/llvm/test/Analysis/ScalarEvolution/sext-mul.ll
index 5d6a1dec72e13..41bab08a9ae82 100644
--- a/llvm/test/Analysis/ScalarEvolution/sext-mul.ll
+++ b/llvm/test/Analysis/ScalarEvolution/sext-mul.ll
@@ -11,17 +11,17 @@ define void @foo(ptr nocapture %arg, i32 %arg1, i32 %arg2) {
; CHECK-NEXT: %tmp9 = shl i64 %tmp8, 33
; CHECK-NEXT: --> {0,+,8589934592}<nuw><%bb7> U: [0,-17179869183) S: [-9223372036854775808,9223372028264841217) Exits: (-8589934592 + (8589934592 * (zext i32 %arg2 to i64))) LoopDispositions: { %bb7: Computable }
; CHECK-NEXT: %tmp10 = ashr exact i64 %tmp9, 32
-; CHECK-NEXT: --> (sext i32 {0,+,2}<nuw><%bb7> to i64) U: [0,-1) S: [-2147483648,2147483647) Exits: (sext i32 (-2 + (2 * %arg2)) to i64) LoopDispositions: { %bb7: Computable }
+; CHECK-NEXT: --> {0,+,2}<nuw><nsw><%bb7> U: [0,4294967293) S: [0,4294967293) Exits: (-2 + (2 * (zext i32 %arg2 to i64))<nuw><nsw>)<nsw> LoopDispositions: { %bb7: Computable }
; CHECK-NEXT: %tmp11 = getelementptr inbounds i32, ptr %arg, i64 %tmp10
-; CHECK-NEXT: --> ((4 * (sext i32 {0,+,2}<nuw><%bb7> to i64))<nsw> + %arg) U: full-set S: full-set Exits: ((4 * (sext i32 (-2 + (2 * %arg2)) to i64))<nsw> + %arg) LoopDispositions: { %bb7: Computable }
+; CHECK-NEXT: --> {%arg,+,8}<nuw><%bb7> U: full-set S: full-set Exits: (-8 + (8 * (zext i32 %arg2 to i64))<nuw><nsw> + %arg) LoopDispositions: { %bb7: Computable }
; CHECK-NEXT: %tmp12 = load i32, ptr %tmp11, align 4
; CHECK-NEXT: --> %tmp12 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
; CHECK-NEXT: %tmp13 = sub nsw i32 %tmp12, %arg1
; CHECK-NEXT: --> ((-1 * %arg1) + %tmp12) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
; CHECK-NEXT: %tmp14 = or disjoint i64 %tmp10, 1
-; CHECK-NEXT: --> (1 + (sext i32 {0,+,2}<nuw><%bb7> to i64))<nuw><nsw> U: [1,0) S: [-2147483647,2147483648) Exits: (1 + (sext i32 (-2 + (2 * %arg2)) to i64))<nuw><nsw> LoopDispositions: { %bb7: Computable }
+; CHECK-NEXT: --> {1,+,2}<nuw><nsw><%bb7> U: [1,4294967294) S: [1,4294967294) Exits: (-1 + (2 * (zext i32 %arg2 to i64))<nuw><nsw>)<nsw> LoopDispositions: { %bb7: Computable }
; CHECK-NEXT: %tmp15 = getelementptr inbounds i32, ptr %arg, i64 %tmp14
-; CHECK-NEXT: --> (4 + (4 * (sext i32 {0,+,2}<nuw><%bb7> to i64))<nsw> + %arg) U: full-set S: full-set Exits: (4 + (4 * (sext i32 (-2 + (2 * %arg2)) to i64))<nsw> + %arg) LoopDispositions: { %bb7: Computable }
+; CHECK-NEXT: --> {(4 + %arg),+,8}<nuw><%bb7> U: full-set S: full-set Exits: (-4 + (8 * (zext i32 %arg2 to i64))<nuw><nsw> + %arg) LoopDispositions: { %bb7: Computable }
; CHECK-NEXT: %tmp16 = load i32, ptr %tmp15, align 4
; CHECK-NEXT: --> %tmp16 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
; CHECK-NEXT: %tmp17 = mul nsw i32 %tmp16, %arg1
diff --git a/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll b/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll
index 712b6ae399f2e..b5549b706957f 100644
--- a/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll
+++ b/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll
@@ -149,7 +149,7 @@ define i32 @test1(ptr %array, i32 %length, i32 %n) #0 {
; CHECK-V8M-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
; CHECK-V8M-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
; CHECK-V8M-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
-; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
+; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1
; CHECK-V8M-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
; CHECK-V8M-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK-V8M: exit:
@@ -176,7 +176,7 @@ define i32 @test1(ptr %array, i32 %length, i32 %n) #0 {
; CHECK-V8A-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
; CHECK-V8A-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
; CHECK-V8A-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
-; CHECK-V8A-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
+; CHECK-V8A-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1
; CHECK-V8A-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
; CHECK-V8A-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK-V8A: exit:
@@ -317,7 +317,7 @@ define i32 @two_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %len
; CHECK-V8M-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_2:%.*]], i64 [[I_I64]]
; CHECK-V8M-NEXT: [[ARRAY_2_I:%.*]] = load i32, ptr [[ARRAY_2_I_PTR]], align 4
; CHECK-V8M-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
-; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
+; CHECK-V8M-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1
; CHECK-V8M-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
; CHECK-V8M-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK-V8M: exit:
@@ -348,7 +348,7 @@ define i32 @two_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %len
; CHECK-V8A-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_2:%.*]], i64 [[I_I64]]
; CHECK-V8A-NEXT: [[ARRAY_2_I:%.*]] = load i32, ptr [[ARRAY_2_I_PTR]], align 4
; CHECK-V8A-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
-; CHECK-V8A-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
+; CHECK-V8A-NEXT: [[I_NEXT]] =...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/217422
More information about the llvm-commits
mailing list