[InstCombine] Support (X ^ C1) & C2 --> (X & C2) ^ (C1&C2) for vector splats.
authorCraig Topper <craig.topper@intel.com>
Sun, 6 Aug 2017 23:11:49 +0000 (23:11 +0000)
committerCraig Topper <craig.topper@intel.com>
Sun, 6 Aug 2017 23:11:49 +0000 (23:11 +0000)
llvm-svn: 310233

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

index a2666f4..d7d460b 100644 (file)
@@ -126,14 +126,6 @@ Instruction *InstCombiner::OptAndOp(BinaryOperator *Op,
 
   switch (Op->getOpcode()) {
   default: break;
-  case Instruction::Xor:
-    if (Op->hasOneUse()) {
-      // (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
-      Value *And = Builder.CreateAnd(X, AndRHS);
-      And->takeName(Op);
-      return BinaryOperator::CreateXor(And, Together);
-    }
-    break;
   case Instruction::Or:
     if (Op->hasOneUse()){
       ConstantInt *TogetherCI = dyn_cast<ConstantInt>(Together);
@@ -1280,6 +1272,15 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
       return new ZExtInst(IsZero, I.getType());
     }
 
+    const APInt *XorC;
+    if (match(Op0, m_OneUse(m_Xor(m_Value(X), m_APInt(XorC))))) {
+      // (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
+      Constant *NewC = ConstantInt::get(I.getType(), *C & *XorC);
+      Value *And = Builder.CreateAnd(X, Op1);
+      And->takeName(Op0);
+      return BinaryOperator::CreateXor(And, NewC);
+    }
+
     // If the mask is only needed on one incoming arm, push the 'and' op up.
     if (match(Op0, m_OneUse(m_Xor(m_Value(X), m_Value(Y)))) ||
         match(Op0, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
@@ -1298,6 +1299,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
         return BinaryOperator::Create(BinOp, NewLHS, Y);
       }
     }
+
   }
 
   if (ConstantInt *AndRHS = dyn_cast<ConstantInt>(Op1)) {
index 9cc2ae4..7502152 100644 (file)
@@ -39,8 +39,8 @@ define i32 @flip_and_mask(i32 %x) {
 
 define <2 x i8> @flip_and_mask_splat(<2 x i8> %x) {
 ; CHECK-LABEL: @flip_and_mask_splat(
-; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i8> %x, <i8 1, i8 1>
-; CHECK-NEXT:    [[INC:%.*]] = and <2 x i8> [[TMP1]], <i8 1, i8 1>
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> %x, <i8 1, i8 1>
+; CHECK-NEXT:    [[INC:%.*]] = xor <2 x i8> [[TMP1]], <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i8> [[INC]]
 ;
   %shl = shl <2 x i8> %x, <i8 7, i8 7>