[llvm-commits] [llvm] r97616 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp lib/Transforms/InstCombine/InstCombineAndOrXor.cpp test/CodeGen/X86/and-or-fold.ll test/Transforms/InstCombine/xor2.ll

Bill Wendling isanbard at gmail.com
Tue Mar 2 16:35:57 PST 2010


Author: void
Date: Tue Mar  2 18:35:56 2010
New Revision: 97616

URL: http://llvm.org/viewvc/llvm-project?rev=97616&view=rev
Log:
This test case:

long test(long x) { return (x & 123124) | 3; }

Currently compiles to:

_test:
        orl     $3, %edi
        movq    %rdi, %rax
        andq    $123127, %rax
        ret

This is because instruction and DAG combiners canonicalize

  (or (and x, C), D) -> (and (or, D), (C | D))

However, this is only profitable if (C & D) != 0. It gets in the way of the
3-addressification because the input bits are known to be zero.

Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/trunk/test/CodeGen/X86/and-or-fold.ll
    llvm/trunk/test/Transforms/InstCombine/xor2.ll

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=97616&r1=97615&r2=97616&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Tue Mar  2 18:35:56 2010
@@ -1786,7 +1786,7 @@
   SDValue RAND = ReassociateOps(ISD::AND, N->getDebugLoc(), N0, N1);
   if (RAND.getNode() != 0)
     return RAND;
-  // fold (and (or x, 0xFFFF), 0xFF) -> 0xFF
+  // fold (and (or x, C), D) -> D if (C & D) == D
   if (N1C && N0.getOpcode() == ISD::OR)
     if (ConstantSDNode *ORI = dyn_cast<ConstantSDNode>(N0.getOperand(1)))
       if ((ORI->getAPIntValue() & N1C->getAPIntValue()) == N1C->getAPIntValue())
@@ -2025,13 +2025,15 @@
   if (ROR.getNode() != 0)
     return ROR;
   // Canonicalize (or (and X, c1), c2) -> (and (or X, c2), c1|c2)
