[PATCH] D109194: [InstCombine] Optimize (a & b) | (~a & c)

Matthias Braun via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 2 14:03:55 PDT 2021


MatzeB created this revision.
MatzeB added reviewers: lebedev.ri, RKSimon, nikic, spatel, reames.
Herald added subscribers: wenlei, hiraditya, mcrosier.
MatzeB requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

(a & b) | (~a & c) can be optimized into (((b ^ c) & a) ^ c)

I found this while comparing md5 implementations...


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D109194

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


Index: llvm/test/Transforms/InstCombine/or.ll
===================================================================
--- llvm/test/Transforms/InstCombine/or.ll
+++ llvm/test/Transforms/InstCombine/or.ll
@@ -1385,3 +1385,33 @@
   %or1 = or i32 %xor, %neg
   ret i32 %or1
 }
+
+define i32 @test_or_and_and_not(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @test_or_and_and_not(
+; CHECK-NEXT:    [[TMP1:%.*]] = freeze i32 [[C:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP2]], [[A:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[TMP3]], [[TMP1]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %and0 = and i32 %a, %b
+  %not_a = xor i32 %a, -1
+  %and1 = and i32 %not_a, %c
+  %or = or i32 %and0, %and1
+  ret i32 %or
+}
+
+define i32 @test_or_and_and_not2(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @test_or_and_and_not2(
+; CHECK-NEXT:    [[TMP1:%.*]] = freeze i32 [[A:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], [[C:%.*]]
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP2]], [[B:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[TMP3]], [[TMP1]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %not_b = xor i32 %b, -1
+  %and0 = and i32 %a, %not_b
+  %and1 = and i32 %b, %c
+  %or = or i32 %and0, %and1
+  ret i32 %or
+}
Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2772,6 +2772,21 @@
       if (Value *V = matchSelectFromAndOr(D, B, C, A))
         return replaceInstUsesWith(I, V);
     }
+
+    // (a & b) | (~a & c)   ->   ((b ^ c_) & a) ^ c_ with c_ = freeze(c)
+    {
+      Value *A, *B, *C;
+      if (Op0->hasOneUse() && Op1->hasOneUse() &&
+          (match(&I, m_BinOp(m_c_And(m_Value(A), m_Value(B)),
+                             m_c_And(m_Not(m_Deferred(A)), m_Value(C)))) ||
+           match(&I, m_BinOp(m_c_And(m_Not(m_Value(A)), m_Value(C)),
+                             m_c_And(m_Deferred(A), m_Value(B)))))) {
+        Value *FrozenC = Builder.CreateFreeze(C);
+        Value *Xor0 = Builder.CreateXor(B, FrozenC);
+        Value *And = Builder.CreateAnd(Xor0, A);
+        return BinaryOperator::CreateXor(And, FrozenC);
+      }
+    }
   }
 
   // (A ^ B) | ((B ^ C) ^ A) -> (A ^ B) | C


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D109194.370398.patch
Type: text/x-patch
Size: 2370 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210902/7e908fa6/attachment-0001.bin>


More information about the llvm-commits mailing list