DAGCombiner: Simplify inverted bit tests
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 8 May 2013 06:44:42 +0000 (06:44 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 8 May 2013 06:44:42 +0000 (06:44 +0000)
Fold (xor (and x, y), y) -> (and (not x), y)

This removes an opportunity for a constant to appear twice.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181395 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
test/CodeGen/MSP430/setcc.ll
test/CodeGen/X86/xor.ll

index 2e09ec08fdb1602ae9c3b7500e82d76179d64b22..700ee12072c88f8e4f2429f8418338087605c70f 100644 (file)
@@ -3460,6 +3460,15 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
       return DAG.getNode(NewOpcode, N->getDebugLoc(), VT, LHS, RHS);
     }
   }
+  // fold (xor (and x, y), y) -> (and (not x), y)
+  if (N0.getOpcode() == ISD::AND && N0.getNode()->hasOneUse() &&
+      N0->getOperand(1) == N1) {
+    SDValue X = N0->getOperand(0);
+    SDValue NotX = DAG.getNode(ISD::XOR, X.getDebugLoc(), VT, X,
+      DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT));
+    AddToWorkList(NotX.getNode());
+    return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, NotX, N1);
+  }
   // fold (xor (xor x, c1), c2) -> (xor x, (xor c1, c2))
   if (N1C && N0.getOpcode() == ISD::XOR) {
     ConstantSDNode *N00C = dyn_cast<ConstantSDNode>(N0.getOperand(0));
index c99b17e1436e7d06abf9747652807073ee8b3d99..05f9acd448a5d4051893cb2cc9344283bd164996 100644 (file)
@@ -32,10 +32,10 @@ define i16 @sccwne(i16 %a, i16 %b) nounwind {
 }
 ; CHECK:sccwne:
 ; CHECK:       cmp.w   r14, r15
-; CHECK:       mov.w   r2, r15
-; CHECK:       rra.w   r15
-; CHECK:       and.w   #1, r15
-; CHECK:       xor.w   #1, r15
+; CHECK:       mov.w   r2, r12
+; CHECK:       rra.w   r12
+; CHECK:       mov.w   #1, r15
+; CHECK:       bic.w   r12, r15
 
 define i16 @sccweq(i16 %a, i16 %b) nounwind {
        %t1 = icmp eq i16 %a, %b
@@ -55,9 +55,8 @@ define i16 @sccwugt(i16 %a, i16 %b) nounwind {
 }
 ; CHECK:sccwugt:
 ; CHECK:       cmp.w   r15, r14
-; CHECK:       mov.w   r2, r15
-; CHECK:       and.w   #1, r15
-; CHECK:       xor.w   #1, r15
+; CHECK:       mov.w   #1, r15
+; CHECK:       bic.w   r2, r15
 
 define i16 @sccwuge(i16 %a, i16 %b) nounwind {
        %t1 = icmp uge i16 %a, %b
@@ -76,9 +75,8 @@ define i16 @sccwult(i16 %a, i16 %b) nounwind {
 }
 ; CHECK:sccwult:
 ; CHECK:       cmp.w   r14, r15
-; CHECK:       mov.w   r2, r15
-; CHECK:       and.w   #1, r15
-; CHECK:       xor.w   #1, r15
+; CHECK:       mov.w   #1, r15
+; CHECK:       bic.w   r2, r15
 
 define i16 @sccwule(i16 %a, i16 %b) nounwind {
        %t1 = icmp ule i16 %a, %b
index 996bfc40ee5649fdba63fed53b6aef9417dd18fe..2408bfe72c6011c779c1f5cdd9193990f3cf9b45 100644 (file)
@@ -142,3 +142,15 @@ entry:
 ; X32: test8:
 ; X32:   notl %eax
 }
+
+define i32 @test9(i32 %a) nounwind {
+  %1 = and i32 %a, 4096
+  %2 = xor i32 %1, 4096
+  ret i32 %2
+; X64: test9:
+; X64:    notl [[REG:%[a-z]+]]
+; X64:    andl {{.*}}[[REG:%[a-z]+]]
+; X32: test9:
+; X32:    notl [[REG:%[a-z]+]]
+; X32:    andl {{.*}}[[REG:%[a-z]+]]
+}