Some dag combiner goodness:
authorEvan Cheng <evan.cheng@apple.com>
Thu, 18 Feb 2010 02:13:50 +0000 (02:13 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Thu, 18 Feb 2010 02:13:50 +0000 (02:13 +0000)
Transform br (xor (x, y)) -> br (x != y)
Transform br (xor (xor (x,y), 1)) -> br (x == y)
Also normalize (and (X, 1) == / != 1 -> (and (X, 1)) != / == 0 to match to "test on x86" and "tst on arm"

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

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
lib/CodeGen/SelectionDAG/TargetLowering.cpp
lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/critical-edge-split.ll
test/CodeGen/X86/ins_subreg_coalesce-3.ll
test/CodeGen/X86/omit-label.ll
test/CodeGen/X86/trunc-to-bool.ll

index 7da7848930f1381bc243c02dae490984dd792194..c5dba39e3f810eee1de7a9949691af6e9f4ac3f7 100644 (file)
@@ -4655,7 +4655,8 @@ SDValue DAGCombiner::visitBRCOND(SDNode *N) {
             DAG.DeleteNode(Trunc);
           }
           // Replace the uses of SRL with SETCC
-          DAG.ReplaceAllUsesOfValueWith(N1, SetCC);
+          WorkListRemover DeadNodes(*this);
+          DAG.ReplaceAllUsesOfValueWith(N1, SetCC, &DeadNodes);
           removeFromWorkList(N1.getNode());
           DAG.DeleteNode(N1.getNode());
           return SDValue(N, 0);   // Return N so it doesn't get rechecked!
@@ -4663,6 +4664,53 @@ SDValue DAGCombiner::visitBRCOND(SDNode *N) {
       }
     }
   }
+  
+  // Transform br(xor(x, y)) -> br(x != y)
+  // Transform br(xor(xor(x,y), 1)) -> br (x == y)
+  if (N1.hasOneUse() && N1.getOpcode() == ISD::XOR) {
+    SDNode *TheXor = N1.getNode();
+    SDValue Op0 = TheXor->getOperand(0);
+    SDValue Op1 = TheXor->getOperand(1);
+    if (Op0.getOpcode() == Op1.getOpcode()) {
+      // Avoid missing important xor optimizations.
+      SDValue Tmp = visitXOR(TheXor);
+      if (Tmp.getNode()) {
+        DEBUG(dbgs() << "\nReplacing.8 ";
+              TheXor->dump(&DAG);
+              dbgs() << "\nWith: ";
+              Tmp.getNode()->dump(&DAG);
+              dbgs() << '\n');
+        WorkListRemover DeadNodes(*this);
+        DAG.ReplaceAllUsesOfValueWith(N1, Tmp, &DeadNodes);
+        removeFromWorkList(TheXor);
+        DAG.DeleteNode(TheXor);
+        return DAG.getNode(ISD::BRCOND, N->getDebugLoc(),
+                           MVT::Other, Chain, Tmp, N2);
+      }
+    }
+
+    if (Op0.getOpcode() != ISD::SETCC && Op1.getOpcode() != ISD::SETCC) {
+      bool Equal = false;
+      if (ConstantSDNode *RHSCI = dyn_cast<ConstantSDNode>(Op0))
+        if (RHSCI->getAPIntValue() == 1 && Op0.hasOneUse() &&
+            Op0.getOpcode() == ISD::XOR) {
+          TheXor = Op0.getNode();
+          Equal = true;
+        }
+    
+      SDValue SetCC = DAG.getSetCC(TheXor->getDebugLoc(),
+                                   TLI.getSetCCResultType(N1.getValueType()),
+                                   Op0, Op1,
+                                   Equal ? ISD::SETEQ : ISD::SETNE);
+      // Replace the uses of XOR with SETCC
+      WorkListRemover DeadNodes(*this);
+      DAG.ReplaceAllUsesOfValueWith(N1, SetCC, &DeadNodes);
+      removeFromWorkList(N1.getNode());
+      DAG.DeleteNode(N1.getNode());
+      return DAG.getNode(ISD::BRCOND, N->getDebugLoc(),
+                         MVT::Other, Chain, SetCC, N2);
+    }
+  }
 
   return SDValue();
 }
