[llvm] [InstCombine] Fold an unsigned icmp of ucmp/scmp with a constant to an icmp of the original arguments (PR #104471)

Volodymyr Vasylkun via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 15 16:01:55 PDT 2024


https://github.com/Poseydon42 updated https://github.com/llvm/llvm-project/pull/104471

>From 3e5bf9cd4f7420d7153e2b9358156af5de819a51 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Thu, 15 Aug 2024 18:01:27 +0100
Subject: [PATCH 1/3] Precommit tests

---
 llvm/test/Transforms/InstCombine/scmp.ll | 27 ++++++++++++++++++++++++
 llvm/test/Transforms/InstCombine/ucmp.ll | 26 +++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/scmp.ll b/llvm/test/Transforms/InstCombine/scmp.ll
index 2523872562cad..cb6d3ebf55423 100644
--- a/llvm/test/Transforms/InstCombine/scmp.ll
+++ b/llvm/test/Transforms/InstCombine/scmp.ll
@@ -157,6 +157,33 @@ define i1 @scmp_sle_neg_1(i32 %x, i32 %y) {
   ret i1 %2
 }
 
+; scmp(x, y) u< C => x s>= y when C u> 1 and C != -1
+define i1 @scmp_ult_positive_const_gt_than_1_lt_than_umax(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_ult_positive_const_gt_than_1_lt_than_umax(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[TMP2]], 4
+; CHECK-NEXT:    ret i1 [[TMP1]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp ult i8 %1, 4
+  ret i1 %2
+}
+
+; scmp(x, y) s> C => x s< y when C != 0 and C != -1
+define i1 @ucmp_ugt_const_not_0_or_neg1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_ugt_const_not_0_or_neg1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i8 [[TMP1]], 12
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp ugt i8 %1, 12
+  ret i1 %2
+}
+
+
 ; ========== Fold -scmp(x, y) => scmp(y, x) ==========
 define i8 @scmp_negated(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i8 @scmp_negated(
diff --git a/llvm/test/Transforms/InstCombine/ucmp.ll b/llvm/test/Transforms/InstCombine/ucmp.ll
index 7210455094baa..7da26cd6d7f05 100644
--- a/llvm/test/Transforms/InstCombine/ucmp.ll
+++ b/llvm/test/Transforms/InstCombine/ucmp.ll
@@ -157,6 +157,32 @@ define i1 @ucmp_sle_neg_1(i32 %x, i32 %y) {
   ret i1 %2
 }
 
+; ucmp(x, y) u< C => x u>= y when C u> 1 and C != -1
+define i1 @ucmp_ult_positive_const_gt_than_1_lt_than_umax(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_ult_positive_const_gt_than_1_lt_than_umax(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[TMP2]], 4
+; CHECK-NEXT:    ret i1 [[TMP1]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp ult i8 %1, 4
+  ret i1 %2
+}
+
+; ucmp(x, y) u> C => x u< y when C != 0 and C != -1
+define i1 @ucmp_ugt_const_not_0_or_neg1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_ugt_const_not_0_or_neg1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i8 [[TMP1]], 12
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp ugt i8 %1, 12
+  ret i1 %2
+}
+
 ; ========== Fold -ucmp(x, y) => ucmp(y, x) ==========
 define i8 @ucmp_negated(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i8 @ucmp_negated(

>From 5792deaa26266f4998515b145b4faa1fe180c12f Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Thu, 15 Aug 2024 18:04:45 +0100
Subject: [PATCH 2/3] Implement the fold

---
 .../lib/Transforms/InstCombine/InstCombineCompares.cpp | 10 ++++++++++
 llvm/test/Transforms/InstCombine/scmp.ll               |  6 ++----
 llvm/test/Transforms/InstCombine/ucmp.ll               |  6 ++----
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 10488ecb747a4..9ef3a45687166 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4018,6 +4018,16 @@ foldICmpOfCmpIntrinsicWithConstant(ICmpInst::Predicate Pred, IntrinsicInst *I,
       NewPredicate = ICmpInst::ICMP_ULE;
     break;
 
+  case ICmpInst::ICMP_ULT:
+    if (C.ugt(1) && !C.isAllOnes())
+      NewPredicate = ICmpInst::ICMP_UGE;
+    break;
+
+  case ICmpInst::ICMP_UGT:
+    if (!C.isZero() && !C.isAllOnes())
+      NewPredicate = ICmpInst::ICMP_ULT;
+    break;
+
   default:
     break;
   }
diff --git a/llvm/test/Transforms/InstCombine/scmp.ll b/llvm/test/Transforms/InstCombine/scmp.ll
index cb6d3ebf55423..460ea96b16fcf 100644
--- a/llvm/test/Transforms/InstCombine/scmp.ll
+++ b/llvm/test/Transforms/InstCombine/scmp.ll
@@ -161,8 +161,7 @@ define i1 @scmp_sle_neg_1(i32 %x, i32 %y) {
 define i1 @scmp_ult_positive_const_gt_than_1_lt_than_umax(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i1 @scmp_ult_positive_const_gt_than_1_lt_than_umax(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[TMP2]], 4
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp sge i32 [[X]], [[Y]]
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
@@ -174,8 +173,7 @@ define i1 @scmp_ult_positive_const_gt_than_1_lt_than_umax(i32 %x, i32 %y) {
 define i1 @ucmp_ugt_const_not_0_or_neg1(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i1 @ucmp_ugt_const_not_0_or_neg1(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i8 [[TMP1]], 12
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[X]], [[Y]]
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
diff --git a/llvm/test/Transforms/InstCombine/ucmp.ll b/llvm/test/Transforms/InstCombine/ucmp.ll
index 7da26cd6d7f05..8690e23ea2e0e 100644
--- a/llvm/test/Transforms/InstCombine/ucmp.ll
+++ b/llvm/test/Transforms/InstCombine/ucmp.ll
@@ -161,8 +161,7 @@ define i1 @ucmp_sle_neg_1(i32 %x, i32 %y) {
 define i1 @ucmp_ult_positive_const_gt_than_1_lt_than_umax(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i1 @ucmp_ult_positive_const_gt_than_1_lt_than_umax(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[TMP2]], 4
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i32 [[X]], [[Y]]
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
@@ -174,8 +173,7 @@ define i1 @ucmp_ult_positive_const_gt_than_1_lt_than_umax(i32 %x, i32 %y) {
 define i1 @ucmp_ugt_const_not_0_or_neg1(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i1 @ucmp_ugt_const_not_0_or_neg1(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i8 [[TMP1]], 12
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)

>From 5aea5762be606af216e411bc0c33bffa252a4453 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Fri, 16 Aug 2024 00:01:30 +0100
Subject: [PATCH 3/3] Remove unnecessary condition for fold

---
 llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9ef3a45687166..34c9e0fde4f42 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4019,7 +4019,7 @@ foldICmpOfCmpIntrinsicWithConstant(ICmpInst::Predicate Pred, IntrinsicInst *I,
     break;
 
   case ICmpInst::ICMP_ULT:
-    if (C.ugt(1) && !C.isAllOnes())
+    if (C.ugt(1))
       NewPredicate = ICmpInst::ICMP_UGE;
     break;
 



More information about the llvm-commits mailing list