Added support for new condition code modeling scheme (i.e. physical register dependen...
[oota-llvm.git] / lib / Target / X86 / X86ISelLowering.cpp
index 5343361a9e125fd9e9017c343c3316f843223474..ab704a74d70d4bcbae2610178eeb50681cc31414 100644 (file)
@@ -31,6 +31,7 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Target/TargetAsmInfo.h"
 #include "llvm/Target/TargetOptions.h"
@@ -3337,41 +3338,58 @@ SDOperand X86TargetLowering::LowerShift(SDOperand Op, SelectionDAG &DAG) {
     SDOperand AndNode = DAG.getNode(ISD::AND, MVT::i8, ShAmt,
                                     DAG.getConstant(32, MVT::i8));
     SDOperand COps[]={DAG.getEntryNode(), AndNode, DAG.getConstant(0, MVT::i8)};
-    SDOperand InFlag = DAG.getNode(X86ISD::CMP, VTs, 2, COps, 3).getValue(1);
+    SDOperand Cond = NewCCModeling
+      ? DAG.getNode(X86ISD::CMP_NEW, MVT::i32,
+                    AndNode, DAG.getConstant(0, MVT::i8))
+      : DAG.getNode(X86ISD::CMP, VTs, 2, COps, 3).getValue(1);
 
     SDOperand Hi, Lo;
     SDOperand CC = DAG.getConstant(X86::COND_NE, MVT::i8);
-
+    unsigned Opc = NewCCModeling ? X86ISD::CMOV_NEW : X86ISD::CMOV;
     VTs = DAG.getNodeValueTypes(MVT::i32, MVT::Flag);
     SmallVector<SDOperand, 4> Ops;
     if (Op.getOpcode() == ISD::SHL_PARTS) {
       Ops.push_back(Tmp2);
       Ops.push_back(Tmp3);
       Ops.push_back(CC);
-      Ops.push_back(InFlag);
-      Hi = DAG.getNode(X86ISD::CMOV, VTs, 2, &Ops[0], Ops.size());
-      InFlag = Hi.getValue(1);
+      Ops.push_back(Cond);
+      if (NewCCModeling)
+        Hi = DAG.getNode(Opc, MVT::i32, &Ops[0], Ops.size());
+      else {
+        Hi = DAG.getNode(Opc, VTs, 2, &Ops[0], Ops.size());
+        Cond = Hi.getValue(1);
+      }
 
       Ops.clear();
       Ops.push_back(Tmp3);
       Ops.push_back(Tmp1);
       Ops.push_back(CC);
-      Ops.push_back(InFlag);
-      Lo = DAG.getNode(X86ISD::CMOV, VTs, 2, &Ops[0], Ops.size());
+      Ops.push_back(Cond);
+      if (NewCCModeling) 
+        Lo = DAG.getNode(Opc, MVT::i32, &Ops[0], Ops.size());
+      else
+        Lo = DAG.getNode(Opc, VTs, 2, &Ops[0], Ops.size());
     } else {
       Ops.push_back(Tmp2);
       Ops.push_back(Tmp3);
       Ops.push_back(CC);
-      Ops.push_back(InFlag);
-      Lo = DAG.getNode(X86ISD::CMOV, VTs, 2, &Ops[0], Ops.size());
-      InFlag = Lo.getValue(1);
+      Ops.push_back(Cond);
+      if (NewCCModeling)
+        Lo = DAG.getNode(Opc, MVT::i32, &Ops[0], Ops.size());
+      else {
+        Lo = DAG.getNode(Opc, VTs, 2, &Ops[0], Ops.size());
+        Cond = Lo.getValue(1);
+      }
 
       Ops.clear();
       Ops.push_back(Tmp3);
       Ops.push_back(Tmp1);
       Ops.push_back(CC);
-      Ops.push_back(InFlag);
-      Hi = DAG.getNode(X86ISD::CMOV, VTs, 2, &Ops[0], Ops.size());
+      Ops.push_back(Cond);
+      if (NewCCModeling)
+        Hi = DAG.getNode(Opc, MVT::i32, &Ops[0], Ops.size());
+      else
+        Hi = DAG.getNode(Opc, VTs, 2, &Ops[0], Ops.size());
     }
 
     VTs = DAG.getNodeValueTypes(MVT::i32, MVT::i32);
@@ -3668,6 +3686,43 @@ SDOperand X86TargetLowering::LowerSETCC(SDOperand Op, SelectionDAG &DAG,
   }
 }
 
+SDOperand X86TargetLowering::LowerSETCC_New(SDOperand Op, SelectionDAG &DAG) {
+  assert(Op.getValueType() == MVT::i8 && "SetCC type must be 8-bit integer");
+  SDOperand Op0 = Op.getOperand(0);
+  SDOperand Op1 = Op.getOperand(1);
+  SDOperand CC = Op.getOperand(2);
+  ISD::CondCode SetCCOpcode = cast<CondCodeSDNode>(CC)->get();
+  bool isFP = MVT::isFloatingPoint(Op.getOperand(1).getValueType());
+  unsigned X86CC;
+
+  SDOperand Cond = DAG.getNode(X86ISD::CMP_NEW, MVT::i32, Op0, Op1);
+  if (translateX86CC(cast<CondCodeSDNode>(CC)->get(), isFP, X86CC,
+                     Op0, Op1, DAG))
+    return DAG.getNode(X86ISD::SETCC_NEW, MVT::i8,
+                       DAG.getConstant(X86CC, MVT::i8), Cond);
+
+  assert(isFP && "Illegal integer SetCC!");
+
+  switch (SetCCOpcode) {
+  default: assert(false && "Illegal floating point SetCC!");
+  case ISD::SETOEQ: {  // !PF & ZF
+    SDOperand Tmp1 = DAG.getNode(X86ISD::SETCC_NEW, MVT::i8,
+                                 DAG.getConstant(X86::COND_NP, MVT::i8), Cond);
+    SDOperand Tmp2 = DAG.getNode(X86ISD::SETCC_NEW, MVT::i8,
+                                 DAG.getConstant(X86::COND_E, MVT::i8), Cond);
+    return DAG.getNode(ISD::AND, MVT::i8, Tmp1, Tmp2);
+  }
+  case ISD::SETUNE: {  // PF | !ZF
+    SDOperand Tmp1 = DAG.getNode(X86ISD::SETCC_NEW, MVT::i8,
+                                 DAG.getConstant(X86::COND_P, MVT::i8), Cond);
+    SDOperand Tmp2 = DAG.getNode(X86ISD::SETCC_NEW, MVT::i8,
+                                 DAG.getConstant(X86::COND_NE, MVT::i8), Cond);
+    return DAG.getNode(ISD::OR, MVT::i8, Tmp1, Tmp2);
+  }
+  }
+}
+
+
 SDOperand X86TargetLowering::LowerSELECT(SDOperand Op, SelectionDAG &DAG) {
   bool addTest = true;
   SDOperand Chain = DAG.getEntryNode();
@@ -3718,6 +3773,56 @@ SDOperand X86TargetLowering::LowerSELECT(SDOperand Op, SelectionDAG &DAG) {
   return DAG.getNode(X86ISD::CMOV, VTs, 2, &Ops[0], Ops.size());
 }
 
+SDOperand X86TargetLowering::LowerSELECT_New(SDOperand Op, SelectionDAG &DAG) {
+  bool addTest = true;
+  SDOperand Cond  = Op.getOperand(0);
+  SDOperand CC;
+
+  if (Cond.getOpcode() == ISD::SETCC)
+    Cond = LowerSETCC_New(Cond, DAG);
+
+  if (Cond.getOpcode() == X86ISD::SETCC_NEW) {
+    CC = Cond.getOperand(0);
+
+    // If condition flag is set by a X86ISD::CMP, then make a copy of it
+    // (since flag operand cannot be shared). Use it as the condition setting
+    // operand in place of the X86ISD::SETCC.
+    // If the X86ISD::SETCC has more than one use, then perhaps it's better
+    // to use a test instead of duplicating the X86ISD::CMP (for register
+    // pressure reason)?
+    SDOperand Cmp = Cond.getOperand(1);
+    unsigned Opc = Cmp.getOpcode();
+    bool IllegalFPCMov = 
+      ! ((X86ScalarSSEf32 && Op.getValueType()==MVT::f32) ||
+         (X86ScalarSSEf64 && Op.getValueType()==MVT::f64)) &&
+      !hasFPCMov(cast<ConstantSDNode>(CC)->getSignExtended());
+    if ((Opc == X86ISD::CMP_NEW ||
+         Opc == X86ISD::COMI_NEW ||
+         Opc == X86ISD::UCOMI_NEW) &&
+        !IllegalFPCMov) {
+      Cond = DAG.getNode(Opc, MVT::i32, Cmp.getOperand(0), Cmp.getOperand(1));
+      addTest = false;
+    }
+  }
+
+  if (addTest) {
+    CC = DAG.getConstant(X86::COND_NE, MVT::i8);
+    Cond = DAG.getNode(X86ISD::CMP_NEW, MVT::i32, Cond,
+                       DAG.getConstant(0, MVT::i8));
+  }
+
+  const MVT::ValueType *VTs = DAG.getNodeValueTypes(Op.getValueType(),
+                                                    MVT::Flag);
+  SmallVector<SDOperand, 4> Ops;
+  // X86ISD::CMOV means set the result (which is operand 1) to the RHS if
+  // condition is true.
+  Ops.push_back(Op.getOperand(2));
+  Ops.push_back(Op.getOperand(1));
+  Ops.push_back(CC);
+  Ops.push_back(Cond);
+  return DAG.getNode(X86ISD::CMOV_NEW, VTs, 2, &Ops[0], Ops.size());
+}
+
 SDOperand X86TargetLowering::LowerBRCOND(SDOperand Op, SelectionDAG &DAG) {
   bool addTest = true;
   SDOperand Chain = Op.getOperand(0);
@@ -3756,6 +3861,43 @@ SDOperand X86TargetLowering::LowerBRCOND(SDOperand Op, SelectionDAG &DAG) {
                      Cond, Op.getOperand(2), CC, Cond.getValue(1));
 }
 
+SDOperand X86TargetLowering::LowerBRCOND_New(SDOperand Op, SelectionDAG &DAG) {
+  bool addTest = true;
+  SDOperand Chain = Op.getOperand(0);
+  SDOperand Cond  = Op.getOperand(1);
+  SDOperand Dest  = Op.getOperand(2);
+  SDOperand CC;
+
+  if (Cond.getOpcode() == ISD::SETCC)
+    Cond = LowerSETCC_New(Cond, DAG);
+
+  if (Cond.getOpcode() == X86ISD::SETCC_NEW) {
+    CC = Cond.getOperand(0);
+
+    // If condition flag is set by a X86ISD::CMP, then make a copy of it
+    // (since flag operand cannot be shared). Use it as the condition setting
+    // operand in place of the X86ISD::SETCC.
+    // If the X86ISD::SETCC has more than one use, then perhaps it's better
+    // to use a test instead of duplicating the X86ISD::CMP (for register
+    // pressure reason)?
+    SDOperand Cmp = Cond.getOperand(1);
+    unsigned Opc = Cmp.getOpcode();
+    if (Opc == X86ISD::CMP_NEW ||
+        Opc == X86ISD::COMI_NEW ||
+        Opc == X86ISD::UCOMI_NEW) {
+      Cond = DAG.getNode(Opc, MVT::i32, Cmp.getOperand(0), Cmp.getOperand(1));
+      addTest = false;
+    }
+  }
+
+  if (addTest) {
+    CC = DAG.getConstant(X86::COND_NE, MVT::i8);
+    Cond= DAG.getNode(X86ISD::CMP_NEW, MVT::i32, Cond, DAG.getConstant(0, MVT::i8));
+  }
+  return DAG.getNode(X86ISD::BRCOND_NEW, Op.getValueType(),
+                     Chain, Op.getOperand(2), CC, Cond);
+}
+
 SDOperand X86TargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
   unsigned CallingConv= cast<ConstantSDNode>(Op.getOperand(1))->getValue();
 
@@ -4355,13 +4497,21 @@ X86TargetLowering::LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG) {
     SDOperand RHS = Op.getOperand(2);
     translateX86CC(CC, true, X86CC, LHS, RHS, DAG);
 
-    const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::Other, MVT::Flag);
-    SDOperand Ops1[] = { DAG.getEntryNode(), LHS, RHS };
-    SDOperand Cond = DAG.getNode(Opc, VTs, 2, Ops1, 3);
-    VTs = DAG.getNodeValueTypes(MVT::i8, MVT::Flag);
-    SDOperand Ops2[] = { DAG.getConstant(X86CC, MVT::i8), Cond };
-    SDOperand SetCC = DAG.getNode(X86ISD::SETCC, VTs, 2, Ops2, 2);
-    return DAG.getNode(ISD::ANY_EXTEND, MVT::i32, SetCC);
+    if (NewCCModeling) {
+      Opc = (Opc == X86ISD::UCOMI) ? X86ISD::UCOMI_NEW : X86ISD::COMI_NEW;
+      SDOperand Cond = DAG.getNode(Opc, MVT::i32, LHS, RHS);
+      SDOperand SetCC = DAG.getNode(X86ISD::SETCC_NEW, MVT::i8,
+                                    DAG.getConstant(X86CC, MVT::i8), Cond);
+      return DAG.getNode(ISD::ANY_EXTEND, MVT::i32, SetCC);
+    } else {
+      const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::Other, MVT::Flag);
+      SDOperand Ops1[] = { DAG.getEntryNode(), LHS, RHS };
+      SDOperand Cond = DAG.getNode(Opc, VTs, 2, Ops1, 3);
+      VTs = DAG.getNodeValueTypes(MVT::i8, MVT::Flag);
+      SDOperand Ops2[] = { DAG.getConstant(X86CC, MVT::i8), Cond };
+      SDOperand SetCC = DAG.getNode(X86ISD::SETCC, VTs, 2, Ops2, 2);
+      return DAG.getNode(ISD::ANY_EXTEND, MVT::i32, SetCC);
+    }
   }
   }
 }
