[llvm] 61d2f3a - [InstCombine] Canonicalize icmp eq pow2 more thoroughly

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 16 01:45:46 PDT 2023


Author: Nikita Popov
Date: 2023-03-16T09:41:52+01:00
New Revision: 61d2f3a71e61929bf9b07c90e21d268090417bdb

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

LOG: [InstCombine] Canonicalize icmp eq pow2 more thoroughly

We currently already canonicalize icmp eq (%x & Pow2), Pow2 to
icmp ne (%x & Pow2), 0. This patch generalizes the fold based on
known bits.

In particular, this allows us to handle comparisons against
!range !{i64 0, i64 2} loads, which addresses an optimization
regression in Rust caused by 8df376db7282b955e7990cb8887ee9dcd3565040.

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

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/div.ll
    llvm/test/Transforms/InstCombine/icmp-range.ll
    llvm/test/Transforms/InstCombine/icmp-shl-nsw.ll
    llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll
    llvm/test/Transforms/InstCombine/zext.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index b790bb7197e26..b1d59d355eb73 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3239,16 +3239,6 @@ Instruction *InstCombinerImpl::foldICmpBinOpEqualityWithConstant(
     }
     break;
   }
-  case Instruction::And: {
-    const APInt *BOC;
-    if (match(BOp1, m_APInt(BOC))) {
-      // If we have ((X & C) == C), turn it into ((X & C) != 0).
-      if (C == *BOC && C.isPowerOf2())
-        return new ICmpInst(isICMP_NE ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE,
-                            BO, Constant::getNullValue(RHS->getType()));
-    }
-    break;
-  }
   case Instruction::UDiv:
     if (C.isZero()) {
       // (icmp eq/ne (udiv A, B), 0) -> (icmp ugt/ule i32 B, A)
@@ -5771,6 +5761,12 @@ Instruction *InstCombinerImpl::foldICmpUsingKnownBits(ICmpInst &I) {
         }
       }
     }
+
+    // Op0 eq C_Pow2 -> Op0 ne 0 if Op0 is known to be C_Pow2 or zero.
+    if (Op1Known.isConstant() && Op1Known.getConstant().isPowerOf2() &&
+        (Op0Known & Op1Known) == Op0Known)
+      return new ICmpInst(CmpInst::getInversePredicate(Pred), Op0,
+                          ConstantInt::getNullValue(Op1->getType()));
     break;
   }
   case ICmpInst::ICMP_ULT: {

diff  --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index 59871f51b9298..1f0081befb07d 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -400,7 +400,7 @@ define i32 @test28(i32 %a) {
 
 define i32 @test29(i32 %a) {
 ; CHECK-LABEL: @test29(
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[A:%.*]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i32 [[A:%.*]], 0
 ; CHECK-NEXT:    [[DIV:%.*]] = zext i1 [[TMP1]] to i32
 ; CHECK-NEXT:    ret i32 [[DIV]]
 ;

diff  --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 29b601f5522be..4281e09cb0309 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1004,7 +1004,7 @@ define i1 @icmp_eq_bool_0(ptr %ptr) {
 define i1 @icmp_eq_bool_1(ptr %ptr) {
 ; CHECK-LABEL: @icmp_eq_bool_1(
 ; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[PTR:%.*]], align 8, !range [[RNG6]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[VAL]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i64 [[VAL]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %val = load i64, ptr %ptr, align 8, !range !{i64 0, i64 2}
@@ -1026,7 +1026,7 @@ define i1 @icmp_ne_bool_0(ptr %ptr) {
 define i1 @icmp_ne_bool_1(ptr %ptr) {
 ; CHECK-LABEL: @icmp_ne_bool_1(
 ; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[PTR:%.*]], align 8, !range [[RNG6]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i64 [[VAL]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[VAL]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %val = load i64, ptr %ptr, align 8, !range !{i64 0, i64 2}

diff  --git a/llvm/test/Transforms/InstCombine/icmp-shl-nsw.ll b/llvm/test/Transforms/InstCombine/icmp-shl-nsw.ll
index 32940428b0dcf..6b9ea1f8ef97e 100644
--- a/llvm/test/Transforms/InstCombine/icmp-shl-nsw.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-shl-nsw.ll
@@ -162,7 +162,7 @@ define i1 @icmp_sgt8(i8 %x) {
 
 define i1 @icmp_sgt9(i8 %x) {
 ; CHECK-LABEL: @icmp_sgt9(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %shl = shl nsw i8 %x, 7
@@ -303,7 +303,7 @@ define i1 @icmp_sle8(i8 %x) {
 
 define i1 @icmp_sle9(i8 %x) {
 ; CHECK-LABEL: @icmp_sle9(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %shl = shl nsw i8 %x, 7

diff  --git a/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll b/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll
index 6ef1c6ca211d5..33c9b59551667 100644
--- a/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll
@@ -2767,7 +2767,7 @@ define i1 @lshrult_03_00_exact(i4 %x) {
 
 define i1 @lshrult_03_01_exact(i4 %x) {
 ; CHECK-LABEL: @lshrult_03_01_exact(
-; CHECK-NEXT:    [[C:%.*]] = icmp ne i4 [[X:%.*]], -8
+; CHECK-NEXT:    [[C:%.*]] = icmp eq i4 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[C]]
 ;
   %s = lshr exact i4 %x, 3

diff  --git a/llvm/test/Transforms/InstCombine/zext.ll b/llvm/test/Transforms/InstCombine/zext.ll
index dd781c78d3fb1..8aa2a10e6abb2 100644
--- a/llvm/test/Transforms/InstCombine/zext.ll
+++ b/llvm/test/Transforms/InstCombine/zext.ll
@@ -718,9 +718,7 @@ define i64 @zext_icmp_eq_bool_0(ptr %ptr) {
 define i64 @zext_icmp_eq_bool_1(ptr %ptr) {
 ; CHECK-LABEL: @zext_icmp_eq_bool_1(
 ; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[PTR:%.*]], align 8, !range [[RNG0]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[VAL]], 1
-; CHECK-NEXT:    [[LEN:%.*]] = zext i1 [[CMP]] to i64
-; CHECK-NEXT:    ret i64 [[LEN]]
+; CHECK-NEXT:    ret i64 [[VAL]]
 ;
   %val = load i64, ptr %ptr, align 8, !range !{i64 0, i64 2}
   %cmp = icmp eq i64 %val, 1
@@ -742,8 +740,7 @@ define i64 @zext_icmp_ne_bool_0(ptr %ptr) {
 define i64 @zext_icmp_ne_bool_1(ptr %ptr) {
 ; CHECK-LABEL: @zext_icmp_ne_bool_1(
 ; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[PTR:%.*]], align 8, !range [[RNG0]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i64 [[VAL]], 1
-; CHECK-NEXT:    [[LEN:%.*]] = zext i1 [[CMP]] to i64
+; CHECK-NEXT:    [[LEN:%.*]] = xor i64 [[VAL]], 1
 ; CHECK-NEXT:    ret i64 [[LEN]]
 ;
   %val = load i64, ptr %ptr, align 8, !range !{i64 0, i64 2}


        


More information about the llvm-commits mailing list