[PATCH] D133919: [InstCombine] Fold ((x?1:4)&(y?1:4))==0 to x^y

Marc Auberer via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 15 00:39:05 PDT 2022


marcauberer created this revision.
marcauberer added reviewers: spatel, RKSimon.
Herald added a subscriber: hiraditya.
Herald added a project: All.
marcauberer requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Fixes issue #57666: https://github.com/llvm/llvm-project/issues/57666

The optimization applies to all constant values that equal to zero when
applied to an bitwise and instruction.

Alive2: https://alive2.llvm.org/ce/z/RrVEyX
Minimalistic Godbolt example: https://godbolt.org/z/3d6h9z4de


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133919

Files:
  llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
  llvm/test/Transforms/InstCombine/select_and_icmpeq.ll


Index: llvm/test/Transforms/InstCombine/select_and_icmpeq.ll
===================================================================
--- llvm/test/Transforms/InstCombine/select_and_icmpeq.ll
+++ llvm/test/Transforms/InstCombine/select_and_icmpeq.ll
@@ -8,10 +8,7 @@
 
 define i1 @select_and_icmpeq_i32_commuted1(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_and_icmpeq_i32_commuted1(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i32 2, i32 1
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i32 2, i32 1
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[S1]], [[S2]]
-; CHECK-NEXT:    [[ICMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT:    [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[ICMP]]
 ;
   %s1 = select i1 %x, i32 2, i32 1
@@ -23,10 +20,7 @@
 
 define i1 @select_and_icmpeq_i32_commuted2(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_and_icmpeq_i32_commuted2(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[Y:%.*]], i32 4, i32 1
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[X:%.*]], i32 4, i32 1
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[S2]], [[S1]]
-; CHECK-NEXT:    [[ICMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT:    [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[ICMP]]
 ;
   %s1 = select i1 %y, i32 4, i32 1
@@ -38,10 +32,7 @@
 
 define i1 @select_and_icmpeq_i32_commuted3(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_and_icmpeq_i32_commuted3(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[Y:%.*]], i32 3, i32 12
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[X:%.*]], i32 3, i32 12
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[S1]], [[S2]]
-; CHECK-NEXT:    [[ICMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT:    [[ICMP:%.*]] = xor i1 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[ICMP]]
 ;
   %s1 = select i1 %y, i32 3, i32 12
@@ -53,10 +44,7 @@
 
 define i1 @select_and_icmpeq_i32_commuted4(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_and_icmpeq_i32_commuted4(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[Y:%.*]], i32 3, i32 16
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[X:%.*]], i32 3, i32 16
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[S2]], [[S1]]
-; CHECK-NEXT:    [[ICMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT:    [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[ICMP]]
 ;
   %s1 = select i1 %y, i32 3, i32 16
@@ -68,10 +56,7 @@
 
 define i1 @select_and_icmpeq_i9(i1 %x, i1 %y) {
 ; CHECK-LABEL: @select_and_icmpeq_i9(
-; CHECK-NEXT:    [[S1:%.*]] = select i1 [[Y:%.*]], i9 3, i9 16
-; CHECK-NEXT:    [[S2:%.*]] = select i1 [[X:%.*]], i9 3, i9 16
-; CHECK-NEXT:    [[AND:%.*]] = and i9 [[S2]], [[S1]]
-; CHECK-NEXT:    [[ICMP:%.*]] = icmp eq i9 [[AND]], 0
+; CHECK-NEXT:    [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[ICMP]]
 ;
   %s1 = select i1 %y, i9 3, i9 16
Index: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6464,6 +6464,22 @@
   if (Instruction *Res = foldReductionIdiom(I, Builder, DL))
     return Res;
 
+  {
+    Value *A, *B;
+    const APInt *C, *D;
+    // Find hidden xor optimization (only works if `and C, D` equals `0`)
+    // (icmp (and (select A, C, D), (select B, C, D)), 0) --> (xor A, B)
+    if (I.getPredicate() == ICmpInst::ICMP_EQ && match(Op0,
+      m_OneUse(m_c_And(
+        m_OneUse(m_Select(m_Value(A), m_APInt(C), m_APInt(D))),
+        m_OneUse(m_Select(m_Value(B), m_APInt(C), m_APInt(D)))
+      ))
+    ) && match(Op1, m_Zero())) {
+      if ((*C & *D) == 0)
+        return BinaryOperator::CreateXor(A, B);
+    }
+  }
+
   return Changed ? &I : nullptr;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D133919.460313.patch
Type: text/x-patch
Size: 3693 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220915/13bd6346/attachment.bin>


More information about the llvm-commits mailing list