@@ -5012,7 +5060,7 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) {
       assert(N->getValueType(2) == MVT::Other && "Malformed indexed loads?");
       if (N->hasNUsesOfValue(0, 0) && N->hasNUsesOfValue(0, 1)) {
         SDValue Undef = DAG.getUNDEF(N->getValueType(0));
-        DEBUG(dbgs() << "\nReplacing.6 ";
+        DEBUG(dbgs() << "\nReplacing.7 ";
               N->dump(&DAG);
               dbgs() << "\nWith: ";
               Undef.getNode()->dump(&DAG);
index e88af4f3e02c185a43bb22c3347fabfc401138b7..9f9d8b0ffd53e623ca0c88901fdc3cf50320b7a7 100644 (file)
@@ -1775,7 +1775,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
         break;   // todo, be more careful with signed comparisons
       }
     } else if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG &&
-                (Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
+               (Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
       EVT ExtSrcTy = cast<VTSDNode>(N0.getOperand(1))->getVT();
       unsigned ExtSrcTyBits = ExtSrcTy.getSizeInBits();
       EVT ExtDstTy = N0.getValueType();
@@ -1809,7 +1809,6 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
                           Cond);
     } else if ((N1C->isNullValue() || N1C->getAPIntValue() == 1) &&
                 (Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
-      
       // SETCC (SETCC), [0|1], [EQ|NE]  -> SETCC
       if (N0.getOpcode() == ISD::SETCC) {
         bool TrueWhenTrue = (Cond == ISD::SETEQ) ^ (N1C->getAPIntValue() != 1);
@@ -1822,9 +1821,9 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
                                   N0.getOperand(0).getValueType().isInteger());
         return DAG.getSetCC(dl, VT, N0.getOperand(0), N0.getOperand(1), CC);
       }
-      
+
       if ((N0.getOpcode() == ISD::XOR ||
-            (N0.getOpcode() == ISD::AND && 
+           (N0.getOpcode() == ISD::AND && 
             N0.getOperand(0).getOpcode() == ISD::XOR &&
             N0.getOperand(1) == N0.getOperand(0).getOperand(1))) &&
           isa<ConstantSDNode>(N0.getOperand(1)) &&
@@ -1847,9 +1846,26 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
                               N0.getOperand(0).getOperand(0),
                               N0.getOperand(1));
           }
+
           return DAG.getSetCC(dl, VT, Val, N1,
                               Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ);
         }
+      } else if (N1C->getAPIntValue() == 1) {
+        // If this is (X&1) == / != 1, normalize it to (X&1) != / == 0.
+        SDValue Op0 = N0;
+        if (Op0.getOpcode() == ISD::TRUNCATE)
+          Op0 = Op0.getOperand(0);
+        if (Op0.getOpcode() == ISD::AND &&
+            isa<ConstantSDNode>(Op0.getOperand(1)) &&
+            cast<ConstantSDNode>(Op0.getOperand(1))->getAPIntValue() == 1) {
+          if (Op0.getValueType() != VT)
+            Op0 = DAG.getNode(ISD::AND, dl, VT,
+                          DAG.getNode(ISD::TRUNCATE, dl, VT, Op0.getOperand(0)),
+                          DAG.getConstant(1, VT));
+          return DAG.getSetCC(dl, VT, Op0,
+                              DAG.getConstant(0, Op0.getValueType()),
+                              Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ);
+        }
       }
     }
     
index 4c40fe1803e92ef22a45dff38c1c11f19655e55d..7b203f285ca55ab0c96d559a3f9913de81039779 100644 (file)
@@ -5874,26 +5874,31 @@ SDValue X86TargetLowering::EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC,
 
 /// LowerToBT - Result of 'and' is compared against zero. Turn it into a BT node
 /// if it's possible.
