[InstCombine] add xor+not folds
authorSanjay Patel <spatel@rotateright.com>
Thu, 6 Sep 2018 16:23:40 +0000 (16:23 +0000)
committerSanjay Patel <spatel@rotateright.com>
Thu, 6 Sep 2018 16:23:40 +0000 (16:23 +0000)
This fold is needed to avoid a regression when we try
to recommit rL300977.
We can't see the most basic win currently because
demanded bits changes the patterns:
https://rise4fun.com/Alive/plpp

llvm-svn: 341559

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

index 9e6f09d..bbe4b9b 100644 (file)
@@ -2702,6 +2702,22 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
       return BinaryOperator::CreateSub(ConstantExpr::getNeg(AddOne(C)), X);
   }
 
+  // Use DeMorgan and reassociation to eliminate a 'not' op.
+  Constant *C1;
+  if (match(Op1, m_Constant(C1))) {
+    Constant *C2;
+    if (match(Op0, m_OneUse(m_Or(m_Not(m_Value(X)), m_Constant(C2))))) {
+      // (~X | C2) ^ C1 --> ((X & ~C2) ^ -1) ^ C1 --> (X & ~C2) ^ ~C1
+      Value *And = Builder.CreateAnd(X, ConstantExpr::getNot(C2));
+      return BinaryOperator::CreateXor(And, ConstantExpr::getNot(C1));
+    }
+    if (match(Op0, m_OneUse(m_And(m_Not(m_Value(X)), m_Constant(C2))))) {
+      // (~X & C2) ^ C1 --> ((X | ~C2) ^ -1) ^ C1 --> (X | ~C2) ^ ~C1
+      Value *Or = Builder.CreateOr(X, ConstantExpr::getNot(C2));
+      return BinaryOperator::CreateXor(Or, ConstantExpr::getNot(C1));
+    }
+  }
+
   // not (cmp A, B) = !cmp A, B
   CmpInst::Predicate Pred;
   if (match(&I, m_Not(m_OneUse(m_Cmp(Pred, m_Value(), m_Value()))))) {
index 51b13be..43a29b8 100644 (file)
@@ -587,7 +587,7 @@ define i32 @and_xor_extra_use(i32 %a, i32 %b, i32* %p) {
   ret i32 %r
 }
 
-; TODO: (~X | C2) ^ C1 --> ((X & ~C2) ^ -1) ^ C1 --> (X & ~C2) ^ ~C1
+; (~X | C2) ^ C1 --> ((X & ~C2) ^ -1) ^ C1 --> (X & ~C2) ^ ~C1
 ; The extra use (store) is here because the simpler case
 ; may be transformed using demanded bits.
 
@@ -595,8 +595,8 @@ define i8 @xor_or_not(i8 %x, i8* %p) {
 ; CHECK-LABEL: @xor_or_not(
 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
 ; CHECK-NEXT:    store i8 [[NX]], i8* [[P:%.*]], align 1
-; CHECK-NEXT:    [[OR:%.*]] = or i8 [[NX]], 7
-; CHECK-NEXT:    [[R:%.*]] = xor i8 [[OR]], 12
+; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X]], -8
+; CHECK-NEXT:    [[R:%.*]] = xor i8 [[TMP1]], -13
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %nx = xor i8 %x, -1
@@ -623,7 +623,7 @@ define i8 @xor_or_not_uses(i8 %x, i8* %p) {
   ret i8 %r
 }
 
-; TODO: (~X & C2) ^ C1 --> ((X | ~C2) ^ -1) ^ C1 --> (X | ~C2) ^ ~C1
+; (~X & C2) ^ C1 --> ((X | ~C2) ^ -1) ^ C1 --> (X | ~C2) ^ ~C1
 ; The extra use (store) is here because the simpler case
 ; may be transformed using demanded bits.
 
@@ -631,8 +631,8 @@ define i8 @xor_and_not(i8 %x, i8* %p) {
 ; CHECK-LABEL: @xor_and_not(
 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
 ; CHECK-NEXT:    store i8 [[NX]], i8* [[P:%.*]], align 1
-; CHECK-NEXT:    [[AND:%.*]] = and i8 [[NX]], 42
-; CHECK-NEXT:    [[R:%.*]] = xor i8 [[AND]], 31
+; CHECK-NEXT:    [[TMP1:%.*]] = or i8 [[X]], -43
+; CHECK-NEXT:    [[R:%.*]] = xor i8 [[TMP1]], -32
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %nx = xor i8 %x, -1