[llvm] [Analysis] Use usub_sat during SCEV expansion in some cases (PR #216975)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 02:54:33 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: David Sherwood (david-arm)

<details>
<summary>Changes</summary>

When expanding code in visitAddExpr we can look for the pattern

  -C + umax(X, C)

and transform this into

--> usub.sat(X, C)

which simplifies the IR in some tests.

---

Patch is 48.32 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/216975.diff


20 Files Affected:

- (modified) llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h (+6) 
- (modified) llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp (+13-1) 
- (modified) llvm/test/Transforms/IRCE/unsigned_comparisons_ugt.ll (+14-29) 
- (modified) llvm/test/Transforms/IRCE/unsigned_comparisons_ult.ll (+20-37) 
- (modified) llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll (+12-24) 
- (modified) llvm/test/Transforms/IndVarSimplify/loop-predication.ll (+6-12) 
- (modified) llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll (+1-3) 
- (modified) llvm/test/Transforms/LoopPredication/predicate-exits.ll (+8-17) 
- (modified) llvm/test/Transforms/LoopVectorize/AArch64/induction-costs-sve.ll (+2-4) 
- (modified) llvm/test/Transforms/LoopVectorize/AArch64/induction-costs.ll (+3-4) 
- (modified) llvm/test/Transforms/LoopVectorize/AArch64/simple_early_exit.ll (+1-2) 
- (modified) llvm/test/Transforms/LoopVectorize/X86/cost-model.ll (+3-6) 
- (modified) llvm/test/Transforms/LoopVectorize/alias-mask-data-tail-folding-style.ll (+1-2) 
- (modified) llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll (+2-4) 
- (modified) llvm/test/Transforms/LoopVectorize/iv_outside_user.ll (+1-2) 
- (modified) llvm/test/Transforms/LoopVectorize/load-deref-pred-align.ll (+1-2) 
- (modified) llvm/test/Transforms/LoopVectorize/pointer-induction.ll (+2-4) 
- (modified) llvm/test/Transforms/LoopVectorize/replace-first-order-recurrence-by-versioned-iv.ll (+1-2) 
- (modified) llvm/test/Transforms/LoopVectorize/runtime-check-small-bounded-ranges.ll (+1-2) 
- (modified) llvm/test/Transforms/LoopVectorize/single_early_exit.ll (+1-2) 


``````````diff
diff --git a/llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h b/llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h
index b6820fbd8075b..d8726b2439ff0 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h
@@ -269,6 +269,12 @@ m_scev_SMax(const Op0_t &Op0, const Op1_t &Op1) {
   return m_scev_Binary<SCEVSMaxExpr>(Op0, Op1);
 }
 
+template <typename Op0_t, typename Op1_t>
+inline SCEVBinaryExpr_match<SCEVUMaxExpr, Op0_t, Op1_t>
+m_scev_UMax(const Op0_t &Op0, const Op1_t &Op1) {
+  return m_scev_Binary<SCEVUMaxExpr>(Op0, Op1);
+}
+
 template <typename Op0_t, typename Op1_t>
 inline SCEVBinaryExpr_match<SCEVMinMaxExpr, Op0_t, Op1_t>
 m_scev_MinMax(const Op0_t &Op0, const Op1_t &Op1) {
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index a7ca2104e59c3..913e29e593727 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -532,7 +532,19 @@ Value *SCEVExpander::visitAddExpr(SCEVUseT<const SCEVAddExpr *> S) {
     Value *LHS = expand(URemLHS);
     Value *RHS = expand(URemRHS);
     return InsertBinop(Instruction::URem, LHS, RHS, SCEV::FlagAnyWrap,
-                      /*IsSafeToHoist*/ false);
+                       /*IsSafeToHoist*/ false);
+  }
+
+  // -C + umax(C, X) --> usub.sat(X, C)
+  const SCEV *UMaxRHS = nullptr;
+  const SCEVConstant *C1, *C2;
+  if (match(S, m_scev_Add(m_SCEVConstant(C1),
+                          m_scev_UMax(m_SCEVConstant(C2), m_SCEV(UMaxRHS)))) &&
+      C1->getAPInt() == -C2->getAPInt()) {
+    Value *LHS = expand(UMaxRHS);
+    Value *RHS = expand(C2);
+    return Builder.CreateIntrinsic(Intrinsic::usub_sat, {S->getType()},
+                                   {LHS, RHS});
   }
 
   // Collect all the add operands in a loop, along with their associated loops.
diff --git a/llvm/test/Transforms/IRCE/unsigned_comparisons_ugt.ll b/llvm/test/Transforms/IRCE/unsigned_comparisons_ugt.ll
index e5caf440aca3a..caa5dacdd5b14 100644
--- a/llvm/test/Transforms/IRCE/unsigned_comparisons_ugt.ll
+++ b/llvm/test/Transforms/IRCE/unsigned_comparisons_ugt.ll
@@ -11,8 +11,8 @@
 
 ; UGT condition for increasing loop.
 define void @test_01(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_01
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_01(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
@@ -88,12 +88,11 @@ exit:
 
 ; UGT condition for decreasing loop.
 define void @test_02(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_02
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_02(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
-; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1
+; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[LEN]], i32 1)
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 100, [[EXIT_PRELOOP_AT]]
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
 ; CHECK:       loop.preloop.preheader:
@@ -166,8 +165,8 @@ exit:
 
 ; Check SINT_MAX + 1, test is similar to test_01.
 define void @test_03(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_03
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_03(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
@@ -243,12 +242,11 @@ exit:
 
 ; Check SINT_MAX + 1, test is similar to test_02.
 define void @test_04(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_04
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_04(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
-; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1
+; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[LEN]], i32 1)
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 -2147483648, [[EXIT_PRELOOP_AT]]
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
 ; CHECK:       loop.preloop.preheader:
@@ -321,8 +319,8 @@ exit:
 
 ; Increasing loop, UINT_MAX. Negative test: we cannot add 1 to UINT_MAX.
 define void @test_05(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_05
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_05(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
@@ -367,8 +365,8 @@ exit:
 
 ; Decreasing loop, UINT_MAX. Positive test.
 define void @test_06(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_06
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_06(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
 ; CHECK-NEXT:    br i1 true, label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
@@ -441,16 +439,3 @@ exit:
 }
 
 !0 = !{i32 0, i32 50}
-;.
-; CHECK: [[RNG0]] = !{i32 0, i32 50}
-; CHECK: [[LOOP1]] = distinct !{[[LOOP1]], [[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]]}
-; CHECK: [[META2]] = !{!"llvm.loop.unroll.disable"}
-; CHECK: [[META3]] = !{!"llvm.loop.vectorize.disable"}
-; CHECK: [[META4]] = !{!"llvm.loop.licm_versioning.disable"}
-; CHECK: [[META5]] = !{!"llvm.loop.distribute.disable"}
-; CHECK: [[META6]] = !{}
-; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META3]], [[META4]], [[META5]]}
-; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META2]], [[META3]], [[META4]], [[META5]]}
-; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META3]], [[META4]], [[META5]]}
-; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META2]], [[META3]], [[META4]], [[META5]]}
-;.
diff --git a/llvm/test/Transforms/IRCE/unsigned_comparisons_ult.ll b/llvm/test/Transforms/IRCE/unsigned_comparisons_ult.ll
index 3fb7b46e69569..00442b51993dd 100644
--- a/llvm/test/Transforms/IRCE/unsigned_comparisons_ult.ll
+++ b/llvm/test/Transforms/IRCE/unsigned_comparisons_ult.ll
@@ -14,8 +14,8 @@
 
 ; ULT condition for increasing loop.
 define void @test_01(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_01
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_01(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
@@ -90,12 +90,11 @@ exit:
 
 ; ULT condition for decreasing loops.
 define void @test_02(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_02
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_02(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
-; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1
+; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[LEN]], i32 1)
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 100, [[EXIT_PRELOOP_AT]]
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
 ; CHECK:       loop.preloop.preheader:
@@ -169,8 +168,8 @@ exit:
 
 ; Check SINT_MAX.
 define void @test_03(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_03
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_03(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
@@ -245,8 +244,8 @@ exit:
 
 ; Check SINT_MAX + 1, test is similar to test_01.
 define void @test_04(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_04
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_04(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
@@ -321,12 +320,11 @@ exit:
 
 ; Check SINT_MAX + 1, test is similar to test_02.
 define void @test_05(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_05
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_05(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
-; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1
+; CHECK-NEXT:    [[EXIT_PRELOOP_AT:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[LEN]], i32 1)
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 -2147483648, [[EXIT_PRELOOP_AT]]
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
 ; CHECK:       loop.preloop.preheader:
@@ -400,8 +398,8 @@ exit:
 
 ; Increasing loop, UINT_MAX. Positive test.
 define void @test_06(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_06
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_06(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
@@ -476,8 +474,8 @@ exit:
 
 ; Decreasing loop, UINT_MAX. Negative test: we cannot substract -1 from 0.
 define void @test_07(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_07
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_07(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
@@ -525,8 +523,8 @@ exit:
 ; range does not prevent us from performing IRCE.
 
 define void @test_08(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_08
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_08(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
@@ -603,8 +601,8 @@ exit:
 ; (iteration space [-100; 100)). Negative test.
 
 define void @test_09(ptr %arr, ptr %a_len_ptr) #0 {
-; CHECK-LABEL: define void @test_09
-; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
+; CHECK-LABEL: define void @test_09(
+; CHECK-SAME: ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
@@ -648,18 +646,3 @@ exit:
 }
 
 !0 = !{i32 0, i32 50}
-;.
-; CHECK: [[RNG0]] = !{i32 0, i32 50}
-; CHECK: [[LOOP1]] = distinct !{[[LOOP1]], [[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]]}
-; CHECK: [[META2]] = !{!"llvm.loop.unroll.disable"}
-; CHECK: [[META3]] = !{!"llvm.loop.vectorize.disable"}
-; CHECK: [[META4]] = !{!"llvm.loop.licm_versioning.disable"}
-; CHECK: [[META5]] = !{!"llvm.loop.distribute.disable"}
-; CHECK: [[META6]] = !{}
-; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META3]], [[META4]], [[META5]]}
-; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META2]], [[META3]], [[META4]], [[META5]]}
-; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META3]], [[META4]], [[META5]]}
-; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META2]], [[META3]], [[META4]], [[META5]]}
-; CHECK: [[LOOP11]] = distinct !{[[LOOP11]], [[META2]], [[META3]], [[META4]], [[META5]]}
-; CHECK: [[LOOP12]] = distinct !{[[LOOP12]], [[META2]], [[META3]], [[META4]], [[META5]]}
-;.
diff --git a/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll b/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll
index 712b6ae399f2e..61ca1d4f016f6 100644
--- a/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll
+++ b/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll
@@ -131,8 +131,7 @@ exit:
 define i32 @test1(ptr %array, i32 %length, i32 %n) #0 {
 ; CHECK-V8M-LABEL: @test1(
 ; CHECK-V8M-NEXT:  loop.preheader:
-; CHECK-V8M-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-V8M-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-V8M-NEXT:    [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
 ; CHECK-V8M-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
 ; CHECK-V8M-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]])
 ; CHECK-V8M-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
@@ -158,8 +157,7 @@ define i32 @test1(ptr %array, i32 %length, i32 %n) #0 {
 ;
 ; CHECK-V8A-LABEL: @test1(
 ; CHECK-V8A-NEXT:  loop.preheader:
-; CHECK-V8A-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-V8A-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-V8A-NEXT:    [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
 ; CHECK-V8A-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
 ; CHECK-V8A-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]])
 ; CHECK-V8A-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
