[llvm] 2265d01 - [InstCombine] reduce xor-of-or's bitwise logic (PR46955)

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 3 05:31:57 PDT 2020


Author: Sanjay Patel
Date: 2020-08-03T08:31:43-04:00
New Revision: 2265d01f2a5bd153959701e22f5be2a40e1674a3

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

LOG: [InstCombine] reduce xor-of-or's bitwise logic (PR46955)

I tried to use m_Deferred() on this, but didn't find
a clean way to do that.

http://bugs.llvm.org/PR46955

https://alive2.llvm.org/ce/z/2h6QTq

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/test/Transforms/InstCombine/xor.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 030d2f203ed6..ef1e8dbe0155 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3351,6 +3351,20 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
       match(Op1, m_Not(m_Specific(A))))
     return BinaryOperator::CreateNot(Builder.CreateAnd(A, B));
 
+  // (A | B) ^ (A | C) --> (B ^ C) & ~A -- There are 4 commuted variants.
+  // TODO: Loosen one-use restriction if common operand is a constant.
+  Value *D;
+  if (match(Op0, m_OneUse(m_Or(m_Value(A), m_Value(B)))) &&
+      match(Op1, m_OneUse(m_Or(m_Value(C), m_Value(D))))) {
+    if (B == C || B == D)
+      std::swap(A, B);
+    if (A == C)
+      std::swap(C, D);
+    if (A == D)
+      return BinaryOperator::CreateAnd(Builder.CreateXor(B, C),
+                                       Builder.CreateNot(A));
+  }
+
   if (auto *LHS = dyn_cast<ICmpInst>(I.getOperand(0)))
     if (auto *RHS = dyn_cast<ICmpInst>(I.getOperand(1)))
       if (Value *V = foldXorOfICmps(LHS, RHS, I))

diff  --git a/llvm/test/Transforms/InstCombine/xor.ll b/llvm/test/Transforms/InstCombine/xor.ll
index a133f2a0e009..2bdb837bff04 100644
--- a/llvm/test/Transforms/InstCombine/xor.ll
+++ b/llvm/test/Transforms/InstCombine/xor.ll
@@ -915,9 +915,9 @@ define <2 x i32> @test51vec(<2 x i32> %x, <2 x i32> %y) {
 
 define i4 @or_or_xor(i4 %x, i4 %y, i4 %z) {
 ; CHECK-LABEL: @or_or_xor(
-; CHECK-NEXT:    [[O1:%.*]] = or i4 [[Z:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[O2:%.*]] = or i4 [[Z]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = xor i4 [[O1]], [[O2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i4 [[Z:%.*]], -1
+; CHECK-NEXT:    [[R:%.*]] = and i4 [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret i4 [[R]]
 ;
   %o1 = or i4 %z, %x
@@ -928,9 +928,9 @@ define i4 @or_or_xor(i4 %x, i4 %y, i4 %z) {
 
 define i4 @or_or_xor_commute1(i4 %x, i4 %y, i4 %z) {
 ; CHECK-LABEL: @or_or_xor_commute1(
-; CHECK-NEXT:    [[O1:%.*]] = or i4 [[X:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[O2:%.*]] = or i4 [[Z]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = xor i4 [[O1]], [[O2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i4 [[Z:%.*]], -1
+; CHECK-NEXT:    [[R:%.*]] = and i4 [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret i4 [[R]]
 ;
   %o1 = or i4 %x, %z
@@ -941,9 +941,9 @@ define i4 @or_or_xor_commute1(i4 %x, i4 %y, i4 %z) {
 
 define i4 @or_or_xor_commute2(i4 %x, i4 %y, i4 %z) {
 ; CHECK-LABEL: @or_or_xor_commute2(
-; CHECK-NEXT:    [[O1:%.*]] = or i4 [[Z:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[O2:%.*]] = or i4 [[Y:%.*]], [[Z]]
-; CHECK-NEXT:    [[R:%.*]] = xor i4 [[O1]], [[O2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i4 [[Z:%.*]], -1
+; CHECK-NEXT:    [[R:%.*]] = and i4 [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret i4 [[R]]
 ;
   %o1 = or i4 %z, %x
@@ -954,9 +954,9 @@ define i4 @or_or_xor_commute2(i4 %x, i4 %y, i4 %z) {
 
 define <2 x i4> @or_or_xor_commute3(<2 x i4> %x, <2 x i4> %y, <2 x i4> %z) {
 ; CHECK-LABEL: @or_or_xor_commute3(
-; CHECK-NEXT:    [[O1:%.*]] = or <2 x i4> [[X:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[O2:%.*]] = or <2 x i4> [[Y:%.*]], [[Z]]
-; CHECK-NEXT:    [[R:%.*]] = xor <2 x i4> [[O1]], [[O2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor <2 x i4> [[Z:%.*]], <i4 -1, i4 -1>
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i4> [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret <2 x i4> [[R]]
 ;
   %o1 = or <2 x i4> %x, %z


        


More information about the llvm-commits mailing list