[llvm] [Analysis] Use usub_sat during SCEV expansion in some cases (PR #216975)
David Sherwood via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 18 23:49:54 PDT 2026
https://github.com/david-arm updated https://github.com/llvm/llvm-project/pull/216975
>From c0d98f16819242cafbd090bb9cf473bad9006b9d Mon Sep 17 00:00:00 2001
From: David Sherwood <david.sherwood at arm.com>
Date: Wed, 19 Aug 2026 06:48:44 +0000
Subject: [PATCH] [Analysis] Use usub_sat during SCEV expansion in some cases
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.
---
.../Analysis/ScalarEvolutionPatternMatch.h | 6 ++
.../Utils/ScalarEvolutionExpander.cpp | 14 ++++-
.../IRCE/unsigned_comparisons_ugt.ll | 43 +++++---------
.../IRCE/unsigned_comparisons_ult.ll | 57 +++++++------------
.../IndVarSimplify/ARM/code-size.ll | 36 ++++--------
.../IndVarSimplify/loop-predication.ll | 18 ++----
.../IndVarSimplify/turn-to-invariant.ll | 4 +-
.../LoopPredication/predicate-exits.ll | 25 +++-----
.../AArch64/induction-costs-sve.ll | 14 ++---
.../LoopVectorize/AArch64/induction-costs.ll | 7 +--
.../AArch64/simple_early_exit.ll | 3 +-
.../LoopVectorize/X86/cost-model.ll | 9 +--
.../alias-mask-data-tail-folding-style.ll | 3 +-
.../first-order-recurrence-complex.ll | 6 +-
.../LoopVectorize/iv_outside_user.ll | 3 +-
.../LoopVectorize/load-deref-pred-align.ll | 3 +-
.../LoopVectorize/pointer-induction.ll | 6 +-
...-first-order-recurrence-by-versioned-iv.ll | 3 +-
.../runtime-check-small-bounded-ranges.ll | 3 +-
.../LoopVectorize/single_early_exit.ll | 3 +-
20 files changed, 102 insertions(+), 164 deletions(-)
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:%.*]])
; CHECK-V8A-NEXT: [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
@@ -727,8 +717,7 @@ define i32 @different_ivs(ptr %array, i32 %length, i32 %n) #0 {
; CHECK-V8M-LABEL: @different_ivs(
; CHECK-V8M-NEXT: loop.preheader:
; CHECK-V8M-NEXT: [[N64:%.*]] = zext i32 [[N:%.*]] to i64
-; CHECK-V8M-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N64]], i64 1)
-; CHECK-V8M-NEXT: [[TMP0:%.*]] = add nsw i64 [[UMAX]], -1
+; CHECK-V8M-NEXT: [[TMP0:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N64]], i64 1)
; CHECK-V8M-NEXT: [[TMP1:%.*]] = freeze i64 [[TMP0]]
; CHECK-V8M-NEXT: [[TMP2:%.*]] = zext i32 [[LENGTH:%.*]] to i64
; CHECK-V8M-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[TMP2]])
@@ -756,8 +745,7 @@ define i32 @different_ivs(ptr %array, i32 %length, i32 %n) #0 {
; CHECK-V8A-LABEL: @different_ivs(
; CHECK-V8A-NEXT: loop.preheader:
; CHECK-V8A-NEXT: [[N64:%.*]] = zext i32 [[N:%.*]] to i64
-; CHECK-V8A-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N64]], i64 1)
-; CHECK-V8A-NEXT: [[TMP0:%.*]] = add nsw i64 [[UMAX]], -1
+; CHECK-V8A-NEXT: [[TMP0:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N64]], i64 1)
; CHECK-V8A-NEXT: [[TMP1:%.*]] = freeze i64 [[TMP0]]
; CHECK-V8A-NEXT: [[TMP2:%.*]] = zext i32 [[LENGTH:%.*]] to i64
; CHECK-V8A-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[TMP2]])
diff --git a/llvm/test/Transforms/IndVarSimplify/loop-predication.ll b/llvm/test/Transforms/IndVarSimplify/loop-predication.ll
index 8ccd227bed4ff..b02b9d71c37c4 100644
--- a/llvm/test/Transforms/IndVarSimplify/loop-predication.ll
+++ b/llvm/test/Transforms/IndVarSimplify/loop-predication.ll
@@ -7,8 +7,7 @@ declare void @prevent_merging()
define i32 @test1(ptr %array, i32 %length, i32 %n) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: loop.preheader:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]]
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]])
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
@@ -231,8 +230,7 @@ define i32 @two_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %len
; CHECK-LABEL: @two_range_checks(
; CHECK-NEXT: loop.preheader:
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_2:%.*]], i32 [[LENGTH_1:%.*]])
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]]
; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[UMIN]])
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[UMIN]], [[UMIN1]]
@@ -296,8 +294,7 @@ define i32 @three_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %l
; CHECK-NEXT: loop.preheader:
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_3:%.*]], i32 [[LENGTH_2:%.*]])
; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[LENGTH_1:%.*]])
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]]
; CHECK-NEXT: [[UMIN2:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[UMIN1]])
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[UMIN1]], [[UMIN2]]
@@ -368,8 +365,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) {
; CHECK-LABEL: @distinct_checks(
; CHECK-NEXT: loop.preheader:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]]
; CHECK-NEXT: [[TMP2:%.*]] = freeze i32 [[LENGTH_2:%.*]]
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[TMP2]])
@@ -445,8 +441,7 @@ exit:
define i32 @duplicate_checks(ptr %array.1, ptr %array.2, ptr %array.3, i32 %length, i32 %n) {
; CHECK-LABEL: @duplicate_checks(
; CHECK-NEXT: loop.preheader:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[TMP0]]
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]])
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
@@ -639,8 +634,7 @@ define i32 @different_ivs(ptr %array, i32 %length, i32 %n) {
; CHECK-LABEL: @different_ivs(
; CHECK-NEXT: loop.preheader:
; CHECK-NEXT: [[N64:%.*]] = zext i32 [[N:%.*]] to i64
-; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N64]], i64 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N64]], i64 1)
; CHECK-NEXT: [[TMP1:%.*]] = freeze i64 [[TMP0]]
; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[LENGTH:%.*]] to i64
; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[TMP2]])
diff --git a/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll b/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll
index c013c91900fee..406b6ecd944f4 100644
--- a/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll
+++ b/llvm/test/Transforms/IndVarSimplify/turn-to-invariant.ll
@@ -925,9 +925,7 @@ constant_check_failed:
define i32 @test_predicated_backedge_no_side_exit(i32 %len) {
; CHECK-LABEL: @test_predicated_backedge_no_side_exit(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
-; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LEN]], i32 [[TMP0]])
+; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[LEN:%.*]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[LEN]], [[UMIN]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
diff --git a/llvm/test/Transforms/LoopPredication/predicate-exits.ll b/llvm/test/Transforms/LoopPredication/predicate-exits.ll
index e72a797f9a0f1..fa0dc27fc78e5 100644
--- a/llvm/test/Transforms/LoopPredication/predicate-exits.ll
+++ b/llvm/test/Transforms/LoopPredication/predicate-exits.ll
@@ -9,8 +9,7 @@ define i32 @test1(ptr %array, i32 %length, i32 %n, i1 %cond_0) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH:%.*]], i32 [[TMP0]])
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[LENGTH]], [[UMIN]]
; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
@@ -90,9 +89,7 @@ define i32 @test_non_canonical(ptr %array, i32 %length, i1 %cond_0) {
; CHECK-LABEL: @test_non_canonical(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LENGTH:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
-; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH]], i32 [[TMP0]])
+; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[LENGTH:%.*]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[LENGTH]], [[UMIN]]
; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[COND_0:%.*]]
@@ -171,8 +168,7 @@ define i32 @test_two_range_checks(ptr %array, i32 %length.1, i32 %length.2, i32
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_2:%.*]], i32 [[LENGTH_1:%.*]])
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[TMP0]])
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[LENGTH_1]], [[UMIN1]]
; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
@@ -346,8 +342,7 @@ define i32 @test_unanalyzeable_exit2(ptr %array, i32 %length, i32 %n, i1 %cond_0
; CHECK-LABEL: @test_unanalyzeable_exit2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH:%.*]], i32 [[TMP0]])
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[LENGTH]], [[UMIN]]
; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
@@ -673,8 +668,7 @@ define i32 @unswitch_exit_form(ptr %array, i32 %length, i32 %n, i1 %cond_0) {
; CHECK-LABEL: @unswitch_exit_form(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH:%.*]], i32 [[TMP0]])
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[LENGTH]], [[UMIN]]
; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
@@ -756,8 +750,7 @@ define i32 @swapped_wb(ptr %array, i32 %length, i32 %n, i1 %cond_0) {
; CHECK-LABEL: @swapped_wb(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH:%.*]], i32 [[TMP0]])
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[LENGTH]], [[UMIN]]
; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
@@ -834,8 +827,7 @@ exit:
define i32 @trivial_wb(ptr %array, i32 %length, i32 %n) {
; CHECK-LABEL: @trivial_wb(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH:%.*]], i32 [[TMP0]])
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[LENGTH]], [[UMIN]]
; CHECK-NEXT: [[TMP2:%.*]] = freeze i1 [[TMP1]]
@@ -983,8 +975,7 @@ define i32 @wb_in_loop(ptr %array, i32 %length, i32 %n, i1 %cond_0) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N:%.*]], i32 1)
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH:%.*]], i32 [[TMP0]])
; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i32 [[LENGTH]], [[UMIN]]
; CHECK-NEXT: [[TMP5:%.*]] = freeze i1 [[TMP4]]
diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/induction-costs-sve.ll b/llvm/test/Transforms/LoopVectorize/AArch64/induction-costs-sve.ll
index aa192fc9d4d67..d22c124617e51 100644
--- a/llvm/test/Transforms/LoopVectorize/AArch64/induction-costs-sve.ll
+++ b/llvm/test/Transforms/LoopVectorize/AArch64/induction-costs-sve.ll
@@ -559,8 +559,7 @@ define void @exit_cond_zext_iv_store32(ptr %dst, i64 %N) {
; DEFAULT-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 4
; DEFAULT-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
; DEFAULT: [[VECTOR_SCEVCHECK]]:
-; DEFAULT-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1)
-; DEFAULT-NEXT: [[TMP1:%.*]] = add i64 [[UMAX]], -1
+; DEFAULT-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 1)
; DEFAULT-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
; DEFAULT-NEXT: [[TMP3:%.*]] = add i32 1, [[TMP2]]
; DEFAULT-NEXT: [[TMP4:%.*]] = icmp ult i32 [[TMP3]], 1
@@ -613,8 +612,7 @@ define void @exit_cond_zext_iv_store32(ptr %dst, i64 %N) {
; PRED-NEXT: [[TMP0:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1)
; PRED-NEXT: br label %[[VECTOR_SCEVCHECK:.*]]
; PRED: [[VECTOR_SCEVCHECK]]:
-; PRED-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1)
-; PRED-NEXT: [[TMP1:%.*]] = add i64 [[UMAX]], -1
+; PRED-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 1)
; PRED-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
; PRED-NEXT: [[TMP3:%.*]] = add i32 1, [[TMP2]]
; PRED-NEXT: [[TMP4:%.*]] = icmp ult i32 [[TMP3]], 1
@@ -690,11 +688,10 @@ define void @exit_cond_zext_iv_store64(ptr %dst, i64 %N) {
; DEFAULT-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) {
; DEFAULT-NEXT: [[ENTRY:.*]]:
; DEFAULT-NEXT: [[TMP0:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1)
-; DEFAULT-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 18
+; DEFAULT-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 16
; DEFAULT-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
; DEFAULT: [[VECTOR_SCEVCHECK]]:
-; DEFAULT-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1)
-; DEFAULT-NEXT: [[TMP1:%.*]] = add i64 [[UMAX]], -1
+; DEFAULT-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 1)
; DEFAULT-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
; DEFAULT-NEXT: [[TMP3:%.*]] = add i32 1, [[TMP2]]
; DEFAULT-NEXT: [[TMP4:%.*]] = icmp ult i32 [[TMP3]], 1
@@ -740,8 +737,7 @@ define void @exit_cond_zext_iv_store64(ptr %dst, i64 %N) {
; PRED-NEXT: [[TMP0:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1)
; PRED-NEXT: br label %[[VECTOR_SCEVCHECK:.*]]
; PRED: [[VECTOR_SCEVCHECK]]:
-; PRED-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1)
-; PRED-NEXT: [[TMP1:%.*]] = add i64 [[UMAX]], -1
+; PRED-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 1)
; PRED-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
; PRED-NEXT: [[TMP3:%.*]] = add i32 1, [[TMP2]]
; PRED-NEXT: [[TMP4:%.*]] = icmp ult i32 [[TMP3]], 1
diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/induction-costs.ll b/llvm/test/Transforms/LoopVectorize/AArch64/induction-costs.ll
index 356e12a532c13..4fd28c6514ec5 100644
--- a/llvm/test/Transforms/LoopVectorize/AArch64/induction-costs.ll
+++ b/llvm/test/Transforms/LoopVectorize/AArch64/induction-costs.ll
@@ -366,8 +366,7 @@ define void @zext_iv_increment(ptr %dst, i64 %N) {
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[UMAX1]], 4
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
; CHECK: [[VECTOR_SCEVCHECK]]:
-; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 1)
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i32
; CHECK-NEXT: [[TMP2:%.*]] = add i32 1, [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 1
@@ -941,7 +940,7 @@ define i64 @live_out_extract_from_ptr_iv_increment(i64 %count, ptr %start, ptr n
; CHECK-NEXT: [[TMP131:%.*]] = insertelement <8 x ptr> [[TMP130]], ptr [[TMP123]], i64 7
; CHECK-NEXT: [[INDEX_NEXT28]] = add nuw i64 [[INDEX19]], 8
; CHECK-NEXT: [[TMP132:%.*]] = icmp eq i64 [[INDEX_NEXT28]], [[N_VEC18]]
-; CHECK-NEXT: br i1 [[TMP132]], label %[[VEC_EPILOG_MIDDLE_BLOCK:.*]], label %[[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP27:![0-9]+]]
+; CHECK-NEXT: br i1 [[TMP132]], label %[[VEC_EPILOG_MIDDLE_BLOCK:.*]], label %[[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]]
; CHECK: [[VEC_EPILOG_MIDDLE_BLOCK]]:
; CHECK-NEXT: [[TMP133:%.*]] = ptrtoint <8 x ptr> [[TMP131]] to <8 x i64>
; CHECK-NEXT: [[TMP134:%.*]] = extractelement <8 x i64> [[TMP133]], i64 7
@@ -961,7 +960,7 @@ define i64 @live_out_extract_from_ptr_iv_increment(i64 %count, ptr %start, ptr n
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
; CHECK-NEXT: [[PTR_INT:%.*]] = ptrtoint ptr [[PTR_IV_NEXT]] to i64
; CHECK-NEXT: [[EC:%.*]] = icmp ult i64 [[IV]], [[COUNT]]
-; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT]], !llvm.loop [[LOOP28:![0-9]+]]
+; CHECK-NEXT: br i1 [[EC]], label %[[LOOP]], label %[[EXIT]], !llvm.loop [[LOOP29:![0-9]+]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: [[PTR_INT_LCSSA:%.*]] = phi i64 [ [[PTR_INT]], %[[LOOP]] ], [ [[TMP87]], %[[MIDDLE_BLOCK]] ], [ [[TMP134]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ]
; CHECK-NEXT: ret i64 [[PTR_INT_LCSSA]]
diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/simple_early_exit.ll b/llvm/test/Transforms/LoopVectorize/AArch64/simple_early_exit.ll
index 9ac7f35e67252..07883e5c4bbe9 100644
--- a/llvm/test/Transforms/LoopVectorize/AArch64/simple_early_exit.ll
+++ b/llvm/test/Transforms/LoopVectorize/AArch64/simple_early_exit.ll
@@ -366,8 +366,7 @@ define i32 @diff_exit_block_needs_scev_check(i32 %end) {
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP2]], 8
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
; CHECK: [[VECTOR_SCEVCHECK]]:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[END_CLAMPED]], i32 1)
-; CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[END_CLAMPED]], i32 1)
; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i8
; CHECK-NEXT: [[TMP5:%.*]] = add i8 1, [[TMP4]]
; CHECK-NEXT: [[TMP6:%.*]] = icmp ult i8 [[TMP5]], 1
diff --git a/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll b/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll
index b75d41907ee90..286bf2ebf47f5 100644
--- a/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll
+++ b/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll
@@ -449,16 +449,14 @@ define void @multi_exit(ptr %dst, ptr %src.1, ptr %src.2, i64 %A, i64 %B) #0 {
; CHECK-LABEL: define void @multi_exit(
; CHECK-SAME: ptr [[DST:%.*]], ptr [[SRC_1:%.*]], ptr [[SRC_2:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[UMAX9:%.*]] = call i64 @llvm.umax.i64(i64 [[B]], i64 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[UMAX9]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[B]], i64 1)
; CHECK-NEXT: [[TMP1:%.*]] = freeze i64 [[TMP0]]
; CHECK-NEXT: [[UMIN10:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[A]])
; CHECK-NEXT: [[TMP2:%.*]] = add nuw i64 [[UMIN10]], 1
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP2]], 24
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
; CHECK: [[VECTOR_SCEVCHECK]]:
-; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[B]], i64 1)
-; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[UMAX]], -1
+; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[B]], i64 1)
; CHECK-NEXT: [[TMP4:%.*]] = freeze i64 [[TMP3]]
; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP4]], i64 [[A]])
; CHECK-NEXT: [[TMP5:%.*]] = trunc i64 [[UMIN]] to i32
@@ -474,8 +472,7 @@ define void @multi_exit(ptr %dst, ptr %src.1, ptr %src.2, i64 %A, i64 %B) #0 {
; CHECK: [[VECTOR_MEMCHECK]]:
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[DST]], i64 1
; CHECK-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[SRC_2]], i64 8
-; CHECK-NEXT: [[UMAX3:%.*]] = call i64 @llvm.umax.i64(i64 [[B]], i64 1)
-; CHECK-NEXT: [[TMP15:%.*]] = add i64 [[UMAX3]], -1
+; CHECK-NEXT: [[TMP15:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[B]], i64 1)
; CHECK-NEXT: [[TMP16:%.*]] = freeze i64 [[TMP15]]
; CHECK-NEXT: [[UMIN4:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP16]], i64 [[A]])
; CHECK-NEXT: [[TMP17:%.*]] = shl i64 [[UMIN4]], 3
diff --git a/llvm/test/Transforms/LoopVectorize/alias-mask-data-tail-folding-style.ll b/llvm/test/Transforms/LoopVectorize/alias-mask-data-tail-folding-style.ll
index 1062bf59e0c58..674676d21101b 100644
--- a/llvm/test/Transforms/LoopVectorize/alias-mask-data-tail-folding-style.ll
+++ b/llvm/test/Transforms/LoopVectorize/alias-mask-data-tail-folding-style.ll
@@ -10,8 +10,7 @@ define void @test(ptr %src, ptr %dst, i32 %n) {
; CHECK-NEXT: [[UMAX3:%.*]] = call i32 @llvm.umax.i32(i32 [[N]], i32 1)
; CHECK-NEXT: br label %[[VECTOR_SCEVCHECK:.*]]
; CHECK: [[VECTOR_SCEVCHECK]]:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[TMP0]], 0
; CHECK-NEXT: br i1 [[TMP1]], label %[[SCALAR_PH:.*]], label %[[VECTOR_CLAMPED_VF_CHECK:.*]]
; CHECK: [[VECTOR_CLAMPED_VF_CHECK]]:
diff --git a/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll b/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll
index a07345cd46b77..7cd5faf5dd9bd 100644
--- a/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll
+++ b/llvm/test/Transforms/LoopVectorize/first-order-recurrence-complex.ll
@@ -785,8 +785,7 @@ define void @sink_dominance(ptr %ptr, i32 %N) {
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[UMAX1]], 4
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]]
; CHECK: vector.scevcheck:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[TMP0]], 0
; CHECK-NEXT: br i1 [[TMP1]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]
; CHECK: vector.ph:
@@ -864,8 +863,7 @@ define void @sink_dominance_2(ptr %ptr, i32 %N) {
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[UMAX1]], 4
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]]
; CHECK: vector.scevcheck:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[TMP0]], 0
; CHECK-NEXT: br i1 [[TMP1]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]
; CHECK: vector.ph:
diff --git a/llvm/test/Transforms/LoopVectorize/iv_outside_user.ll b/llvm/test/Transforms/LoopVectorize/iv_outside_user.ll
index ea41682f00e08..8448f3eaba7d1 100644
--- a/llvm/test/Transforms/LoopVectorize/iv_outside_user.ll
+++ b/llvm/test/Transforms/LoopVectorize/iv_outside_user.ll
@@ -1426,8 +1426,7 @@ define i32 @added_step(i32 %n, i32 %step_base, ptr %p) {
; VEC-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[UMAX1]], 2
; VEC-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
; VEC: [[VECTOR_SCEVCHECK]]:
-; VEC-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N]], i32 1)
-; VEC-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; VEC-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N]], i32 1)
; VEC-NEXT: [[TMP1:%.*]] = icmp slt i32 [[TMP0]], 0
; VEC-NEXT: br i1 [[TMP1]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]]
; VEC: [[VECTOR_PH]]:
diff --git a/llvm/test/Transforms/LoopVectorize/load-deref-pred-align.ll b/llvm/test/Transforms/LoopVectorize/load-deref-pred-align.ll
index bc5450eb79f4f..fc90697140265 100644
--- a/llvm/test/Transforms/LoopVectorize/load-deref-pred-align.ll
+++ b/llvm/test/Transforms/LoopVectorize/load-deref-pred-align.ll
@@ -166,8 +166,7 @@ define i32 @loop_requires_scev_predicate(ptr %dest, i32 %end) {
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[UMAX1]], 2
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]]
; CHECK: vector.scevcheck:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[END_CLAMPED]], i32 1)
-; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[END_CLAMPED]], i32 1)
; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
; CHECK-NEXT: [[TMP4:%.*]] = add i8 1, [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i8 [[TMP4]], 1
diff --git a/llvm/test/Transforms/LoopVectorize/pointer-induction.ll b/llvm/test/Transforms/LoopVectorize/pointer-induction.ll
index 1894e4b2e8b30..0ee54814ae02e 100644
--- a/llvm/test/Transforms/LoopVectorize/pointer-induction.ll
+++ b/llvm/test/Transforms/LoopVectorize/pointer-induction.ll
@@ -284,8 +284,7 @@ define void @outside_lattice(ptr noalias %p, ptr noalias %q, i32 %n) {
; DEFAULT-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], 4
; DEFAULT-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]]
; DEFAULT: vector.scevcheck:
-; DEFAULT-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N]], i32 1)
-; DEFAULT-NEXT: [[TMP2:%.*]] = add i32 [[UMAX]], -1
+; DEFAULT-NEXT: [[TMP2:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N]], i32 1)
; DEFAULT-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 0
; DEFAULT-NEXT: br i1 [[TMP3]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]
; DEFAULT: vector.ph:
@@ -338,8 +337,7 @@ define void @outside_lattice(ptr noalias %p, ptr noalias %q, i32 %n) {
; STRIDED-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], 4
; STRIDED-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]]
; STRIDED: vector.scevcheck:
-; STRIDED-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N]], i32 1)
-; STRIDED-NEXT: [[TMP2:%.*]] = add i32 [[UMAX]], -1
+; STRIDED-NEXT: [[TMP2:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[N]], i32 1)
; STRIDED-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 0
; STRIDED-NEXT: br i1 [[TMP3]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]
; STRIDED: vector.ph:
diff --git a/llvm/test/Transforms/LoopVectorize/replace-first-order-recurrence-by-versioned-iv.ll b/llvm/test/Transforms/LoopVectorize/replace-first-order-recurrence-by-versioned-iv.ll
index c82e72aa7b118..1baef57e6eb2f 100644
--- a/llvm/test/Transforms/LoopVectorize/replace-first-order-recurrence-by-versioned-iv.ll
+++ b/llvm/test/Transforms/LoopVectorize/replace-first-order-recurrence-by-versioned-iv.ll
@@ -570,8 +570,7 @@ define void @induction_with_predicate_replaceable_by_for(ptr %dst, i32 %len) {
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[UMAX1]], 4
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
; CHECK: [[VECTOR_PH]]:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)
-; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[LEN]], i32 1)
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[TMP0]], 255
; CHECK-NEXT: br i1 [[TMP1]], label %[[SCALAR_PH]], label %[[VECTOR_PH1:.*]]
; CHECK: [[VECTOR_PH1]]:
diff --git a/llvm/test/Transforms/LoopVectorize/runtime-check-small-bounded-ranges.ll b/llvm/test/Transforms/LoopVectorize/runtime-check-small-bounded-ranges.ll
index fa5ca7159365c..784dcab3e7847 100644
--- a/llvm/test/Transforms/LoopVectorize/runtime-check-small-bounded-ranges.ll
+++ b/llvm/test/Transforms/LoopVectorize/runtime-check-small-bounded-ranges.ll
@@ -497,8 +497,7 @@ define void @wider_nusw_does_not_imply_narrower(ptr %dst, i64 %n) {
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP1]], 4
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
; CHECK: [[VECTOR_SCEVCHECK]]:
-; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1)
-; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[UMAX]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 1)
; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i32
; CHECK-NEXT: [[TMP4:%.*]] = add i32 1, [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 1
diff --git a/llvm/test/Transforms/LoopVectorize/single_early_exit.ll b/llvm/test/Transforms/LoopVectorize/single_early_exit.ll
index 5883771e29def..533a8345f7631 100644
--- a/llvm/test/Transforms/LoopVectorize/single_early_exit.ll
+++ b/llvm/test/Transforms/LoopVectorize/single_early_exit.ll
@@ -143,8 +143,7 @@ define i32 @diff_exit_block_needs_scev_check(i32 %end) {
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[UMAX1]], 4
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]]
; CHECK: vector.scevcheck:
-; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[END_CLAMPED]], i32 1)
-; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[UMAX]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[END_CLAMPED]], i32 1)
; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8
; CHECK-NEXT: [[TMP4:%.*]] = add i8 1, [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i8 [[TMP4]], 1
More information about the llvm-commits
mailing list