[llvm] a3c1669 - [InstCombine] fold icmp equality with 'or' mask ops

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 7 13:39:49 PDT 2021


Author: Sanjay Patel
Date: 2021-09-07T16:34:00-04:00
New Revision: a3c1669b1717545e16e33c0d7c147355f4912faa

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

LOG: [InstCombine] fold icmp equality with 'or' mask ops

This could go either direction since the instruction
count is the same either way, but there are a few
reasons to prefer this:
1. We already do the related transform with 'and'
   (see just above the new code).
2. We try (too hard) to compensate for not having this
   and possibly other folds in transformZExtICmp(),
   and that leads to bugs like https://llvm.org/PR51762 .
3. Codegen looks better across a variety of targets.

https://alive2.llvm.org/ce/z/uEgn4P

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 8e66b81abcfe..04657360afe3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4465,6 +4465,19 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
     }
   }
 
+  {
+    // Similar to above, but specialized for constant because invert is needed:
+    // (X | C) == (Y | C) --> (X ^ Y) & ~C == 0
+    Value *X, *Y;
+    Constant *C;
+    if (match(Op0, m_OneUse(m_Or(m_Value(X), m_Constant(C)))) &&
+        match(Op1, m_OneUse(m_Or(m_Value(Y), m_Specific(C))))) {
+      Value *Xor = Builder.CreateXor(X, Y);
+      Value *And = Builder.CreateAnd(Xor, ConstantExpr::getNot(C));
+      return new ICmpInst(Pred, And, Constant::getNullValue(And->getType()));
+    }
+  }
+
   // Transform (zext A) == (B & (1<<X)-1) --> A == (trunc B)
   // and       (B & (1<<X)-1) == (zext A) --> A == (trunc B)
   ConstantInt *Cst1;

diff  --git a/llvm/test/Transforms/InstCombine/icmp-or.ll b/llvm/test/Transforms/InstCombine/icmp-or.ll
index f7c03feb3eea..7c821aa2a320 100644
--- a/llvm/test/Transforms/InstCombine/icmp-or.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-or.ll
@@ -113,9 +113,9 @@ define i1 @set_low_bit_mask_sle(i8 %x) {
 
 define i1 @eq_const_mask(i8 %x, i8 %y) {
 ; CHECK-LABEL: @eq_const_mask(
-; CHECK-NEXT:    [[B0:%.*]] = or i8 [[X:%.*]], 42
-; CHECK-NEXT:    [[B1:%.*]] = or i8 [[Y:%.*]], 42
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[B0]], [[B1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[TMP1]], -43
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[TMP2]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %b0 = or i8 %x, 42
@@ -126,9 +126,9 @@ define i1 @eq_const_mask(i8 %x, i8 %y) {
 
 define <2 x i1> @ne_const_mask(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @ne_const_mask(
-; CHECK-NEXT:    [[B0:%.*]] = or <2 x i8> [[X:%.*]], <i8 -106, i8 5>
-; CHECK-NEXT:    [[B1:%.*]] = or <2 x i8> [[Y:%.*]], <i8 -106, i8 5>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i8> [[B0]], [[B1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i8> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i8> [[TMP1]], <i8 105, i8 -6>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i8> [[TMP2]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %b0 = or <2 x i8> %x, <i8 150, i8 5>
@@ -137,6 +137,8 @@ define <2 x i1> @ne_const_mask(<2 x i8> %x, <2 x i8> %y) {
   ret <2 x i1> %cmp
 }
 
+; negative test - predicate
+
 define i1 @eq_const_mask_not_equality(i8 %x, i8 %y) {
 ; CHECK-LABEL: @eq_const_mask_not_equality(
 ; CHECK-NEXT:    [[B0:%.*]] = or i8 [[X:%.*]], 5
@@ -150,6 +152,8 @@ define i1 @eq_const_mask_not_equality(i8 %x, i8 %y) {
   ret i1 %cmp
 }
 
+; negative test - mismatched constants
+
 define i1 @eq_const_mask_not_same(i8 %x, i8 %y) {
 ; CHECK-LABEL: @eq_const_mask_not_same(
 ; CHECK-NEXT:    [[B0:%.*]] = or i8 [[X:%.*]], 5
@@ -163,6 +167,8 @@ define i1 @eq_const_mask_not_same(i8 %x, i8 %y) {
   ret i1 %cmp
 }
 
+; negative test - mismatched logic
+
 define i1 @eq_const_mask_wrong_opcode(i8 %x, i8 %y) {
 ; CHECK-LABEL: @eq_const_mask_wrong_opcode(
 ; CHECK-NEXT:    [[B0:%.*]] = or i8 [[X:%.*]], 5
@@ -176,6 +182,8 @@ define i1 @eq_const_mask_wrong_opcode(i8 %x, i8 %y) {
   ret i1 %cmp
 }
 
+; negative test - no extra uses
+
 define i1 @eq_const_mask_use1(i8 %x, i8 %y) {
 ; CHECK-LABEL: @eq_const_mask_use1(
 ; CHECK-NEXT:    [[B0:%.*]] = or i8 [[X:%.*]], 5
@@ -191,6 +199,8 @@ define i1 @eq_const_mask_use1(i8 %x, i8 %y) {
   ret i1 %cmp
 }
 
+; negative test - no extra uses
+
 define i1 @eq_const_mask_use2(i8 %x, i8 %y) {
 ; CHECK-LABEL: @eq_const_mask_use2(
 ; CHECK-NEXT:    [[B0:%.*]] = or i8 [[X:%.*]], 5


        


More information about the llvm-commits mailing list