[llvm] e3175f7 - [InstCombine] icmp(X | OrC, C) --> icmp(X, 0)

Jun Zhang via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 13 02:27:20 PDT 2023


Author: Jun Zhang
Date: 2023-04-13T17:26:24+08:00
New Revision: e3175f7f1b55a38e9ab845ca26f0c4343ee2f7ff

URL: https://github.com/llvm/llvm-project/commit/e3175f7f1b55a38e9ab845ca26f0c4343ee2f7ff
DIFF: https://github.com/llvm/llvm-project/commit/e3175f7f1b55a38e9ab845ca26f0c4343ee2f7ff.diff

LOG: [InstCombine] icmp(X | OrC, C) --> icmp(X, 0)

We can eliminate the or operation based on the predicate and the
relation between OrC and C.

sge: X | OrC s>= C --> X s>= 0 iff OrC s>= C s>= 0
sgt: X | OrC s>  C --> X s>= 0 iff OrC s>  C s>= 0
sle: X | OrC s<= C --> X s<  0 iff OrC s>  C s>= 0
slt: X | OrC s<  C --> X s<  0 iff OrC s>= C s>= 0

Alive2 links:
sge: https://alive2.llvm.org/ce/z/W-6FHE
sgt: https://alive2.llvm.org/ce/z/TKK2yJ
sle: https://alive2.llvm.org/ce/z/vURQGM
slt: https://alive2.llvm.org/ce/z/JAsVfw

Related issue: https://github.com/llvm/llvm-project/issues/61538

Signed-off-by: Jun Zhang <jun at junz.org>

Differential Revision: https://reviews.llvm.org/D147597

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/icmp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 13fdaf22f63d2..646a130d612fe 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1953,6 +1953,30 @@ Instruction *InstCombinerImpl::foldICmpOrConstant(ICmpInst &Cmp,
     return new ICmpInst(NewPred, X, NewC);
   }
 
+  const APInt *OrC;
+  // icmp(X | OrC, C) --> icmp(X, 0)
+  if (C.isNonNegative() && match(Or, m_Or(m_Value(X), m_APInt(OrC)))) {
+    switch (Pred) {
+    // X | OrC s< C --> X s< 0 iff OrC s>= C s>= 0
+    case ICmpInst::ICMP_SLT:
+    // X | OrC s>= C --> X s>= 0 iff OrC s>= C s>= 0
+    case ICmpInst::ICMP_SGE:
+      if (OrC->sge(C))
+        return new ICmpInst(Pred, X, ConstantInt::getNullValue(X->getType()));
+      break;
+    // X | OrC s<= C --> X s< 0 iff OrC s> C s>= 0
+    case ICmpInst::ICMP_SLE:
+    // X | OrC s> C --> X s>= 0 iff OrC s> C s>= 0
+    case ICmpInst::ICMP_SGT:
+      if (OrC->sgt(C))
+        return new ICmpInst(ICmpInst::getFlippedStrictnessPredicate(Pred), X,
+                            ConstantInt::getNullValue(X->getType()));
+      break;
+    default:
+      break;
+    }
+  }
+
   if (!Cmp.isEquality() || !C.isZero() || !Or->hasOneUse())
     return nullptr;
 

diff  --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index 7077ff4b81145..ec9ac67641487 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -4633,8 +4633,7 @@ define i1 @zext_notbool_and_ne0(i2 %x, i8 %y) {
 
 define i1 @or_positive_sgt_zero(i8 %a) {
 ; CHECK-LABEL: @or_positive_sgt_zero(
-; CHECK-NEXT:    [[B:%.*]] = or i8 [[A:%.*]], 24
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[B]], 0
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %b = or i8 %a, 24
@@ -4644,8 +4643,7 @@ define i1 @or_positive_sgt_zero(i8 %a) {
 
 define <2 x i1> @or_postive_sgt_zero_vec(<2 x i8> %a) {
 ; CHECK-LABEL: @or_postive_sgt_zero_vec(
-; CHECK-NEXT:    [[B:%.*]] = or <2 x i8> [[A:%.*]], <i8 24, i8 24>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[B]], zeroinitializer
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[A:%.*]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
 
@@ -4697,8 +4695,7 @@ define <2 x i1> @or_poison_vec_sge_zero_vec(<2 x i8> %a) {
 
 define i1 @or_positive_sge_postive(i8 %a) {
 ; CHECK-LABEL: @or_positive_sge_postive(
-; CHECK-NEXT:    [[B:%.*]] = or i8 [[A:%.*]], 24
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[B]], 23
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %b = or i8 %a, 24
@@ -4708,8 +4705,7 @@ define i1 @or_positive_sge_postive(i8 %a) {
 
 define <2 x i1> @or_postive_sge_positive_vec(<2 x i8> %a) {
 ; CHECK-LABEL: @or_postive_sge_positive_vec(
-; CHECK-NEXT:    [[B:%.*]] = or <2 x i8> [[A:%.*]], <i8 24, i8 24>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[B]], <i8 23, i8 23>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[A:%.*]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
 
@@ -4730,8 +4726,7 @@ define <2 x i1> @or_poison_vec_sge_positive_vec(<2 x i8> %a) {
 
 define i1 @or_positive_sle_zero(i8 %a) {
 ; CHECK-LABEL: @or_positive_sle_zero(
-; CHECK-NEXT:    [[B:%.*]] = or i8 [[A:%.*]], 24
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[B]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[A:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %b = or i8 %a, 24
@@ -4741,8 +4736,7 @@ define i1 @or_positive_sle_zero(i8 %a) {
 
 define <2 x i1> @or_postive_sle_zero_vec(<2 x i8> %a) {
 ; CHECK-LABEL: @or_postive_sle_zero_vec(
-; CHECK-NEXT:    [[B:%.*]] = or <2 x i8> [[A:%.*]], <i8 24, i8 24>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[B]], <i8 1, i8 1>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
 
@@ -4794,8 +4788,7 @@ define <2 x i1> @or_poison_vec_slt_zero_vec(<2 x i8> %a) {
 
 define i1 @or_positive_slt_postive(i8 %a) {
 ; CHECK-LABEL: @or_positive_slt_postive(
-; CHECK-NEXT:    [[B:%.*]] = or i8 [[A:%.*]], 24
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[B]], 24
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[A:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %b = or i8 %a, 24
@@ -4805,8 +4798,7 @@ define i1 @or_positive_slt_postive(i8 %a) {
 
 define <2 x i1> @or_postive_slt_positive_vec(<2 x i8> %a) {
 ; CHECK-LABEL: @or_postive_slt_positive_vec(
-; CHECK-NEXT:    [[B:%.*]] = or <2 x i8> [[A:%.*]], <i8 24, i8 24>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[B]], <i8 24, i8 24>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
 
@@ -4965,7 +4957,7 @@ define i1 @or_positive_sgt_zero_multi_use(i8 %a) {
 ; CHECK-LABEL: @or_positive_sgt_zero_multi_use(
 ; CHECK-NEXT:    [[B:%.*]] = or i8 [[A:%.*]], 24
 ; CHECK-NEXT:    call void @use_i8(i8 [[B]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[B]], 0
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %b = or i8 %a, 24


        


More information about the llvm-commits mailing list