[llvm] 63bedc8 - [InstSimplify] Handle commutativity for 'and' and 'outer or' for (~A & B) | ~(A | B) --> ~A

Dávid Bolvanský via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 16 10:43:04 PST 2021


Author: Dávid Bolvanský
Date: 2021-01-16T19:42:50+01:00
New Revision: 63bedc80da36cf5eb71b06b453c186e057607bf4

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

LOG: [InstSimplify] Handle commutativity for 'and' and 'outer or' for (~A & B) | ~(A | B) --> ~A

Reviewed By: lebedev.ri

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

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/or.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 73f046dcb8de..6a065c46d9bf 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2224,7 +2224,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
   if (Value *V = simplifyLogicOfAddSub(Op0, Op1, Instruction::Or))
     return V;
 
-  Value *A, *B;
+  Value *A, *B, *NotA;
   // (A & ~B) | (A ^ B) -> (A ^ B)
   // (~B & A) | (A ^ B) -> (A ^ B)
   // (A & ~B) | (B ^ A) -> (B ^ A)
@@ -2236,7 +2236,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
 
   // Commute the 'or' operands.
   // (A ^ B) | (A & ~B) -> (A ^ B)
-  // (A ^ B) | (~B & A) -> (A ^ B)
+  // (A ^ B) | (~B & A) -> (A ^ B)D94870
   // (B ^ A) | (A & ~B) -> (B ^ A)
   // (B ^ A) | (~B & A) -> (B ^ A)
   if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
@@ -2253,6 +2253,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
        match(Op1, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B)))))
     return Op1;
 
+  // Commute the 'or' operands.
   // (~A ^ B) | (A & B) -> (~A ^ B)
   // (~A ^ B) | (B & A) -> (~A ^ B)
   // (B ^ ~A) | (A & B) -> (B ^ ~A)
@@ -2266,9 +2267,20 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
   // (~A & B) | ~(B | A) --> ~A
   // (B & ~A) | ~(A | B) --> ~A
   // (B & ~A) | ~(B | A) --> ~A
-  if (match(Op0, m_And(m_Not(m_Value(A)), m_Value(B))) &&
+  if (match(Op0, m_c_And(m_CombineAnd(m_Value(NotA), m_Not(m_Value(A))),
+                         m_Value(B))) &&
       match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
-    return cast<BinaryOperator>(Op0)->getOperand(0);
+    return NotA;
+
+  // Commute the 'or' operands.
+  // ~(A | B) | (~A & B) --> ~A
+  // ~(B | A) | (~A & B) --> ~A
+  // ~(A | B) | (B & ~A) --> ~A
+  // ~(B | A) | (B & ~A) --> ~A
+  if (match(Op1, m_c_And(m_CombineAnd(m_Value(NotA), m_Not(m_Value(A))),
+                         m_Value(B))) &&
+      match(Op0, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
+    return NotA;
 
   if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, false))
     return V;

diff  --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll
index 68d2af4a4041..7f347193be9a 100644
--- a/llvm/test/Transforms/InstSimplify/or.ll
+++ b/llvm/test/Transforms/InstSimplify/or.ll
@@ -399,11 +399,7 @@ define i32 @and_or_not_or4_use3(i32 %A, i32 %B) {
 define i32 @and_or_not_or5(i32 %A, i32 %B) {
 ; CHECK-LABEL: @and_or_not_or5(
 ; CHECK-NEXT:    [[I:%.*]] = xor i32 [[A:%.*]], -1
-; CHECK-NEXT:    [[I2:%.*]] = and i32 [[B:%.*]], [[I]]
-; CHECK-NEXT:    [[I3:%.*]] = or i32 [[B]], [[A]]
-; CHECK-NEXT:    [[I4:%.*]] = xor i32 [[I3]], -1
-; CHECK-NEXT:    [[I5:%.*]] = or i32 [[I2]], [[I4]]
-; CHECK-NEXT:    ret i32 [[I5]]
+; CHECK-NEXT:    ret i32 [[I]]
 ;
   %i = xor i32 %A, -1
   %i2 = and i32 %B, %i
@@ -416,11 +412,7 @@ define i32 @and_or_not_or5(i32 %A, i32 %B) {
 define i32 @and_or_not_or6(i32 %A, i32 %B) {
 ; CHECK-LABEL: @and_or_not_or6(
 ; CHECK-NEXT:    [[I:%.*]] = xor i32 [[A:%.*]], -1
-; CHECK-NEXT:    [[I2:%.*]] = and i32 [[I]], [[B:%.*]]
-; CHECK-NEXT:    [[I3:%.*]] = or i32 [[B]], [[A]]
-; CHECK-NEXT:    [[I4:%.*]] = xor i32 [[I3]], -1
-; CHECK-NEXT:    [[I5:%.*]] = or i32 [[I4]], [[I2]]
-; CHECK-NEXT:    ret i32 [[I5]]
+; CHECK-NEXT:    ret i32 [[I]]
 ;
   %i = xor i32 %A, -1
   %i2 = and i32 %i, %B
@@ -433,11 +425,7 @@ define i32 @and_or_not_or6(i32 %A, i32 %B) {
 define i32 @and_or_not_or7(i32 %A, i32 %B) {
 ; CHECK-LABEL: @and_or_not_or7(
 ; CHECK-NEXT:    [[I:%.*]] = xor i32 [[A:%.*]], -1
-; CHECK-NEXT:    [[I2:%.*]] = and i32 [[B:%.*]], [[I]]
-; CHECK-NEXT:    [[I3:%.*]] = or i32 [[B]], [[A]]
-; CHECK-NEXT:    [[I4:%.*]] = xor i32 [[I3]], -1
-; CHECK-NEXT:    [[I5:%.*]] = or i32 [[I4]], [[I2]]
-; CHECK-NEXT:    ret i32 [[I5]]
+; CHECK-NEXT:    ret i32 [[I]]
 ;
   %i = xor i32 %A, -1
   %i2 = and i32 %B, %i
@@ -450,11 +438,7 @@ define i32 @and_or_not_or7(i32 %A, i32 %B) {
 define i32 @and_or_not_or8(i32 %A, i32 %B) {
 ; CHECK-LABEL: @and_or_not_or8(
 ; CHECK-NEXT:    [[I:%.*]] = xor i32 [[B:%.*]], -1
-; CHECK-NEXT:    [[I2:%.*]] = and i32 [[A:%.*]], [[I]]
-; CHECK-NEXT:    [[I3:%.*]] = or i32 [[B]], [[A]]
-; CHECK-NEXT:    [[I4:%.*]] = xor i32 [[I3]], -1
-; CHECK-NEXT:    [[I5:%.*]] = or i32 [[I4]], [[I2]]
-; CHECK-NEXT:    ret i32 [[I5]]
+; CHECK-NEXT:    ret i32 [[I]]
 ;
   %i = xor i32 %B, -1
   %i2 = and i32 %A, %i


        


More information about the llvm-commits mailing list