@@ -296,8 +294,7 @@ define i32 @two_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %len
 ; CHECK-V8M-LABEL: @two_range_checks(
 ; CHECK-V8M-NEXT:  loop.preheader:
 ; CHECK-V8M-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_2:%.*]], i32 [[LENGTH_1:%.*]])
-; CHECK-V8M-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-V8M-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-V8M-NEXT:    [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
 ; CHECK-V8M-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
 ; CHECK-V8M-NEXT:    [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[UMIN]])
 ; CHECK-V8M-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[UMIN]], [[UMIN1]]
@@ -327,8 +324,7 @@ define i32 @two_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %len
 ; CHECK-V8A-LABEL: @two_range_checks(
 ; CHECK-V8A-NEXT:  loop.preheader:
 ; CHECK-V8A-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_2:%.*]], i32 [[LENGTH_1:%.*]])
-; CHECK-V8A-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-V8A-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-V8A-NEXT:    [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
 ; CHECK-V8A-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
 ; CHECK-V8A-NEXT:    [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[UMIN]])
 ; CHECK-V8A-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[UMIN]], [[UMIN1]]
@@ -392,8 +388,7 @@ define i32 @three_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %l
 ; CHECK-V8M-NEXT:  loop.preheader:
 ; CHECK-V8M-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_3:%.*]], i32 [[LENGTH_2:%.*]])
 ; CHECK-V8M-NEXT:    [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[LENGTH_1:%.*]])
