[PATCH] D32458: [InstSimplify] Handle (~A & ~B) | (~A ^ B) -> ~A ^ B

Craig Topper via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 24 16:38:13 PDT 2017


craig.topper created this revision.

The code Sanjay Patel moved over from InstCombine doesn't work properly if the 'and' has both inputs as nots because we used a commuted op matcher on the 'and' first. But this will bind to the first 'not' on 'and' when there could be two 'not's. InstCombine could rely on DeMorgan to ensure the 'and' wouldn't have two 'not's eventually, but InstSimplify can't rely on that.

This patch matches the xor first then checks for the ands and allows a not of either operand of the xor.


https://reviews.llvm.org/D32458

Files:
  lib/Analysis/InstructionSimplify.cpp
  test/Transforms/InstSimplify/AndOrXor.ll


Index: test/Transforms/InstSimplify/AndOrXor.ll
===================================================================
--- test/Transforms/InstSimplify/AndOrXor.ll
+++ test/Transforms/InstSimplify/AndOrXor.ll
@@ -521,3 +521,65 @@
   ret i32 %or
 }
 
+; (~A & ~B) | (~A ^ B) -> ~A ^ B
+
+define i32 @test45(i32 %a, i32 %b) {
+; CHECK-LABEL: @test45(
+; CHECK-NEXT:    [[NEGB:%.*]] = xor i32 [[B:%.*]], -1
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A:%.*]], [[NEGB]]
+; CHECK-NEXT:    ret i32 [[XOR]]
+;
+  %nega = xor i32 %a, -1
+  %negb = xor i32 %b, -1
+  %and = and i32 %nega, %negb
+  %xor = xor i32 %a, %negb
+  %or = or i32 %and, %xor
+  ret i32 %or
+}
+
+define i32 @test45_commuted_and(i32 %a, i32 %b) {
+; CHECK-LABEL: @test45(
+; CHECK-NEXT:    [[NEGB:%.*]] = xor i32 [[B:%.*]], -1
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A:%.*]], [[NEGB]]
+; CHECK-NEXT:    ret i32 [[XOR]]
+;
+  %nega = xor i32 %a, -1
+  %negb = xor i32 %b, -1
+  %and = and i32 %negb, %nega
+  %xor = xor i32 %a, %negb
+  %or = or i32 %and, %xor
+  ret i32 %or
+}
+
+; Commute operands of the 'or'.
+; (~A ^ B) | (~A & ~B) -> ~A ^ B
+
+define i32 @test46(i32 %a, i32 %b) {
+; CHECK-LABEL: @test46(
+; CHECK-NEXT:    [[NEGB:%.*]] = xor i32 [[B:%.*]], -1
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A:%.*]], [[NEGB]]
+; CHECK-NEXT:    ret i32 [[XOR]]
+;
+  %nega = xor i32 %a, -1
+  %negb = xor i32 %b, -1
+  %and = and i32 %nega, %negb
+  %xor = xor i32 %a, %negb
+  %or = or i32 %xor, %and
+  ret i32 %or
+}
+
+; (~A & ~B) | (~A ^ B) -> ~A ^ B
+
+define i32 @test46_commuted_and(i32 %a, i32 %b) {
+; CHECK-LABEL: @test45(
+; CHECK-NEXT:    [[NEGB:%.*]] = xor i32 [[B:%.*]], -1
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A:%.*]], [[NEGB]]
+; CHECK-NEXT:    ret i32 [[XOR]]
+;
+  %nega = xor i32 %a, -1
+  %negb = xor i32 %b, -1
+  %and = and i32 %negb, %nega
+  %xor = xor i32 %a, %negb
+  %or = or i32 %xor, %and
+  ret i32 %or
+}
Index: lib/Analysis/InstructionSimplify.cpp
===================================================================
--- lib/Analysis/InstructionSimplify.cpp
+++ lib/Analysis/InstructionSimplify.cpp
@@ -1886,15 +1886,17 @@
 
   // (A & ~B) | (A ^ B) -> (A ^ B)
   // (~B & A) | (A ^ B) -> (A ^ B)
-  if (match(Op0, m_c_And(m_Value(A), m_Not(m_Value(B)))) &&
-      match(Op1, m_Xor(m_Specific(A), m_Specific(B))))
+  if (match(Op1, m_Xor(m_Value(A), m_Value(B))) &&
+      (match(Op0, m_c_And(m_Specific(A), m_Not(m_Specific(B)))) ||
+       match(Op0, m_c_And(m_Not(m_Specific(A)), m_Specific(B)))))
     return Op1;
 
   // Commute the 'or' operands.
   // (A ^ B) | (A & ~B) -> (A ^ B)
   // (A ^ B) | (~B & A) -> (A ^ B)
-  if (match(Op1, m_c_And(m_Value(A), m_Not(m_Value(B)))) &&
-      match(Op0, m_Xor(m_Specific(A), m_Specific(B))))
+  if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
+      (match(Op1, m_c_And(m_Specific(A), m_Not(m_Specific(B)))) ||
+       match(Op1, m_c_And(m_Not(m_Specific(A)), m_Specific(B)))))
     return Op0;
 
   if (auto *ICILHS = dyn_cast<ICmpInst>(Op0)) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D32458.96482.patch
Type: text/x-patch
Size: 2996 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170424/526f466e/attachment.bin>


More information about the llvm-commits mailing list