[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