[PATCH] D12705: InstCombine: match De Morgan's Law hidden by zext ops (PR22723)

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 09:13:57 PDT 2015


spatel updated this revision to Diff 35637.
spatel added a comment.

Patch updated: check operands in tests.


http://reviews.llvm.org/D12705

Files:
  lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
  test/Transforms/InstCombine/demorgan-zext.ll

Index: test/Transforms/InstCombine/demorgan-zext.ll
===================================================================
--- test/Transforms/InstCombine/demorgan-zext.ll
+++ test/Transforms/InstCombine/demorgan-zext.ll
@@ -11,12 +11,10 @@
   ret i32 %or
 
 ; CHECK-LABEL: demorgan_or(
-; CHECK-NEXT:  = zext
-; CHECK-NEXT:  = zext
-; CHECK-NEXT:  = xor
-; CHECK-NEXT:  = xor
-; CHECK-NEXT:  = or
-; CHECK-NEXT:  ret
+; CHECK-NEXT:  %[[AND:.*]] = and i1 %X, %Y
+; CHECK-NEXT:  %[[ZEXT:.*]] = zext i1 %[[AND]] to i32
+; CHECK-NEXT:  %[[XOR:.*]] = xor i32 %[[ZEXT]], 1
+; CHECK-NEXT:  ret i32 %[[XOR]]
 }
 
 define i32 @demorgan_and(i1 %X, i1 %Y) {
@@ -28,11 +26,9 @@
   ret i32 %and
 
 ; CHECK-LABEL: demorgan_and(
-; CHECK-NEXT:  = zext
-; CHECK-NEXT:  = zext
-; CHECK-NEXT:  = xor
-; CHECK-NEXT:  = xor
-; CHECK-NEXT:  = and
-; CHECK-NEXT:  ret
+; CHECK-NEXT:  %[[OR:.*]] = or i1 %X, %Y
+; CHECK-NEXT:  %[[ZEXT:.*]] = zext i1 %[[OR]] to i32
+; CHECK-NEXT:  %[[XOR:.*]] = xor i32 %[[ZEXT]], 1
+; CHECK-NEXT:  ret i32 %[[XOR]]
 }
 
Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1208,23 +1208,43 @@
   auto Opcode = I.getOpcode();
   assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&
          "Trying to match De Morgan's Laws with something other than and/or");
+  // Flip the logic operation.
+  if (Opcode == Instruction::And)
+    Opcode = Instruction::Or;
+  else
+    Opcode = Instruction::And;
 
   Value *Op0 = I.getOperand(0);
   Value *Op1 = I.getOperand(1);
   // TODO: Use pattern matchers instead of dyn_cast.
   if (Value *Op0NotVal = dyn_castNotVal(Op0))
     if (Value *Op1NotVal = dyn_castNotVal(Op1))
       if (Op0->hasOneUse() && Op1->hasOneUse()) {
-        // Flip the logic operation.
-        if (Opcode == Instruction::And)
-          Opcode = Instruction::Or;
-        else
-          Opcode = Instruction::And;
         Value *LogicOp = Builder->CreateBinOp(Opcode, Op0NotVal, Op1NotVal,
                                               I.getName() + ".demorgan");
         return BinaryOperator::CreateNot(LogicOp);
       }
 
+  // De Morgan's Law in disguise:
+  // (zext(bool A) ^ 1) & (zext(bool B) ^ 1) -> zext(~(A | B))
+  // (zext(bool A) ^ 1) | (zext(bool B) ^ 1) -> zext(~(A & B))
+  Value *A = nullptr;
+  Value *B = nullptr;
+  ConstantInt *C1 = nullptr;
+  if (match(Op0, m_OneUse(m_Xor(m_ZExt(m_Value(A)), m_ConstantInt(C1)))) &&
+      match(Op1, m_OneUse(m_Xor(m_ZExt(m_Value(B)), m_Specific(C1))))) {
+    // TODO: This check could be loosened to handle different type sizes.
+    // Alternatively, we could fix the definition of m_Not to recognize a not
+    // operation hidden by a zext?
+    if (A->getType()->isIntegerTy(1) && B->getType()->isIntegerTy(1) &&
+        C1->isOne()) {
+      Value *LogicOp = Builder->CreateBinOp(Opcode, A, B,
+                                            I.getName() + ".demorgan");
+      Value *Not = Builder->CreateNot(LogicOp);
+      return CastInst::CreateZExtOrBitCast(Not, I.getType());
+    }
+  }
+
   return nullptr;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D12705.35637.patch
Type: text/x-patch
Size: 3221 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150924/c2a3ec08/attachment.bin>


More information about the llvm-commits mailing list