[llvm] c572eb1 - [InstCombine] Fold (~A | B) ^ A --> ~(A & B)

Mehrnoosh Heidarpour via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 29 08:31:11 PST 2021


Author: Mehrnoosh Heidarpour
Date: 2021-11-29T11:29:21-05:00
New Revision: c572eb1ad9d8a528bcaff0160888aff31b1f4b5f

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

LOG: [InstCombine] Fold (~A | B) ^ A --> ~(A & B)

https://alive2.llvm.org/ce/z/gLrYPk

Fixes:
https://llvm.org/PR52518

Reviewed by: spatel

Differential revision: https://reviews.llvm.org/D114339

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 20c641210f99b..15f1d8790a7fe 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3623,6 +3623,14 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
   if (match(&I, m_c_Xor(m_c_And(m_Not(m_Value(A)), m_Value(B)), m_Deferred(A))))
     return BinaryOperator::CreateOr(A, B);
 
+  // (~A | B) ^ A --> ~(A & B)
+  if (match(Op0, m_OneUse(m_c_Or(m_Not(m_Specific(Op1)), m_Value(B)))))
+    return BinaryOperator::CreateNot(Builder.CreateAnd(Op1, B));
+
+  // A ^ (~A | B) --> ~(A & B)
+  if (match(Op1, m_OneUse(m_c_Or(m_Not(m_Specific(Op0)), m_Value(B)))))
+    return BinaryOperator::CreateNot(Builder.CreateAnd(Op0, 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;

diff  --git a/llvm/test/Transforms/InstCombine/xor.ll b/llvm/test/Transforms/InstCombine/xor.ll
index d7e0186ab126c..d1499a1fd4aef 100644
--- a/llvm/test/Transforms/InstCombine/xor.ll
+++ b/llvm/test/Transforms/InstCombine/xor.ll
@@ -1236,9 +1236,8 @@ define i32 @xor_andn_commute4(i32 %pa, i32 %pb) {
 
 define <2 x i64> @xor_orn(<2 x i64> %a, <2 x i64> %b) {
 ; CHECK-LABEL: @xor_orn(
-; CHECK-NEXT:    [[NOTA:%.*]] = xor <2 x i64> [[A:%.*]], <i64 -1, i64 -1>
-; CHECK-NEXT:    [[L:%.*]] = or <2 x i64> [[NOTA]], [[B:%.*]]
-; CHECK-NEXT:    [[Z:%.*]] = xor <2 x i64> [[L]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i64> [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = xor <2 x i64> [[TMP1]], <i64 -1, i64 -1>
 ; CHECK-NEXT:    ret <2 x i64> [[Z]]
 ;
   %nota = xor <2 x i64> %a, <i64 -1, i64 -1>
@@ -1252,9 +1251,8 @@ define <2 x i64> @xor_orn(<2 x i64> %a, <2 x i64> %b) {
 define i8 @xor_orn_commute1(i8 %pa, i8 %b) {
 ; CHECK-LABEL: @xor_orn_commute1(
 ; CHECK-NEXT:    [[A:%.*]] = udiv i8 42, [[PA:%.*]]
-; CHECK-NEXT:    [[NOTA:%.*]] = xor i8 [[A]], -1
-; CHECK-NEXT:    [[L:%.*]] = or i8 [[NOTA]], [[B:%.*]]
-; CHECK-NEXT:    [[Z:%.*]] = xor i8 [[A]], [[L]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[A]], [[B:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = xor i8 [[TMP1]], -1
 ; CHECK-NEXT:    ret i8 [[Z]]
 ;
   %a = udiv i8 42, %pa
@@ -1269,9 +1267,8 @@ define i8 @xor_orn_commute1(i8 %pa, i8 %b) {
 define i32 @xor_orn_commute2(i32 %a, i32 %pb,i32* %s) {
 ; CHECK-LABEL: @xor_orn_commute2(
 ; CHECK-NEXT:    [[B:%.*]] = udiv i32 42, [[PB:%.*]]
-; CHECK-NEXT:    [[NOTA:%.*]] = xor i32 [[A:%.*]], -1
-; CHECK-NEXT:    [[L:%.*]] = or i32 [[B]], [[NOTA]]
-; CHECK-NEXT:    [[Z:%.*]] = xor i32 [[L]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[B]], [[A:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = xor i32 [[TMP1]], -1
 ; CHECK-NEXT:    ret i32 [[Z]]
 ;
   %b = udiv i32 42, %pb
@@ -1281,14 +1278,13 @@ define i32 @xor_orn_commute2(i32 %a, i32 %pb,i32* %s) {
   ret i32 %z
 }
 
-
 define i32 @xor_orn_commute2_1use(i32 %a, i32 %pb,i32* %s) {
 ; CHECK-LABEL: @xor_orn_commute2_1use(
 ; CHECK-NEXT:    [[B:%.*]] = udiv i32 42, [[PB:%.*]]
 ; CHECK-NEXT:    [[NOTA:%.*]] = xor i32 [[A:%.*]], -1
-; CHECK-NEXT:    [[L:%.*]] = or i32 [[B]], [[NOTA]]
 ; CHECK-NEXT:    store i32 [[NOTA]], i32* [[S:%.*]], align 4
-; CHECK-NEXT:    [[Z:%.*]] = xor i32 [[L]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[B]], [[A]]
+; CHECK-NEXT:    [[Z:%.*]] = xor i32 [[TMP1]], -1
 ; CHECK-NEXT:    ret i32 [[Z]]
 ;
   %b = udiv i32 42, %pb
@@ -1305,9 +1301,8 @@ define i67 @xor_orn_commute3(i67 %pa, i67 %pb, i67* %s) {
 ; CHECK-LABEL: @xor_orn_commute3(
 ; CHECK-NEXT:    [[A:%.*]] = udiv i67 42, [[PA:%.*]]
 ; CHECK-NEXT:    [[B:%.*]] = udiv i67 42, [[PB:%.*]]
-; CHECK-NEXT:    [[NOTA:%.*]] = xor i67 [[A]], -1
-; CHECK-NEXT:    [[L:%.*]] = or i67 [[B]], [[NOTA]]
-; CHECK-NEXT:    [[Z:%.*]] = xor i67 [[A]], [[L]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i67 [[A]], [[B]]
+; CHECK-NEXT:    [[Z:%.*]] = xor i67 [[TMP1]], -1
 ; CHECK-NEXT:    ret i67 [[Z]]
 ;
   %a = udiv i67 42, %pa
@@ -1337,7 +1332,6 @@ define i67 @xor_orn_commute3_1use(i67 %pa, i67 %pb, i67* %s) {
   ret i67 %z
 }
 
-
 define i32 @xor_orn_2use(i32 %a, i32 %b, i32* %s1, i32* %s2) {
 ; CHECK-LABEL: @xor_orn_2use(
 ; CHECK-NEXT:    [[NOTA:%.*]] = xor i32 [[A:%.*]], -1


        


More information about the llvm-commits mailing list