-; CHECK-V8M-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-V8M-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-V8M-NEXT:    [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
 ; CHECK-V8M-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
 ; CHECK-V8M-NEXT:    [[UMIN2:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[UMIN1]])
 ; CHECK-V8M-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[UMIN1]], [[UMIN2]]
@@ -427,8 +422,7 @@ define i32 @three_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %l
 ; CHECK-V8A-NEXT:  loop.preheader:
 ; CHECK-V8A-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_3:%.*]], i32 [[LENGTH_2:%.*]])
 ; CHECK-V8A-NEXT:    [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[LENGTH_1:%.*]])
-; CHECK-V8A-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-V8A-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-V8A-NEXT:    [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
 ; CHECK-V8A-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
 ; CHECK-V8A-NEXT:    [[UMIN2:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[UMIN1]])
 ; CHECK-V8A-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[UMIN1]], [[UMIN2]]
@@ -499,8 +493,7 @@ exit:                                             ; preds = %guarded, %entry
 define i32 @distinct_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %length.2, ptr %array.3, i32 %length.3, i32 %n) #0 {
 ; CHECK-V8M-LABEL: @distinct_checks(
 ; CHECK-V8M-NEXT:  loop.preheader:
-; CHECK-V8M-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-V8M-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-V8M-NEXT:    [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
 ; CHECK-V8M-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
 ; CHECK-V8M-NEXT:    [[TMP2:%.*]] = freeze i32 [[LENGTH_2:%.*]]
 ; CHECK-V8M-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[TMP2]])