@@ -4529,9 +4679,15 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   case ISD::FABS:               return LowerFABS(Op, DAG);
   case ISD::FNEG:               return LowerFNEG(Op, DAG);
   case ISD::FCOPYSIGN:          return LowerFCOPYSIGN(Op, DAG);
-  case ISD::SETCC:              return LowerSETCC(Op, DAG, DAG.getEntryNode());
-  case ISD::SELECT:             return LowerSELECT(Op, DAG);
-  case ISD::BRCOND:             return LowerBRCOND(Op, DAG);
+  case ISD::SETCC:              return NewCCModeling
+                                  ? LowerSETCC_New(Op, DAG)
+                                  : LowerSETCC(Op, DAG, DAG.getEntryNode());
+  case ISD::SELECT:             return NewCCModeling
+                                  ? LowerSELECT_New(Op, DAG)
+                                  : LowerSELECT(Op, DAG);
+  case ISD::BRCOND:             return NewCCModeling
+                                  ? LowerBRCOND_New(Op, DAG)
+                                  : LowerBRCOND(Op, DAG);
   case ISD::JumpTable:          return LowerJumpTable(Op, DAG);
   case ISD::CALL:               return LowerCALL(Op, DAG);
   case ISD::RET:                return LowerRET(Op, DAG);
