[llvm] c65e651 - [InstSimplify] fix logic fold of 'or' for vectors

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 5 06:57:28 PST 2021


Author: Sanjay Patel
Date: 2021-12-05T09:57:07-05:00
New Revision: c65e651e6025dd04b69ea144a94962a5b4716681

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

LOG: [InstSimplify] fix logic fold of 'or' for vectors

Reduce code duplication for commutative pattern matching
and fix a miscompile.

We can't safely propagate an undef element in this transform:
https://alive2.llvm.org/ce/z/s5xy55

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 2f018469871d3..8894a2c1b052e 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2198,6 +2198,18 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
 
   Value *A, *B;
 
+  // (A ^ B) | (A | B) --> A | B
+  // (A ^ B) | (B | A) --> B | A
+  if (match(X, m_Xor(m_Value(A), m_Value(B))) &&
+      match(Y, m_c_Or(m_Specific(A), m_Specific(B))))
+    return Y;
+
+  // ~(A ^ B) | (A | B) --> -1
+  // ~(A ^ B) | (B | A) --> -1
+  if (match(X, m_Not(m_Xor(m_Value(A), m_Value(B)))) &&
+      match(Y, m_c_Or(m_Specific(A), m_Specific(B))))
+    return ConstantInt::getAllOnesValue(Ty);
+
   // (A & ~B) | (A ^ B) --> A ^ B
   // (~B & A) | (A ^ B) --> A ^ B
   // (A & ~B) | (B ^ A) --> B ^ A
@@ -2214,18 +2226,6 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
       match(Y, m_c_And(m_Specific(A), m_Specific(B))))
     return X;
 
-  // (A ^ B) | (A | B) --> A | B
-  // (A ^ B) | (B | A) --> B | A
-  if (match(X, m_Xor(m_Value(A), m_Value(B))) &&
-      match(Y, m_c_Or(m_Specific(A), m_Specific(B))))
-    return Y;
-
-  // ~(A ^ B) | (A | B) --> -1
-  // ~(A ^ B) | (B | A) --> -1
-  if (match(X, m_Not(m_Xor(m_Value(A), m_Value(B)))) &&
-      match(Y, m_c_Or(m_Specific(A), m_Specific(B))))
-    return ConstantInt::getAllOnesValue(Ty);
-
   // (~A | B) | (A ^ B) --> -1
   // (~A | B) | (B ^ A) --> -1
   // (B | ~A) | (A ^ B) --> -1
@@ -2234,6 +2234,17 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
       match(Y, m_c_Xor(m_Specific(A), m_Specific(B))))
     return ConstantInt::getAllOnesValue(Ty);
 
+  // (~A & B) | ~(A | B) --> ~A
+  // (~A & B) | ~(B | A) --> ~A
+  // (B & ~A) | ~(A | B) --> ~A
+  // (B & ~A) | ~(B | A) --> ~A
+  Value *NotA;
+  if (match(X,
+            m_c_And(m_CombineAnd(m_Value(NotA), m_NotForbidUndef(m_Value(A))),
+                    m_Value(B))) &&
+      match(Y, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
+    return NotA;
+
   return nullptr;
 }
 
@@ -2267,27 +2278,6 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
   if (Value *V = simplifyLogicOfAddSub(Op0, Op1, Instruction::Or))
     return V;
 
-  Value *A, *B, *NotA;
-
-  // (~A & B) | ~(A | B) --> ~A
-  // (~A & B) | ~(B | A) --> ~A
-  // (B & ~A) | ~(A | B) --> ~A
-  // (B & ~A) | ~(B | A) --> ~A
-  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 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;
-
   // Rotated -1 is still -1:
   // (-1 << X) | (-1 >> (C - X)) --> -1
   // (-1 >> X) | (-1 << (C - X)) --> -1
@@ -2343,6 +2333,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
   }
 
   // (A & C1)|(B & C2)
+  Value *A, *B;
   const APInt *C1, *C2;
   if (match(Op0, m_And(m_Value(A), m_APInt(C1))) &&
       match(Op1, m_And(m_Value(B), m_APInt(C2)))) {

diff  --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll
index 6591dcedf7ec4..1f56c15ee102b 100644
--- a/llvm/test/Transforms/InstSimplify/or.ll
+++ b/llvm/test/Transforms/InstSimplify/or.ll
@@ -454,12 +454,16 @@ define <2 x i4> @and_or_not_or_commute7(<2 x i4> %A, <2 x i4> %B) {
   ret <2 x i4> %r
 }
 
-; FIXME: It is not safe to propagate an undef element from the 'not' op.
+; negative test - It is not safe to propagate an undef element from the 'not' op.
 
 define <2 x i4> @and_or_not_or_commute7_undef_elt(<2 x i4> %A, <2 x i4> %B) {
 ; CHECK-LABEL: @and_or_not_or_commute7_undef_elt(
 ; CHECK-NEXT:    [[NOTA:%.*]] = xor <2 x i4> [[A:%.*]], <i4 undef, i4 -1>
-; CHECK-NEXT:    ret <2 x i4> [[NOTA]]
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i4> [[B:%.*]], [[NOTA]]
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i4> [[B]], [[A]]
+; CHECK-NEXT:    [[NOTAB:%.*]] = xor <2 x i4> [[OR]], <i4 -1, i4 -1>
+; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[NOTAB]], [[AND]]
+; CHECK-NEXT:    ret <2 x i4> [[R]]
 ;
   %nota = xor <2 x i4> %A, <i4 undef, i4 -1>
   %and = and <2 x i4> %B, %nota


        


More information about the llvm-commits mailing list