[PATCH] D86395: InstCombine transform pattern "(~A & B) ^ A -> (A | B)" added

Jaydeep Chauhan via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 7 09:36:24 PDT 2020


Jac1494 updated this revision to Diff 290305.
Jac1494 added a comment.

@spatel test cases are updated as per your review comments. Thanks for this.
And these test cases were failing without this patch. So it means that patch is doing correct transformations.

IR Without my patch(for test52):-

  define i32 @test52(i32 %0, i32 %1) {
    %3 = xor i32 %0, -1
    %4 = and i32 %3, %1
    %5 = xor i32 %4, %0
    ret i32 %5
  }

IR after my patch(Transformation applied):-

  define i32 @test52(i32 %0, i32 %1) {
    %3 = or i32 %1, %0
    ret i32 %3
  }




CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86395/new/

https://reviews.llvm.org/D86395

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
@@ -1161,3 +1161,65 @@
   %r = xor i8 %a, -2
   ret i8 %r
 }
+
+; (~A & B) ^ A  -->   (A | B)
+; The division ops are here to thwart complexity-based canonicalization: all ops are binops.
+
+define i32 @test52(i32 %p1, i32 %p2) {
+; CHECK-LABEL: @test52(
+; CHECK-NEXT:    [[A:%.*]] = udiv i32 42, [[P1:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = udiv i32 42, [[P2:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = or i32 [[A]], [[B]]
+; CHECK-NEXT:    ret i32 [[Z]]
+  %a = udiv i32 42, %p1
+  %o = xor i32 %a, -1
+  %b = udiv i32 42, %p2
+  %r = and i32 %o, %b
+  %z = xor i32 %r, %a
+  ret i32 %z
+}
+
+; (~B & A) ^ B  -->   (A | B)
+; The division ops are here to thwart complexity-based canonicalization: all ops are binops.
+
+define i32 @test53(i32 %p1, i32 %p2) {
+; CHECK-LABEL: @test53(
+; CHECK-NEXT:    [[A:%.*]] = udiv i32 42, [[P1:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = udiv i32 42, [[P2:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = or i32 [[A]], [[B]]
+; CHECK-NEXT:    ret i32 [[Z]]
+  %b = udiv i32 42, %p2
+  %o = xor i32 %b, -1
+  %a = udiv i32 42, %p1
+  %r = and i32 %o, %a
+  %z = xor i32 %r, %b
+  ret i32 %z
+}
+
+define i32 @test54(i32 %p1, i32 %p2) {
+; CHECK-LABEL: @test54(
+; CHECK-NEXT:    [[A:%.*]] = udiv i32 42, [[P1:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = udiv i32 42, [[P2:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = or i32 [[A]], [[B]]
+; CHECK-NEXT:    ret i32 [[Z]]
+  %a = udiv i32 42, %p1
+  %o = xor i32 %a, -1
+  %b = udiv i32 42, %p2
+  %r = and i32 %b, %o
+  %z = xor i32 %r, %a
+  ret i32 %z
+}
+
+define i32 @test55(i32 %p1, i32 %p2) {
+; CHECK-LABEL: @test55(
+; CHECK-NEXT:    [[A:%.*]] = udiv i32 42, [[P1:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = udiv i32 42, [[P2:%.*]]
+; CHECK-NEXT:    [[Z:%.*]] = or i32 [[A]], [[B]]
+; CHECK-NEXT:    ret i32 [[Z]]
+  %a = udiv i32 42, %p1
+  %o = xor i32 %a, -1
+  %b = udiv i32 42, %p2
+  %r = and i32 %o, %b
+  %z = xor i32 %a, %r
+  ret i32 %z
+}
Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3353,6 +3353,10 @@
       match(Op1, m_Not(m_Specific(A))))
     return BinaryOperator::CreateNot(Builder.CreateAnd(A, B));
 
+  // (~A & B) ^ A  -->   (A | B)
+  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 | 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: D86395.290305.patch
Type: text/x-patch
Size: 2793 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200907/3fa6967c/attachment.bin>


More information about the llvm-commits mailing list