+  // iff (c1 & c2) == 0.
   if (N1C && N0.getOpcode() == ISD::AND && N0.getNode()->hasOneUse() &&
              isa<ConstantSDNode>(N0.getOperand(1))) {
     ConstantSDNode *C1 = cast<ConstantSDNode>(N0.getOperand(1));
-    return DAG.getNode(ISD::AND, N->getDebugLoc(), VT,
-                       DAG.getNode(ISD::OR, N0.getDebugLoc(), VT,
-                                   N0.getOperand(0), N1),
-                       DAG.FoldConstantArithmetic(ISD::OR, VT, N1C, C1));
+    if ((C1->getZExtValue() & N1C->getZExtValue()) != 0)
+      return DAG.getNode(ISD::AND, N->getDebugLoc(), VT,
+                         DAG.getNode(ISD::OR, N0.getDebugLoc(), VT,
+                                     N0.getOperand(0), N1),
+                         DAG.FoldConstantArithmetic(ISD::OR, VT, N1C, C1));
   }
   // fold (or (setcc x), (setcc y)) -> (setcc (or x, y))
   if (isSetCCEquivalent(N0, LL, LR, CC0) && isSetCCEquivalent(N1, RL, RR, CC1)){

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp?rev=97616&r1=97615&r2=97616&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Tue Mar  2 18:35:56 2010
@@ -1464,8 +1464,7 @@
 
   if (Value *V = SimplifyOrInst(Op0, Op1, TD))
     return ReplaceInstUsesWith(I, V);
-  
-  
+
   // See if we can simplify any instructions used by the instruction whose sole 
   // purpose is to compute bits we don't care about.
   if (SimplifyDemandedInstructionBits(I))
@@ -1474,7 +1473,9 @@
   if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
     ConstantInt *C1 = 0; Value *X = 0;
     // (X & C1) | C2 --> (X | C2) & (C1|C2)
+    // iff (C1 & C2) == 0.
     if (match(Op0, m_And(m_Value(X), m_ConstantInt(C1))) &&
+        (RHS->getValue() & C1->getValue()) != 0 &&
         Op0->hasOneUse()) {
       Value *Or = Builder->CreateOr(X, RHS);
       Or->takeName(Op0);
@@ -1497,6 +1498,7 @@
     if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
       if (Instruction *R = FoldOpIntoSelect(I, SI))
         return R;
+
     if (isa<PHINode>(Op0))
       if (Instruction *NV = FoldOpIntoPhi(I))
         return NV;

Modified: llvm/trunk/test/CodeGen/X86/and-or-fold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/and-or-fold.ll?rev=97616&r1=97615&r2=97616&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/and-or-fold.ll (original)
+++ llvm/trunk/test/CodeGen/X86/and-or-fold.ll Tue Mar  2 18:35:56 2010
@@ -1,14 +1,26 @@
-; RUN: llc < %s -march=x86 | grep and | count 1
+; RUN: llc < %s -mtriple=i686-apple-darwin | FileCheck -check-prefix=DARWIN %s
+; RUN: opt < %s -O2 | llc -mtriple=x86_64-apple-darwin | FileCheck -check-prefix=DARWIN-OPT %s
 
 ; The dag combiner should fold together (x&127)|(y&16711680) -> (x|y)&c1
 ; in this case.
 
-define i32 @test6(i32 %x, i16 %y) {
-        %tmp1 = zext i16 %y to i32              ; <i32> [#uses=1]
-        %tmp2 = and i32 %tmp1, 127              ; <i32> [#uses=1]
-        %tmp4 = shl i32 %x, 16          ; <i32> [#uses=1]
-        %tmp5 = and i32 %tmp4, 16711680         ; <i32> [#uses=1]
-        %tmp6 = or i32 %tmp2, %tmp5             ; <i32> [#uses=1]
-        ret i32 %tmp6
+define i32 @test1(i32 %x, i16 %y) {
+  %tmp1 = zext i16 %y to i32
+  %tmp2 = and i32 %tmp1, 127
+  %tmp4 = shl i32 %x, 16
+  %tmp5 = and i32 %tmp4, 16711680
+  %tmp6 = or i32 %tmp2, %tmp5
+  ret i32 %tmp6
+; DARWIN: andl $16711807, %eax
 }
 
+; <rdar://problem/7529774> The optimizer shouldn't fold this into (and (or, C),  D)
+; if (C & D) == 0
+define i64 @test2(i64 %x) nounwind readnone ssp {
+entry:
+  %tmp1 = and i64 %x, 123127
+  %tmp2 = or i64 %tmp1, 3
+  ret i64 %tmp2
+; DARWIN-OPT:       andq $123124
+; DARWIN-OPT-NEXT:  leaq 3
+}

Modified: llvm/trunk/test/Transforms/InstCombine/xor2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/xor2.ll?rev=97616&r1=97615&r2=97616&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/xor2.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/xor2.ll Tue Mar  2 18:35:56 2010
@@ -22,8 +22,8 @@
 ; PR1014
 define i32 @test2(i32 %tmp1) {
 ; CHECK:      @test2
-; CHECK-NEXT:   or i32 %tmp1, 8 
-; CHECK-NEXT:   and i32
+; CHECK-NEXT:   and i32 %tmp1, 32
+; CHECK-NEXT:   or i32 %ovm, 8 
 ; CHECK-NEXT:   ret i32
         %ovm = and i32 %tmp1, 32
         %ov3 = add i32 %ovm, 145
@@ -33,8 +33,8 @@
 
 define i32 @test3(i32 %tmp1) {
 ; CHECK:      @test3
-; CHECK-NEXT:   or i32 %tmp1, 8 
-; CHECK-NEXT:   and i32
+; CHECK-NEXT:   and i32 %tmp1, 32
+; CHECK-NEXT:   or i32 %tmp, 8
 ; CHECK-NEXT:   ret i32
   %ovm = or i32 %tmp1, 145 
   %ov31 = and i32 %ovm, 177





More information about the llvm-commits mailing list