@@ -4575,11 +4731,17 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
   case X86ISD::TAILCALL:           return "X86ISD::TAILCALL";
   case X86ISD::RDTSC_DAG:          return "X86ISD::RDTSC_DAG";
   case X86ISD::CMP:                return "X86ISD::CMP";
+  case X86ISD::CMP_NEW:            return "X86ISD::CMP_NEW";
   case X86ISD::COMI:               return "X86ISD::COMI";
+  case X86ISD::COMI_NEW:           return "X86ISD::COMI_NEW";
   case X86ISD::UCOMI:              return "X86ISD::UCOMI";
+  case X86ISD::UCOMI_NEW:          return "X86ISD::UCOMI_NEW";
   case X86ISD::SETCC:              return "X86ISD::SETCC";
+  case X86ISD::SETCC_NEW:          return "X86ISD::SETCC_NEW";
   case X86ISD::CMOV:               return "X86ISD::CMOV";
+  case X86ISD::CMOV_NEW:           return "X86ISD::CMOV_NEW";
   case X86ISD::BRCOND:             return "X86ISD::BRCOND";
+  case X86ISD::BRCOND_NEW:         return "X86ISD::BRCOND_NEW";
   case X86ISD::RET_FLAG:           return "X86ISD::RET_FLAG";
   case X86ISD::REP_STOS:           return "X86ISD::REP_STOS";
   case X86ISD::REP_MOVS:           return "X86ISD::REP_MOVS";
@@ -4696,7 +4858,13 @@ X86TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
   case X86::CMOV_FR64:
   case X86::CMOV_V4F32:
   case X86::CMOV_V2F64:
-  case X86::CMOV_V2I64: {
+  case X86::CMOV_V2I64:
+
+  case X86::NEW_CMOV_FR32:
+  case X86::NEW_CMOV_FR64:
+  case X86::NEW_CMOV_V4F32:
+  case X86::NEW_CMOV_V2F64:
+  case X86::NEW_CMOV_V2I64: {
     // To "insert" a SELECT_CC instruction, we actually have to insert the
     // diamond control-flow pattern.  The incoming instruction knows the
     // destination vreg to set, the condition code register to branch on, the
@@ -4853,6 +5021,7 @@ void X86TargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
   switch (Opc) {
   default: break;
   case X86ISD::SETCC:
+  case X86ISD::SETCC_NEW:
     KnownZero |= (MVT::getIntVTBitMask(Op.getValueType()) ^ 1ULL);
     break;
   }