[llvm] b46427b - [InstSimplify] (~A & B) | ~(A | B) --> ~A with logical and

David Green via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 7 02:03:34 PST 2022


Author: David Green
Date: 2022-11-07T10:03:18Z
New Revision: b46427b9a2fa2587e9087ab7e2bbb2c5abbb30e3

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

LOG: [InstSimplify] (~A & B) | ~(A | B) --> ~A with logical and

According to https://alive2.llvm.org/ce/z/opsdrb, it is valid to convert
(~A & B) | ~(A | B) --> ~A even if the And is a Logical And. This came
up from the vector masking of predicated blocks.

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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index acfac8cb9437c..98db224e9e809 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2198,6 +2198,7 @@ Value *llvm::simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
   return ::simplifyAndInst(Op0, Op1, Q, RecursionLimit);
 }
 
+// TODO: Many of these folds could use LogicalAnd/LogicalOr.
 static Value *simplifyOrLogic(Value *X, Value *Y) {
   assert(X->getType() == Y->getType() && "Expected same type for 'or' ops");
   Type *Ty = X->getType();
@@ -2262,6 +2263,14 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
                     m_Value(B))) &&
       match(Y, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
     return NotA;
+  // The same is true of Logical And
+  // TODO: This could share the logic of the version above if there was a
+  // version of LogicalAnd that allowed more than just i1 types.
+  if (match(X, m_c_LogicalAnd(
+                   m_CombineAnd(m_Value(NotA), m_NotForbidUndef(m_Value(A))),
+                   m_Value(B))) &&
+      match(Y, m_Not(m_c_LogicalOr(m_Specific(A), m_Specific(B)))))
+    return NotA;
 
   // ~(A ^ B) | (A & B) --> ~(A ^ B)
   // ~(A ^ B) | (B & A) --> ~(A ^ B)

diff  --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll
index fa10eefb87987..25cf241f44c07 100644
--- a/llvm/test/Transforms/InstCombine/or.ll
+++ b/llvm/test/Transforms/InstCombine/or.ll
@@ -1564,14 +1564,8 @@ define i32 @mul_common_bits(i32 %p) {
 
 define <4 x i1> @and_or_not_or_logical_vec(<4 x i32> %ap, <4 x i32> %bp) {
 ; CHECK-LABEL: @and_or_not_or_logical_vec(
-; CHECK-NEXT:    [[A:%.*]] = icmp eq <4 x i32> [[AP:%.*]], zeroinitializer
-; CHECK-NEXT:    [[B:%.*]] = icmp eq <4 x i32> [[BP:%.*]], zeroinitializer
-; CHECK-NEXT:    [[V:%.*]] = xor <4 x i1> [[A]], <i1 true, i1 true, i1 true, i1 true>
-; CHECK-NEXT:    [[X:%.*]] = select <4 x i1> [[B]], <4 x i1> [[V]], <4 x i1> zeroinitializer
-; CHECK-NEXT:    [[W:%.*]] = or <4 x i1> [[B]], [[A]]
-; CHECK-NEXT:    [[Y:%.*]] = xor <4 x i1> [[W]], <i1 true, i1 true, i1 true, i1 true>
-; CHECK-NEXT:    [[Z:%.*]] = or <4 x i1> [[X]], [[Y]]
-; CHECK-NEXT:    ret <4 x i1> [[Z]]
+; CHECK-NEXT:    [[A:%.*]] = icmp ne <4 x i32> [[AP:%.*]], zeroinitializer
+; CHECK-NEXT:    ret <4 x i1> [[A]]
 ;
   %A = icmp eq <4 x i32> %ap, zeroinitializer
   %B = icmp eq <4 x i32> %bp, zeroinitializer

diff  --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll
index ddfa85cc4b642..913b760dd331c 100644
--- a/llvm/test/Transforms/InstSimplify/or.ll
+++ b/llvm/test/Transforms/InstSimplify/or.ll
@@ -458,11 +458,7 @@ define <2 x i4> @and_or_not_or_commute7(<2 x i4> %A, <2 x i4> %B) {
 define i1 @and_or_not_or_logical(i1 %A, i1 %B) {
 ; CHECK-LABEL: @and_or_not_or_logical(
 ; CHECK-NEXT:    [[V:%.*]] = xor i1 [[A:%.*]], true
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[V]], i1 [[B:%.*]], i1 false
-; CHECK-NEXT:    [[W:%.*]] = or i1 [[B]], [[A]]
-; CHECK-NEXT:    [[Y:%.*]] = xor i1 [[W]], true
-; CHECK-NEXT:    [[Z:%.*]] = or i1 [[X]], [[Y]]
-; CHECK-NEXT:    ret i1 [[Z]]
+; CHECK-NEXT:    ret i1 [[V]]
 ;
   %V = xor i1 %A, true
   %X = select i1 %V, i1 %B, i1 false
@@ -476,11 +472,7 @@ define i1 @and_or_not_or_logical(i1 %A, i1 %B) {
 define i1 @and_or_not_or_logical_rev(i1 %A, i1 %B) {
 ; CHECK-LABEL: @and_or_not_or_logical_rev(
 ; CHECK-NEXT:    [[V:%.*]] = xor i1 [[A:%.*]], true
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[B:%.*]], i1 [[V]], i1 false
-; CHECK-NEXT:    [[W:%.*]] = or i1 [[B]], [[A]]
-; CHECK-NEXT:    [[Y:%.*]] = xor i1 [[W]], true
-; CHECK-NEXT:    [[Z:%.*]] = or i1 [[X]], [[Y]]
-; CHECK-NEXT:    ret i1 [[Z]]
+; CHECK-NEXT:    ret i1 [[V]]
 ;
   %V = xor i1 %A, true
   %X = select i1 %B, i1 %V, i1 false
@@ -494,11 +486,7 @@ define i1 @and_or_not_or_logical_rev(i1 %A, i1 %B) {
 define i1 @and_or_not_logical_or_logical_rev(i1 %A, i1 %B) {
 ; CHECK-LABEL: @and_or_not_logical_or_logical_rev(
 ; CHECK-NEXT:    [[V:%.*]] = xor i1 [[A:%.*]], true
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[B:%.*]], i1 [[V]], i1 false
-; CHECK-NEXT:    [[W:%.*]] = select i1 [[B]], i1 true, i1 [[A]]
-; CHECK-NEXT:    [[Y:%.*]] = xor i1 [[W]], true
-; CHECK-NEXT:    [[Z:%.*]] = or i1 [[X]], [[Y]]
-; CHECK-NEXT:    ret i1 [[Z]]
+; CHECK-NEXT:    ret i1 [[V]]
 ;
   %V = xor i1 %A, true
   %X = select i1 %B, i1 %V, i1 false


        


More information about the llvm-commits mailing list