[llvm] [CorrelatedValuePropagation] Fold calls to UCMP/SCMP when we know that ranges of operands do not overlap (PR #97235)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 1 11:23:36 PDT 2024
https://github.com/Poseydon42 updated https://github.com/llvm/llvm-project/pull/97235
>From 19157355368bdda8d72b6a86e994c11808140317 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Sun, 30 Jun 2024 22:38:22 +0100
Subject: [PATCH 1/4] [CVP] Fold calls to UCMP/SCMP when we know that ranges of
operands do not overlap
---
.../Scalar/CorrelatedValuePropagation.cpp | 26 ++++
.../CorrelatedValuePropagation/uscmp.ll | 118 ++++++++++++++++++
2 files changed, 144 insertions(+)
create mode 100644 llvm/test/Transforms/CorrelatedValuePropagation/uscmp.ll
diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index 88adeb597e755..853925bba0be1 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -548,6 +548,27 @@ static bool processAbsIntrinsic(IntrinsicInst *II, LazyValueInfo *LVI) {
return false;
}
+static bool processCmpIntrinsic(IntrinsicInst *II, LazyValueInfo *LVI) {
+ bool IsSigned = II->getIntrinsicID() == Intrinsic::scmp;
+ ConstantRange LHS_CR = LVI->getConstantRangeAtUse(II->getOperandUse(0),
+ /*UndefAllowed*/ false);
+ ConstantRange RHS_CR = LVI->getConstantRangeAtUse(II->getOperandUse(1),
+ /*UndefAllowed*/ false);
+
+ if (LHS_CR.icmp(IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT, RHS_CR)) {
+ II->replaceAllUsesWith(ConstantInt::get(II->getType(), 1));
+ II->eraseFromParent();
+ return true;
+ }
+ if (LHS_CR.icmp(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT, RHS_CR)) {
+ II->replaceAllUsesWith(ConstantInt::getSigned(II->getType(), -1));
+ II->eraseFromParent();
+ return true;
+ }
+
+ return false;
+}
+
// See if this min/max intrinsic always picks it's one specific operand.
// If not, check whether we can canonicalize signed minmax into unsigned version
static bool processMinMaxIntrinsic(MinMaxIntrinsic *MM, LazyValueInfo *LVI) {
@@ -639,6 +660,11 @@ static bool processCallSite(CallBase &CB, LazyValueInfo *LVI) {
return processAbsIntrinsic(&cast<IntrinsicInst>(CB), LVI);
}
+ if (CB.getIntrinsicID() == Intrinsic::scmp ||
+ CB.getIntrinsicID() == Intrinsic::ucmp) {
+ return processCmpIntrinsic(&cast<IntrinsicInst>(CB), LVI);
+ }
+
if (auto *MM = dyn_cast<MinMaxIntrinsic>(&CB)) {
return processMinMaxIntrinsic(MM, LVI);
}
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/uscmp.ll b/llvm/test/Transforms/CorrelatedValuePropagation/uscmp.ll
new file mode 100644
index 0000000000000..7a3b815f64f12
--- /dev/null
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/uscmp.ll
@@ -0,0 +1,118 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
+
+; If nothing is known we can't change anything
+define i8 @ucmp_0(i32 %x, i32 %y) {
+ %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+define i8 @scmp_0(i32 %x, i32 %y) {
+ %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+; If we know that range of LHS < range of RHS then return -1
+define i8 @ucmp_1(i32 %x, i32 %y) {
+ ; X is within [4, 8)
+ %cond1 = icmp uge i32 %x, 4
+ call void @llvm.assume(i1 %cond1)
+ %cond2 = icmp ult i32 %x, 8
+ call void @llvm.assume(i1 %cond2)
+ ; Y is within [8, +INF)
+ %cond3 = icmp uge i32 %y, 8
+ call void @llvm.assume(i1 %cond3)
+
+ %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+define i8 @scmp_1(i32 %x, i32 %y) {
+ ; X is within [-5, 3)
+ %cond1 = icmp sge i32 %x, -5
+ call void @llvm.assume(i1 %cond1)
+ %cond2 = icmp slt i32 %x, 3
+ call void @llvm.assume(i1 %cond2)
+ ; Y is within [3, +INF)
+ %cond3 = icmp sge i32 %y, 3
+ call void @llvm.assume(i1 %cond3)
+
+ %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+; If we know that range of LHS > range of RHS then return 1
+define i8 @ucmp_2(i32 %x, i32 %y) {
+ ; X is within [4, +INF)
+ %cond1 = icmp uge i32 %x, 4
+ call void @llvm.assume(i1 %cond1)
+ ; Y is within [0, 4)
+ %cond2 = icmp ult i32 %y, 4
+ call void @llvm.assume(i1 %cond2)
+
+ %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+define i8 @scmp_2(i32 %x, i32 %y) {
+ ; X is within [4, +INF)
+ %cond1 = icmp sge i32 %x, 4
+ call void @llvm.assume(i1 %cond1)
+ ; Y is within [-INF, 4)
+ %cond2 = icmp slt i32 %y, 4
+ call void @llvm.assume(i1 %cond2)
+
+ %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+; Negative test: ranges overlap
+define i8 @ucmp_3(i32 %x, i32 %y) {
+ ; X is within [4, +INF)
+ %cond1 = icmp uge i32 %x, 4
+ call void @llvm.assume(i1 %cond1)
+ ; Y is within [0, 6)
+ %cond2 = icmp ult i32 %y, 6
+ call void @llvm.assume(i1 %cond2)
+
+ %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+define i8 @scmp_3(i32 %x, i32 %y) {
+ ; X is within [2, +INF)
+ %cond1 = icmp sge i32 %x, 2
+ call void @llvm.assume(i1 %cond1)
+ ; Y is within [-INF, 4)
+ %cond2 = icmp slt i32 %y, 4
+ call void @llvm.assume(i1 %cond2)
+
+ %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+; Negative test: mismatched signedness of range-establishing comparisons and
+; of the intrinsic
+define i8 @ucmp_4(i32 %x, i32 %y) {
+ ; X is within [4, +INF)
+ %cond1 = icmp sge i32 %x, 4
+ call void @llvm.assume(i1 %cond1)
+ ; Y is within [0, 4)
+ %cond2 = icmp slt i32 %y, 4
+ call void @llvm.assume(i1 %cond2)
+
+ %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+define i8 @scmp_4(i32 %x, i32 %y) {
+ ; X is within [4, +INF)
+ %cond1 = icmp uge i32 %x, 4
+ call void @llvm.assume(i1 %cond1)
+ ; Y is within [0, 4)
+ %cond2 = icmp ult i32 %y, 4
+ call void @llvm.assume(i1 %cond2)
+
+ %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %1
+}
>From cfb0e07cb88594cdd44081cb0a88e33dae8939ab Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Mon, 1 Jul 2024 14:20:04 +0100
Subject: [PATCH 2/4] Added statistics
---
llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index 853925bba0be1..d59fc48d3c9e8 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -85,6 +85,7 @@ STATISTIC(NumOverflows, "Number of overflow checks removed");
STATISTIC(NumSaturating,
"Number of saturating arithmetics converted to normal arithmetics");
STATISTIC(NumNonNull, "Number of function pointer arguments marked non-null");
+STATISTIC(NumCmpIntr, "Number of llvm.[us]cmp intrinsics removed");
STATISTIC(NumMinMax, "Number of llvm.[us]{min,max} intrinsics removed");
STATISTIC(NumSMinMax,
"Number of llvm.s{min,max} intrinsics simplified to unsigned");
@@ -556,11 +557,13 @@ static bool processCmpIntrinsic(IntrinsicInst *II, LazyValueInfo *LVI) {
/*UndefAllowed*/ false);
if (LHS_CR.icmp(IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT, RHS_CR)) {
+ ++NumCmpIntr;
II->replaceAllUsesWith(ConstantInt::get(II->getType(), 1));
II->eraseFromParent();
return true;
}
if (LHS_CR.icmp(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT, RHS_CR)) {
+ ++NumCmpIntr;
II->replaceAllUsesWith(ConstantInt::getSigned(II->getType(), -1));
II->eraseFromParent();
return true;
>From f6d67d0537a867cbbb32d6f8b73a8c5405829e44 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Mon, 1 Jul 2024 19:22:08 +0100
Subject: [PATCH 3/4] Handle the case where ranges of LHS and RHS are equal and
have width of 1
---
llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index d59fc48d3c9e8..875d3ea78fae5 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -568,6 +568,12 @@ static bool processCmpIntrinsic(IntrinsicInst *II, LazyValueInfo *LVI) {
II->eraseFromParent();
return true;
}
+ if (LHS_CR.icmp(ICmpInst::ICMP_EQ, RHS_CR)) {
+ ++NumCmpIntr;
+ II->replaceAllUsesWith(ConstantInt::get(II->getType(), 0));
+ II->eraseFromParent();
+ return true;
+ }
return false;
}
>From 9f32a46326a6da7954543a425c46ab2ae59adaf7 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Mon, 1 Jul 2024 19:23:03 +0100
Subject: [PATCH 4/4] Add check lines and a few more test cases
---
.../CorrelatedValuePropagation/uscmp.ll | 160 ++++++++++++++++--
1 file changed, 150 insertions(+), 10 deletions(-)
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/uscmp.ll b/llvm/test/Transforms/CorrelatedValuePropagation/uscmp.ll
index 7a3b815f64f12..efe4235b344a6 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/uscmp.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/uscmp.ll
@@ -3,11 +3,19 @@
; If nothing is known we can't change anything
define i8 @ucmp_0(i32 %x, i32 %y) {
+; CHECK-LABEL: @ucmp_0(
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
%1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
ret i8 %1
}
define i8 @scmp_0(i32 %x, i32 %y) {
+; CHECK-LABEL: @scmp_0(
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
%1 = call i8 @llvm.scmp(i32 %x, i32 %y)
ret i8 %1
}
@@ -15,11 +23,20 @@ define i8 @scmp_0(i32 %x, i32 %y) {
; If we know that range of LHS < range of RHS then return -1
define i8 @ucmp_1(i32 %x, i32 %y) {
; X is within [4, 8)
+; CHECK-LABEL: @ucmp_1(
+; CHECK-NEXT: [[COND1:%.*]] = icmp uge i32 [[X:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp ult i32 [[X]], 8
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: [[COND3:%.*]] = icmp uge i32 [[Y:%.*]], 8
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND3]])
+; CHECK-NEXT: ret i8 -1
+;
%cond1 = icmp uge i32 %x, 4
call void @llvm.assume(i1 %cond1)
%cond2 = icmp ult i32 %x, 8
call void @llvm.assume(i1 %cond2)
- ; Y is within [8, +INF)
+ ; Y is within [8, UNSIGNED_MAX)
%cond3 = icmp uge i32 %y, 8
call void @llvm.assume(i1 %cond3)
@@ -29,11 +46,20 @@ define i8 @ucmp_1(i32 %x, i32 %y) {
define i8 @scmp_1(i32 %x, i32 %y) {
; X is within [-5, 3)
+; CHECK-LABEL: @scmp_1(
+; CHECK-NEXT: [[COND1:%.*]] = icmp sge i32 [[X:%.*]], -5
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp slt i32 [[X]], 3
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: [[COND3:%.*]] = icmp sge i32 [[Y:%.*]], 3
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND3]])
+; CHECK-NEXT: ret i8 -1
+;
%cond1 = icmp sge i32 %x, -5
call void @llvm.assume(i1 %cond1)
%cond2 = icmp slt i32 %x, 3
call void @llvm.assume(i1 %cond2)
- ; Y is within [3, +INF)
+ ; Y is within [3, SIGNED_MAX)
%cond3 = icmp sge i32 %y, 3
call void @llvm.assume(i1 %cond3)
@@ -43,7 +69,14 @@ define i8 @scmp_1(i32 %x, i32 %y) {
; If we know that range of LHS > range of RHS then return 1
define i8 @ucmp_2(i32 %x, i32 %y) {
- ; X is within [4, +INF)
+ ; X is within [4, UNSIGNED_MAX)
+; CHECK-LABEL: @ucmp_2(
+; CHECK-NEXT: [[COND1:%.*]] = icmp uge i32 [[X:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp ult i32 [[Y:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: ret i8 1
+;
%cond1 = icmp uge i32 %x, 4
call void @llvm.assume(i1 %cond1)
; Y is within [0, 4)
@@ -55,10 +88,17 @@ define i8 @ucmp_2(i32 %x, i32 %y) {
}
define i8 @scmp_2(i32 %x, i32 %y) {
- ; X is within [4, +INF)
+ ; X is within [4, SIGNED_MAX)
+; CHECK-LABEL: @scmp_2(
+; CHECK-NEXT: [[COND1:%.*]] = icmp sge i32 [[X:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp slt i32 [[Y:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: ret i8 1
+;
%cond1 = icmp sge i32 %x, 4
call void @llvm.assume(i1 %cond1)
- ; Y is within [-INF, 4)
+ ; Y is within [SIGNED_MIN, 4)
%cond2 = icmp slt i32 %y, 4
call void @llvm.assume(i1 %cond2)
@@ -66,9 +106,65 @@ define i8 @scmp_2(i32 %x, i32 %y) {
ret i8 %1
}
+; If we know that LHS and RHS are both constants then return 0
+define i8 @ucmp_5(i32 %x, i32 %y) {
+; CHECK-LABEL: @ucmp_5(
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i32 [[X:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp eq i32 [[Y:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: ret i8 0
+;
+ %cond1 = icmp eq i32 %x, 4
+ call void @llvm.assume(i1 %cond1)
+ %cond2 = icmp eq i32 %y, 4
+ call void @llvm.assume(i1 %cond2)
+
+ %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+define i8 @scmp_5(i32 %x, i32 %y) {
+; CHECK-LABEL: @scmp_5(
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i32 [[X:%.*]], -5
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp eq i32 [[Y:%.*]], -5
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: ret i8 0
+;
+ %cond1 = icmp eq i32 %x, -5
+ call void @llvm.assume(i1 %cond1)
+ %cond2 = icmp eq i32 %y, -5
+ call void @llvm.assume(i1 %cond2)
+
+ %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %1
+}
+
+; We can infer ranges based on the location where a UCMP/SCMP result is used
+define i8 @scmp_6(i32 noundef %x) {
+; CHECK-LABEL: @scmp_6(
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 10
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 -1, i8 5
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp slt i32 %x, 10
+ %2 = call i8 @llvm.scmp(i32 %x, i32 10)
+ %3 = select i1 %1, i8 %2, i8 5
+ ret i8 %3
+}
+
; Negative test: ranges overlap
define i8 @ucmp_3(i32 %x, i32 %y) {
- ; X is within [4, +INF)
+ ; X is within [4, UNSIGNED_MAX)
+; CHECK-LABEL: @ucmp_3(
+; CHECK-NEXT: [[COND1:%.*]] = icmp uge i32 [[X:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp ult i32 [[Y:%.*]], 6
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
%cond1 = icmp uge i32 %x, 4
call void @llvm.assume(i1 %cond1)
; Y is within [0, 6)
@@ -80,10 +176,18 @@ define i8 @ucmp_3(i32 %x, i32 %y) {
}
define i8 @scmp_3(i32 %x, i32 %y) {
- ; X is within [2, +INF)
+ ; X is within [2, SIGNED_MAX)
+; CHECK-LABEL: @scmp_3(
+; CHECK-NEXT: [[COND1:%.*]] = icmp sge i32 [[X:%.*]], 2
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp slt i32 [[Y:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
%cond1 = icmp sge i32 %x, 2
call void @llvm.assume(i1 %cond1)
- ; Y is within [-INF, 4)
+ ; Y is within [SIGNED_MIN, 4)
%cond2 = icmp slt i32 %y, 4
call void @llvm.assume(i1 %cond2)
@@ -94,7 +198,15 @@ define i8 @scmp_3(i32 %x, i32 %y) {
; Negative test: mismatched signedness of range-establishing comparisons and
; of the intrinsic
define i8 @ucmp_4(i32 %x, i32 %y) {
- ; X is within [4, +INF)
+ ; X is within [4, SIGNED_MAX)
+; CHECK-LABEL: @ucmp_4(
+; CHECK-NEXT: [[COND1:%.*]] = icmp sge i32 [[X:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp slt i32 [[Y:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
%cond1 = icmp sge i32 %x, 4
call void @llvm.assume(i1 %cond1)
; Y is within [0, 4)
@@ -106,7 +218,15 @@ define i8 @ucmp_4(i32 %x, i32 %y) {
}
define i8 @scmp_4(i32 %x, i32 %y) {
- ; X is within [4, +INF)
+ ; X is within [4, UNSIGNED_MAX)
+; CHECK-LABEL: @scmp_4(
+; CHECK-NEXT: [[COND1:%.*]] = icmp uge i32 [[X:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp ult i32 [[Y:%.*]], 4
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
%cond1 = icmp uge i32 %x, 4
call void @llvm.assume(i1 %cond1)
; Y is within [0, 4)
@@ -116,3 +236,23 @@ define i8 @scmp_4(i32 %x, i32 %y) {
%1 = call i8 @llvm.scmp(i32 %x, i32 %y)
ret i8 %1
}
+
+; Negative test: ranges are the same, but we can't be sure the values are equal
+define i8 @ucmp_6(i32 %x, i32 %y) {
+ ; Both X and Y are within [0, 10]
+; CHECK-LABEL: @ucmp_6(
+; CHECK-NEXT: [[COND1:%.*]] = icmp ule i32 [[X:%.*]], 10
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp ule i32 [[Y:%.*]], 10
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
+ %cond1 = icmp ule i32 %x, 10
+ call void @llvm.assume(i1 %cond1)
+ %cond2 = icmp ule i32 %y, 10
+ call void @llvm.assume(i1 %cond2)
+
+ %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %1
+}
More information about the llvm-commits
mailing list