@@ -537,8 +530,7 @@ define i32 @distinct_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %leng
 ;
 ; CHECK-V8A-LABEL: @distinct_checks(
 ; CHECK-V8A-NEXT:  loop.preheader:
-; CHECK-V8A-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-V8A-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-V8A-NEXT:    [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
 ; CHECK-V8A-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
 ; CHECK-V8A-NEXT:    [[TMP2:%.*]] = freeze i32 [[LENGTH_2:%.*]]
 ; CHECK-V8A-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[TMP2]])
@@ -614,8 +606,7 @@ exit:
 define i32 @duplicate_checks(ptr %array.1, ptr %array.2, ptr %array.3, i32 %length, i32 %n) #0 {
 ; CHECK-V8M-LABEL: @duplicate_checks(
 ; CHECK-V8M-NEXT:  loop.preheader:
-; CHECK-V8M-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-V8M-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-V8M-NEXT:    [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
 ; CHECK-V8M-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
 ; CHECK-V8M-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]])
 ; CHECK-V8M-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
@@ -649,8 +640,7 @@ define i32 @duplicate_checks(ptr %array.1, ptr %array.2, ptr %array.3, i32 %leng
 ;
 ; CHECK-V8A-LABEL: @duplicate_checks(
 ; CHECK-V8A-NEXT:  loop.preheader:
-; CHECK-V8A-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-V8A-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-V8A-NEXT:    [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
 ; CHECK-V8A-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
 ; CHECK-V8A-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/216975


More information about the llvm-commits mailing list