-static SDValue LowerToBT(SDValue Op0, ISD::CondCode CC,
+static SDValue LowerToBT(SDValue And, ISD::CondCode CC,
                          DebugLoc dl, SelectionDAG &DAG) {
+  SDValue Op0 = And.getOperand(0);
+  SDValue Op1 = And.getOperand(1);
+  if (Op0.getOpcode() == ISD::TRUNCATE)
+    Op0 = Op0.getOperand(0);
+  if (Op1.getOpcode() == ISD::TRUNCATE)
+    Op1 = Op1.getOperand(0);
+
   SDValue LHS, RHS;
-  if (Op0.getOperand(1).getOpcode() == ISD::SHL) {
-    if (ConstantSDNode *Op010C =
-        dyn_cast<ConstantSDNode>(Op0.getOperand(1).getOperand(0)))
-      if (Op010C->getZExtValue() == 1) {
-        LHS = Op0.getOperand(0);
-        RHS = Op0.getOperand(1).getOperand(1);
+  if (Op1.getOpcode() == ISD::SHL) {
+    if (ConstantSDNode *And10C = dyn_cast<ConstantSDNode>(Op1.getOperand(0)))
+      if (And10C->getZExtValue() == 1) {
+        LHS = Op0;
+        RHS = Op1.getOperand(1);
       }
-  } else if (Op0.getOperand(0).getOpcode() == ISD::SHL) {
-    if (ConstantSDNode *Op000C =
-        dyn_cast<ConstantSDNode>(Op0.getOperand(0).getOperand(0)))
-      if (Op000C->getZExtValue() == 1) {
-        LHS = Op0.getOperand(1);
-        RHS = Op0.getOperand(0).getOperand(1);
+  } else if (Op0.getOpcode() == ISD::SHL) {
+    if (ConstantSDNode *And00C = dyn_cast<ConstantSDNode>(Op0.getOperand(0)))
+      if (And00C->getZExtValue() == 1) {
+        LHS = Op1;
+        RHS = Op0.getOperand(1);
       }
-  } else if (Op0.getOperand(1).getOpcode() == ISD::Constant) {
-    ConstantSDNode *AndRHS = cast<ConstantSDNode>(Op0.getOperand(1));
-    SDValue AndLHS = Op0.getOperand(0);
+  } else if (Op1.getOpcode() == ISD::Constant) {
+    ConstantSDNode *AndRHS = cast<ConstantSDNode>(Op1);
+    SDValue AndLHS = Op0;
     if (AndRHS->getZExtValue() == 1 && AndLHS.getOpcode() == ISD::SRL) {
       LHS = AndLHS.getOperand(0);
       RHS = AndLHS.getOperand(1);
@@ -5943,6 +5948,17 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) {
       return NewSetCC;
   }
 
+  // Look for "(setcc) == / != 1" to avoid unncessary setcc.
+  if (Op0.getOpcode() == X86ISD::SETCC &&
+      Op1.getOpcode() == ISD::Constant &&
+      cast<ConstantSDNode>(Op1)->getZExtValue() == 1 &&
+      (CC == ISD::SETEQ || CC == ISD::SETNE)) {
+    X86::CondCode CCode = (X86::CondCode)Op0.getConstantOperandVal(0);
+    CCode = X86::GetOppositeBranchCondition(CCode);
+    return DAG.getNode(X86ISD::SETCC, dl, MVT::i8,
+                       DAG.getConstant(CCode, MVT::i8), Op0.getOperand(1));
+  }
+
   bool isFP = Op.getOperand(1).getValueType().isFloatingPoint();
   unsigned X86CC = TranslateX86CC(CC, isFP, Op0, Op1, DAG);
   if (X86CC == X86::COND_INVALID)
index 4fe554de75a027f95f3852d6b7eae0a7dc7d63b7..f29cbf323e376b5d9957c22a02e27ebed0074d29 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mtriple=i386-apple-darwin -tailcallopt=false -stats -info-output-file - | grep asm-printer | grep 31
+; RUN: llc < %s -mtriple=i386-apple-darwin -stats -info-output-file - | grep asm-printer | grep 29
 
        %CC = type { %Register }
        %II = type { %"struct.XX::II::$_74" }
index 627edc51c18d761a25e981974a48425e422951ee..8c1c40976605a568d891a180d83e7704b3288c3e 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=x86-64 | grep mov | count 5
+; RUN: llc < %s -march=x86-64 | grep mov | count 3
 
        %struct.COMPOSITE = type { i8, i16, i16 }
        %struct.FILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 }
index 0ec03ebace8969c87745ddd6fd248ff17b90edff..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,57 +0,0 @@
-; RUN: llc < %s -asm-verbose=false -mtriple=x86_64-linux-gnu | FileCheck %s
-; PR4126
-; PR4732
-
-; Don't omit these labels' definitions.
-
-; CHECK: bux:
-; CHECK: LBB1_1:
-
-define void @bux(i32 %p_53) nounwind optsize {
-entry:
-       %0 = icmp eq i32 %p_53, 0               ; <i1> [#uses=1]
-       %1 = icmp sgt i32 %p_53, 0              ; <i1> [#uses=1]
-       %or.cond = and i1 %0, %1                ; <i1> [#uses=1]
-       br i1 %or.cond, label %bb.i, label %bb3
-
-bb.i:          ; preds = %entry
-       %2 = add i32 %p_53, 1           ; <i32> [#uses=1]
-       %3 = icmp slt i32 %2, 0         ; <i1> [#uses=0]
-       br label %bb3
-
-bb3:           ; preds = %bb.i, %entry
-       %4 = tail call i32 (...)* @baz(i32 0) nounwind          ; <i32> [#uses=0]
-       ret void
-}
-
-declare i32 @baz(...)
-
-; Don't omit this label in the assembly output.
-; CHECK: int321:
-; CHECK: LBB2_1
-; CHECK: LBB2_1
-; CHECK: LBB2_1:
-
-define void @int321(i8 signext %p_103, i32 %uint8p_104) nounwind readnone {
-entry:
-  %tobool = icmp eq i8 %p_103, 0                  ; <i1> [#uses=1]
-  %cmp.i = icmp sgt i8 %p_103, 0                  ; <i1> [#uses=1]
-  %or.cond = and i1 %tobool, %cmp.i               ; <i1> [#uses=1]
-  br i1 %or.cond, label %land.end.i, label %for.cond.preheader
-
-land.end.i:                                       ; preds = %entry
-  %conv3.i = sext i8 %p_103 to i32                ; <i32> [#uses=1]
-  %div.i = sdiv i32 1, %conv3.i                   ; <i32> [#uses=1]
-  %tobool.i = icmp eq i32 %div.i, -2147483647     ; <i1> [#uses=0]
-  br label %for.cond.preheader
-
-for.cond.preheader:                               ; preds = %land.end.i, %entry
-  %cmp = icmp sgt i8 %p_103, 1                    ; <i1> [#uses=1]
-  br i1 %cmp, label %for.end.split, label %for.cond
-
-for.cond:                                         ; preds = %for.cond.preheader, %for.cond
-  br label %for.cond
-
-for.end.split:                                    ; preds = %for.cond.preheader
-  ret void
-}
index bfab1aef901431f2a48b47c65ddd700836e7815d..60620841064f68f6c1b5cb46043cd2a033f1d3d7 100644 (file)
@@ -3,13 +3,14 @@
 ; value and as the operand of a branch.
 ; RUN: llc < %s -march=x86 | FileCheck %s
 
-define i1 @test1(i32 %X) zeroext {
+define i1 @test1(i32 %X) zeroext nounwind {
     %Y = trunc i32 %X to i1
     ret i1 %Y
 }
+; CHECK: test1:
 ; CHECK: andl $1, %eax
 
-define i1 @test2(i32 %val, i32 %mask) {
+define i1 @test2(i32 %val, i32 %mask) nounwind {
 entry:
     %shifted = ashr i32 %val, %mask
     %anded = and i32 %shifted, 1
@@ -20,9 +21,10 @@ ret_true:
 ret_false:
     ret i1 false
 }
-; CHECK: testb $1, %al
+; CHECK: test2:
+; CHECK: btl %eax
 
-define i32 @test3(i8* %ptr) {
+define i32 @test3(i8* %ptr) nounwind {
     %val = load i8* %ptr
     %tmp = trunc i8 %val to i1
     br i1 %tmp, label %cond_true, label %cond_false
@@ -31,9 +33,10 @@ cond_true:
 cond_false:
     ret i32 42
 }
-; CHECK: testb $1, %al
+; CHECK: test3:
+; CHECK: testb $1, (%eax)
 
-define i32 @test4(i8* %ptr) {
+define i32 @test4(i8* %ptr) nounwind {
     %tmp = ptrtoint i8* %ptr to i1
     br i1 %tmp, label %cond_true, label %cond_false
 cond_true:
@@ -41,9 +44,10 @@ cond_true:
 cond_false:
     ret i32 42
 }
-; CHECK: testb $1, %al
+; CHECK: test4:
+; CHECK: testb $1, 4(%esp)
 
-define i32 @test6(double %d) {
+define i32 @test5(double %d) nounwind {
     %tmp = fptosi double %d to i1
     br i1 %tmp, label %cond_true, label %cond_false
 cond_true:
@@ -51,4 +55,5 @@ cond_true:
 cond_false:
     ret i32 42
 }
+; CHECK: test5:
 ; CHECK: testb $1