[PATCH] D114339: [InstCombine] simplify (~A | B) ^ A --> ~( A & B)

Mehrnoosh Heidarpour via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 21 13:37:41 PST 2021


MehrHeidar created this revision.
MehrHeidar added a reviewer: foad.
Herald added a subscriber: hiraditya.
MehrHeidar requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

This bug is reported at : https://bugs.llvm.org/show_bug.cgi?id=52518

According to the Alive2, https://alive2.llvm.org/ce/z/gLrYPk, the transformation seems to be correct and  -O2/-O3 does not do it.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D114339

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


Index: llvm/test/Transforms/InstCombine/xor.ll
===================================================================
--- llvm/test/Transforms/InstCombine/xor.ll
+++ llvm/test/Transforms/InstCombine/xor.ll
@@ -1231,3 +1231,59 @@
   %z = xor i32 %a, %r
   ret i32 %z
 }
+
+; (~A | B) ^ A --> ~(A & B)
+
+define i64 @xor_orn(i64 %a, i64 %b) {
+; CHECK-LABEL: @xor_orn(
+; CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = xor i64 [[TMP1]], -1
+; CHECK-NEXT:    ret i64 [[Z]]
+;
+  %nota = xor i64 %a, -1
+  %l = or i64 %nota, %b
+  %z = xor i64 %l, %a
+  ret i64 %z
+}
+
+; A  ^ (~A | B) --> ~(A & B)
+
+define <4 x i8> @xor_orn_commute1(<4 x i8> %a, <4 x i8> %b) {
+; CHECK-LABEL: @xor_orn_commute1(
+; CHECK-NEXT:    [[TMP1:%.*]] = and <4 x i8> [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = xor <4 x i8> [[TMP1]], <i8 -1, i8 -1, i8 -1, i8 -1>
+; CHECK-NEXT:    ret <4 x i8> [[Z]]
+;
+  %nota = xor <4 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1>
+  %l = or <4 x i8> %nota, %b
+  %z = xor <4 x i8> %a, %l
+  ret <4 x i8> %z
+}
+
+; (B | ~A) ^ A --> ~(A & B)
+
+define i32 @xor_orn_commute2(i32 %a, i32 %b) {
+; CHECK-LABEL: @xor_orn_commute2(
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = xor i32 [[TMP1]], -1
+; CHECK-NEXT:    ret i32 [[Z]]
+;
+  %nota = xor i32 %a, -1
+  %l = or i32 %b, %nota
+  %z = xor i32 %l, %a
+  ret i32 %z
+}
+
+; A ^ (B | ~A) --> ~(A & B)
+
+define i67 @xor_orn_commute3(i67 %a, i67 %b) {
+; CHECK-LABEL: @xor_orn_commute3(
+; CHECK-NEXT:    [[TMP1:%.*]] = and i67 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = xor i67 [[TMP1]], -1
+; CHECK-NEXT:    ret i67 [[Z]]
+;
+  %nota = xor i67 %a, -1
+  %l = or i67 %b, %nota
+  %z = xor i67 %a, %l
+  ret i67 %z
+}
Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3615,6 +3615,10 @@
   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) -- There are 4 commuted variants.
+  if (match(&I, m_c_Xor(m_c_Or(m_Not(m_Value(A)), m_Value(B)), m_Deferred(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;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D114339.388770.patch
Type: text/x-patch
Size: 2546 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211121/9e3e5ffa/attachment.bin>


More information about the llvm-commits mailing list