[llvm] [InstSimplify] Implement simple folds for `ucmp`/`scmp` intrinsics (PR #95601)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 15 14:35:26 PDT 2024
https://github.com/Poseydon42 updated https://github.com/llvm/llvm-project/pull/95601
>From 2783c2d50ed8819856bbdfd07cbd106694541c11 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Fri, 14 Jun 2024 21:33:09 +0100
Subject: [PATCH 1/4] [InstSimplify] Add tests for some folds for UCMP/SCMP
intrinsics
This adds tests for the following folds:
- cmp x, x => 0
- cmp x, <something greater than x> => 1
- cmp x, <something equal to x> => 0
- cmp x, <something less than x> => -1
---
llvm/test/Transforms/InstSimplify/uscmp.ll | 221 +++++++++++++++++++++
1 file changed, 221 insertions(+)
diff --git a/llvm/test/Transforms/InstSimplify/uscmp.ll b/llvm/test/Transforms/InstSimplify/uscmp.ll
index adfcc313eff9e..a5c431ce76000 100644
--- a/llvm/test/Transforms/InstSimplify/uscmp.ll
+++ b/llvm/test/Transforms/InstSimplify/uscmp.ll
@@ -96,3 +96,224 @@ define <4 x i8> @scmp_nonsplat() {
%1 = call <4 x i8> @llvm.scmp(<4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32> <i32 -1, i32 1, i32 -2, i32 4>)
ret <4 x i8> %1
}
+
+define i8 @scmp_with_itself(i32 %x) {
+; CHECK-LABEL: define i8 @scmp_with_itself(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[X]])
+; CHECK-NEXT: ret i8 [[TMP1]]
+;
+ %1 = call i8 @llvm.scmp(i32 %x, i32 %x)
+ ret i8 %1
+}
+
+define <4 x i8> @ucmp_vec_with_itself(<4 x i32> %x) {
+; CHECK-LABEL: define <4 x i8> @ucmp_vec_with_itself(
+; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i8> @llvm.scmp.v4i8.v4i32(<4 x i32> [[X]], <4 x i32> [[X]])
+; CHECK-NEXT: ret <4 x i8> [[TMP1]]
+;
+ %1 = call <4 x i8> @llvm.scmp(<4 x i32> %x, <4 x i32> %x)
+ ret <4 x i8> %1
+}
+
+define i8 @scmp_known_gt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i8 @scmp_known_gt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp sgt i32 %x, %y
+ call void @llvm.assume(i1 %1)
+
+ %2 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %2
+}
+
+define i8 @scmp_known_eq(i32 %x, i32 %y) {
+; CHECK-LABEL: define i8 @scmp_known_eq(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp eq i32 %x, %y
+ call void @llvm.assume(i1 %1)
+
+ %2 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %2
+}
+
+define i8 @scmp_known_lt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i8 @scmp_known_lt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp slt i32 %x, %y
+ call void @llvm.assume(i1 %1)
+
+ %2 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %2
+}
+
+define i8 @ucmp_known_gt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i8 @ucmp_known_gt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp ugt i32 %x, %y
+ call void @llvm.assume(i1 %1)
+
+ %2 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %2
+}
+
+define i8 @ucmp_known_eq(i32 %x, i32 %y) {
+; CHECK-LABEL: define i8 @ucmp_known_eq(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp eq i32 %x, %y
+ call void @llvm.assume(i1 %1)
+
+ %2 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %2
+}
+
+define i8 @ucmp_known_lt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i8 @ucmp_known_lt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp ult i32 %x, %y
+ call void @llvm.assume(i1 %1)
+
+ %2 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %2
+}
+
+define i8 @ucmp_with_addition(i32 %x) {
+; CHECK-LABEL: define i8 @ucmp_with_addition(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[X]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[TMP1]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = add nuw i32 %x, 1
+ %2 = call i8 @llvm.ucmp(i32 %x, i32 %1)
+ ret i8 %2
+}
+
+define i8 @ucmp_with_addition2(i32 %x) {
+; CHECK-LABEL: define i8 @ucmp_with_addition2(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[X]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[TMP1]], i32 [[X]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = add nuw i32 %x, 1
+ %2 = call i8 @llvm.ucmp(i32 %1, i32 %x)
+ ret i8 %2
+}
+
+; Negative case: mismatched signedness of predicates
+define i8 @scmp_known_ugt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i8 @scmp_known_ugt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp ugt i32 %x, %y
+ call void @llvm.assume(i1 %1)
+
+ %2 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %2
+}
+
+define i8 @scmp_known_ult(i32 %x, i32 %y) {
+; CHECK-LABEL: define i8 @scmp_known_ult(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp ult i32 %x, %y
+ call void @llvm.assume(i1 %1)
+
+ %2 = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %2
+}
+
+define i8 @ucmp_known_sgt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i8 @ucmp_known_sgt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp sgt i32 %x, %y
+ call void @llvm.assume(i1 %1)
+
+ %2 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %2
+}
+
+define i8 @ucmp_known_slt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i8 @ucmp_known_slt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = icmp slt i32 %x, %y
+ call void @llvm.assume(i1 %1)
+
+ %2 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %2
+}
+
+; Negative case: no nuw flag
+define i8 @ucmp_with_addition_no_nuw(i32 %x) {
+; CHECK-LABEL: define i8 @ucmp_with_addition_no_nuw(
+; CHECK-SAME: i32 [[X:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[TMP1]])
+; CHECK-NEXT: ret i8 [[TMP2]]
+;
+ %1 = add i32 %x, 1
+ %2 = call i8 @llvm.ucmp(i32 %x, i32 %1)
+ ret i8 %2
+}
+
+; Negative case: vector types are not (yet) supported
+define <4 x i8> @scmp_with_addition_vec(<4 x i32> %x) {
+; CHECK-LABEL: define <4 x i8> @scmp_with_addition_vec(
+; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = add nuw <4 x i32> [[X]], <i32 1, i32 1, i32 1, i32 1>
+; CHECK-NEXT: [[TMP2:%.*]] = call <4 x i8> @llvm.scmp.v4i8.v4i32(<4 x i32> [[X]], <4 x i32> [[TMP1]])
+; CHECK-NEXT: ret <4 x i8> [[TMP2]]
+;
+ %1 = add nuw <4 x i32> %x, splat(i32 1)
+ %2 = call <4 x i8> @llvm.scmp(<4 x i32> %x, <4 x i32> %1)
+ ret <4 x i8> %2
+}
>From 94054ac7f6c61edccc19da83b44873780b2acaf1 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Sat, 15 Jun 2024 20:46:54 +0100
Subject: [PATCH 2/4] [InstSimplify] Implement folds of UCMP/SCMP when we know
the relationship between operands
---
llvm/lib/Analysis/InstructionSimplify.cpp | 23 ++++++++++++++++
llvm/test/Transforms/InstSimplify/uscmp.ll | 32 +++++++---------------
2 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 8b2aa6b9f18b0..78047c580ad22 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6505,6 +6505,29 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
break;
}
+ case Intrinsic::scmp:
+ case Intrinsic::ucmp: {
+ // Fold cmp x, x -> 0
+ if (Op0 == Op1)
+ return Constant::getNullValue(ReturnType);
+
+ // Fold to a constant if the relationship between operands can be
+ // established with certainty
+ if (isICmpTrue(CmpInst::ICMP_EQ, Op0, Op1, Q, RecursionLimit))
+ return Constant::getNullValue(ReturnType);
+
+ ICmpInst::Predicate PredGT =
+ IID == Intrinsic::scmp ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
+ if (isICmpTrue(PredGT, Op0, Op1, Q, RecursionLimit))
+ return ConstantInt::get(ReturnType, 1);
+
+ ICmpInst::Predicate PredLT =
+ IID == Intrinsic::scmp ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
+ if (isICmpTrue(PredLT, Op0, Op1, Q, RecursionLimit))
+ return ConstantInt::get(ReturnType, -1, /*IsSigned*/ true);
+
+ break;
+ }
case Intrinsic::usub_with_overflow:
case Intrinsic::ssub_with_overflow:
// X - X -> { 0, false }
diff --git a/llvm/test/Transforms/InstSimplify/uscmp.ll b/llvm/test/Transforms/InstSimplify/uscmp.ll
index a5c431ce76000..616dc0d5d9d39 100644
--- a/llvm/test/Transforms/InstSimplify/uscmp.ll
+++ b/llvm/test/Transforms/InstSimplify/uscmp.ll
@@ -100,8 +100,7 @@ define <4 x i8> @scmp_nonsplat() {
define i8 @scmp_with_itself(i32 %x) {
; CHECK-LABEL: define i8 @scmp_with_itself(
; CHECK-SAME: i32 [[X:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[X]])
-; CHECK-NEXT: ret i8 [[TMP1]]
+; CHECK-NEXT: ret i8 0
;
%1 = call i8 @llvm.scmp(i32 %x, i32 %x)
ret i8 %1
@@ -110,8 +109,7 @@ define i8 @scmp_with_itself(i32 %x) {
define <4 x i8> @ucmp_vec_with_itself(<4 x i32> %x) {
; CHECK-LABEL: define <4 x i8> @ucmp_vec_with_itself(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i8> @llvm.scmp.v4i8.v4i32(<4 x i32> [[X]], <4 x i32> [[X]])
-; CHECK-NEXT: ret <4 x i8> [[TMP1]]
+; CHECK-NEXT: ret <4 x i8> zeroinitializer
;
%1 = call <4 x i8> @llvm.scmp(<4 x i32> %x, <4 x i32> %x)
ret <4 x i8> %1
@@ -122,8 +120,7 @@ define i8 @scmp_known_gt(i32 %x, i32 %y) {
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X]], [[Y]]
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
-; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT: ret i8 [[TMP2]]
+; CHECK-NEXT: ret i8 1
;
%1 = icmp sgt i32 %x, %y
call void @llvm.assume(i1 %1)
@@ -137,8 +134,7 @@ define i8 @scmp_known_eq(i32 %x, i32 %y) {
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X]], [[Y]]
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
-; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT: ret i8 [[TMP2]]
+; CHECK-NEXT: ret i8 0
;
%1 = icmp eq i32 %x, %y
call void @llvm.assume(i1 %1)
@@ -152,8 +148,7 @@ define i8 @scmp_known_lt(i32 %x, i32 %y) {
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X]], [[Y]]
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
-; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT: ret i8 [[TMP2]]
+; CHECK-NEXT: ret i8 -1
;
%1 = icmp slt i32 %x, %y
call void @llvm.assume(i1 %1)
@@ -167,8 +162,7 @@ define i8 @ucmp_known_gt(i32 %x, i32 %y) {
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[X]], [[Y]]
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
-; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT: ret i8 [[TMP2]]
+; CHECK-NEXT: ret i8 1
;
%1 = icmp ugt i32 %x, %y
call void @llvm.assume(i1 %1)
@@ -182,8 +176,7 @@ define i8 @ucmp_known_eq(i32 %x, i32 %y) {
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X]], [[Y]]
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
-; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT: ret i8 [[TMP2]]
+; CHECK-NEXT: ret i8 0
;
%1 = icmp eq i32 %x, %y
call void @llvm.assume(i1 %1)
@@ -197,8 +190,7 @@ define i8 @ucmp_known_lt(i32 %x, i32 %y) {
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X]], [[Y]]
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP1]])
-; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT: ret i8 [[TMP2]]
+; CHECK-NEXT: ret i8 -1
;
%1 = icmp ult i32 %x, %y
call void @llvm.assume(i1 %1)
@@ -210,9 +202,7 @@ define i8 @ucmp_known_lt(i32 %x, i32 %y) {
define i8 @ucmp_with_addition(i32 %x) {
; CHECK-LABEL: define i8 @ucmp_with_addition(
; CHECK-SAME: i32 [[X:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[X]], 1
-; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[TMP1]])
-; CHECK-NEXT: ret i8 [[TMP2]]
+; CHECK-NEXT: ret i8 -1
;
%1 = add nuw i32 %x, 1
%2 = call i8 @llvm.ucmp(i32 %x, i32 %1)
@@ -222,9 +212,7 @@ define i8 @ucmp_with_addition(i32 %x) {
define i8 @ucmp_with_addition2(i32 %x) {
; CHECK-LABEL: define i8 @ucmp_with_addition2(
; CHECK-SAME: i32 [[X:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[X]], 1
-; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[TMP1]], i32 [[X]])
-; CHECK-NEXT: ret i8 [[TMP2]]
+; CHECK-NEXT: ret i8 1
;
%1 = add nuw i32 %x, 1
%2 = call i8 @llvm.ucmp(i32 %1, i32 %x)
>From 2506267c87316c844acf650a7bb1180997b14f88 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Sat, 15 Jun 2024 22:00:14 +0100
Subject: [PATCH 3/4] Added a test case for vector fold of x with x+1
---
llvm/test/Transforms/InstSimplify/uscmp.ll | 23 ++++++++++------------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/llvm/test/Transforms/InstSimplify/uscmp.ll b/llvm/test/Transforms/InstSimplify/uscmp.ll
index 616dc0d5d9d39..db96aa39192d6 100644
--- a/llvm/test/Transforms/InstSimplify/uscmp.ll
+++ b/llvm/test/Transforms/InstSimplify/uscmp.ll
@@ -219,6 +219,16 @@ define i8 @ucmp_with_addition2(i32 %x) {
ret i8 %2
}
+define <4 x i8> @ucmp_with_addition_vec(<4 x i32> %x) {
+; CHECK-LABEL: define <4 x i8> @ucmp_with_addition_vec(
+; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-NEXT: ret <4 x i8> <i8 -1, i8 -1, i8 -1, i8 -1>
+;
+ %1 = add nuw <4 x i32> %x, splat(i32 1)
+ %2 = call <4 x i8> @llvm.ucmp(<4 x i32> %x, <4 x i32> %1)
+ ret <4 x i8> %2
+}
+
; Negative case: mismatched signedness of predicates
define i8 @scmp_known_ugt(i32 %x, i32 %y) {
; CHECK-LABEL: define i8 @scmp_known_ugt(
@@ -292,16 +302,3 @@ define i8 @ucmp_with_addition_no_nuw(i32 %x) {
%2 = call i8 @llvm.ucmp(i32 %x, i32 %1)
ret i8 %2
}
-
-; Negative case: vector types are not (yet) supported
-define <4 x i8> @scmp_with_addition_vec(<4 x i32> %x) {
-; CHECK-LABEL: define <4 x i8> @scmp_with_addition_vec(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = add nuw <4 x i32> [[X]], <i32 1, i32 1, i32 1, i32 1>
-; CHECK-NEXT: [[TMP2:%.*]] = call <4 x i8> @llvm.scmp.v4i8.v4i32(<4 x i32> [[X]], <4 x i32> [[TMP1]])
-; CHECK-NEXT: ret <4 x i8> [[TMP2]]
-;
- %1 = add nuw <4 x i32> %x, splat(i32 1)
- %2 = call <4 x i8> @llvm.scmp(<4 x i32> %x, <4 x i32> %1)
- ret <4 x i8> %2
-}
>From fcde482ce391999b94c2752c80d20b331b645379 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Sat, 15 Jun 2024 22:35:18 +0100
Subject: [PATCH 4/4] Replace ConstantInt::get() with ConstantInt::getSigned()
Co-authored-by: Yingwei Zheng <dtcxzyw at qq.com>
---
llvm/lib/Analysis/InstructionSimplify.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 78047c580ad22..6cb8cc8ce1831 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6524,7 +6524,7 @@ Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
ICmpInst::Predicate PredLT =
IID == Intrinsic::scmp ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
if (isICmpTrue(PredLT, Op0, Op1, Q, RecursionLimit))
- return ConstantInt::get(ReturnType, -1, /*IsSigned*/ true);
+ return ConstantInt::getSigned(ReturnType, -1);
break;
}
More information about the llvm-commits
mailing list