aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/X86/X86FloatingPoint.cpp27
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp215
-rw-r--r--lib/Target/X86/X86ISelLowering.h7
-rw-r--r--lib/Target/X86/X86InstrFPStack.td25
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp73
-rw-r--r--lib/Target/X86/X86InstrInfo.td726
-rw-r--r--lib/Target/X86/X86InstrSSE.td99
-rw-r--r--lib/Target/X86/X86InstrX86-64.td200
-rw-r--r--lib/Target/X86/X86RegisterInfo.cpp82
9 files changed, 1409 insertions, 45 deletions
diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp
index 90813b57ef..ea9a8f7c48 100644
--- a/lib/Target/X86/X86FloatingPoint.cpp
+++ b/lib/Target/X86/X86FloatingPoint.cpp
@@ -437,6 +437,33 @@ static const TableEntry OpcodeTable[] = {
{ X86::MUL_FpI32m32 , X86::MUL_FI32m },
{ X86::MUL_FpI32m64 , X86::MUL_FI32m },
{ X86::MUL_FpI32m80 , X86::MUL_FI32m },
+
+ // TEMPORARY
+ { X86::NEW_CMOVBE_Fp32 , X86::CMOVBE_F },
+ { X86::NEW_CMOVBE_Fp64 , X86::CMOVBE_F },
+ { X86::NEW_CMOVBE_Fp80 , X86::CMOVBE_F },
+ { X86::NEW_CMOVB_Fp32 , X86::CMOVB_F },
+ { X86::NEW_CMOVB_Fp64 , X86::CMOVB_F },
+ { X86::NEW_CMOVB_Fp80 , X86::CMOVB_F },
+ { X86::NEW_CMOVE_Fp32 , X86::CMOVE_F },
+ { X86::NEW_CMOVE_Fp64 , X86::CMOVE_F },
+ { X86::NEW_CMOVE_Fp80 , X86::CMOVE_F },
+ { X86::NEW_CMOVNBE_Fp32 , X86::CMOVNBE_F },
+ { X86::NEW_CMOVNBE_Fp64 , X86::CMOVNBE_F },
+ { X86::NEW_CMOVNBE_Fp80 , X86::CMOVNBE_F },
+ { X86::NEW_CMOVNB_Fp32 , X86::CMOVNB_F },
+ { X86::NEW_CMOVNB_Fp64 , X86::CMOVNB_F },
+ { X86::NEW_CMOVNB_Fp80 , X86::CMOVNB_F },
+ { X86::NEW_CMOVNE_Fp32 , X86::CMOVNE_F },
+ { X86::NEW_CMOVNE_Fp64 , X86::CMOVNE_F },
+ { X86::NEW_CMOVNE_Fp80 , X86::CMOVNE_F },
+ { X86::NEW_CMOVNP_Fp32 , X86::CMOVNP_F },
+ { X86::NEW_CMOVNP_Fp64 , X86::CMOVNP_F },
+ { X86::NEW_CMOVNP_Fp80 , X86::CMOVNP_F },
+ { X86::NEW_CMOVP_Fp32 , X86::CMOVP_F },
+ { X86::NEW_CMOVP_Fp64 , X86::CMOVP_F },
+ { X86::NEW_CMOVP_Fp80 , X86::CMOVP_F },
+
{ X86::SIN_Fp32 , X86::SIN_F },
{ X86::SIN_Fp64 , X86::SIN_F },
{ X86::SIN_Fp80 , X86::SIN_F },
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 5343361a9e..ab704a74d7 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -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;
}
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index 658b34449d..04279e835c 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -117,22 +117,26 @@ namespace llvm {
/// X86 compare and logical compare instructions.
CMP, COMI, UCOMI,
+ CMP_NEW, COMI_NEW, UCOMI_NEW,
/// X86 SetCC. Operand 1 is condition code, and operand 2 is the flag
/// operand produced by a CMP instruction.
SETCC,
+ SETCC_NEW,
/// X86 conditional moves. Operand 1 and operand 2 are the two values
/// to select from (operand 1 is a R/W operand). Operand 3 is the
/// condition code, and operand 4 is the flag operand produced by a CMP
/// or TEST instruction. It also writes a flag result.
CMOV,
+ CMOV_NEW,
/// X86 conditional branches. Operand 1 is the chain operand, operand 2
/// is the block to branch if condition is true, operand 3 is the
/// condition code, and operand 4 is the flag operand produced by a CMP
/// or TEST instruction.
BRCOND,
+ BRCOND_NEW,
/// Return with a flag operand. Operand 1 is the chain operand, operand
/// 2 is the number of bytes of stack to pop.
@@ -422,8 +426,11 @@ namespace llvm {
SDOperand LowerFNEG(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerFCOPYSIGN(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerSETCC(SDOperand Op, SelectionDAG &DAG, SDOperand Chain);
+ SDOperand LowerSETCC_New(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerSELECT(SDOperand Op, SelectionDAG &DAG);
+ SDOperand LowerSELECT_New(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerBRCOND(SDOperand Op, SelectionDAG &DAG);
+ SDOperand LowerBRCOND_New(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerMEMSET(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerMEMCPY(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG);
diff --git a/lib/Target/X86/X86InstrFPStack.td b/lib/Target/X86/X86InstrFPStack.td
index 1e8cf6a5b4..737c74539c 100644
--- a/lib/Target/X86/X86InstrFPStack.td
+++ b/lib/Target/X86/X86InstrFPStack.td
@@ -320,6 +320,31 @@ defm CMOVNE : FPCMov<X86_COND_NE>;
defm CMOVNP : FPCMov<X86_COND_NP>;
}
+multiclass NEW_FPCMov<PatLeaf cc> {
+ def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2),
+ CondMovFP,
+ [(set RFP32:$dst, (X86cmov_new RFP32:$src1, RFP32:$src2,
+ cc, EFLAGS))]>;
+ def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2),
+ CondMovFP,
+ [(set RFP64:$dst, (X86cmov_new RFP64:$src1, RFP64:$src2,
+ cc, EFLAGS))]>;
+ def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2),
+ CondMovFP,
+ [(set RFP80:$dst, (X86cmov_new RFP80:$src1, RFP80:$src2,
+ cc, EFLAGS))]>;
+}
+let Uses = [EFLAGS], isTwoAddress = 1 in {
+defm NEW_CMOVB : NEW_FPCMov<X86_COND_B>;
+defm NEW_CMOVBE : NEW_FPCMov<X86_COND_BE>;
+defm NEW_CMOVE : NEW_FPCMov<X86_COND_E>;
+defm NEW_CMOVP : NEW_FPCMov<X86_COND_P>;
+defm NEW_CMOVNB : NEW_FPCMov<X86_COND_AE>;
+defm NEW_CMOVNBE: NEW_FPCMov<X86_COND_A>;
+defm NEW_CMOVNE : NEW_FPCMov<X86_COND_NE>;
+defm NEW_CMOVNP : NEW_FPCMov<X86_COND_NP>;
+}
+
// These are not factored because there's no clean way to pass DA/DB.
def CMOVB_F : FPI<0xC0, AddRegFrm, (outs RST:$op), (ins),
"fcmovb\t{$op, %st(0)|%ST(0), $op}">, DA;
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 0cf65b04e6..e510369399 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -21,6 +21,7 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/Target/TargetOptions.h"
using namespace llvm;
X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
@@ -385,28 +386,68 @@ static X86::CondCode GetCondFromBranchOpc(unsigned BrOpc) {
case X86::JNP: return X86::COND_NP;
case X86::JO: return X86::COND_O;
case X86::JNO: return X86::COND_NO;
+ // TEMPORARY
+ case X86::NEW_JE: return X86::COND_E;
+ case X86::NEW_JNE: return X86::COND_NE;
+ case X86::NEW_JL: return X86::COND_L;
+ case X86::NEW_JLE: return X86::COND_LE;
+ case X86::NEW_JG: return X86::COND_G;
+ case X86::NEW_JGE: return X86::COND_GE;
+ case X86::NEW_JB: return X86::COND_B;
+ case X86::NEW_JBE: return X86::COND_BE;
+ case X86::NEW_JA: return X86::COND_A;
+ case X86::NEW_JAE: return X86::COND_AE;
+ case X86::NEW_JS: return X86::COND_S;
+ case X86::NEW_JNS: return X86::COND_NS;
+ case X86::NEW_JP: return X86::COND_P;
+ case X86::NEW_JNP: return X86::COND_NP;
+ case X86::NEW_JO: return X86::COND_O;
+ case X86::NEW_JNO: return X86::COND_NO;
+
}
}
unsigned X86::GetCondBranchFromCond(X86::CondCode CC) {
+ if (!NewCCModeling) {
+ switch (CC) {
+ default: assert(0 && "Illegal condition code!");
+ case X86::COND_E: return X86::JE;
+ case X86::COND_NE: return X86::JNE;
+ case X86::COND_L: return X86::JL;
+ case X86::COND_LE: return X86::JLE;
+ case X86::COND_G: return X86::JG;
+ case X86::COND_GE: return X86::JGE;
+ case X86::COND_B: return X86::JB;
+ case X86::COND_BE: return X86::JBE;
+ case X86::COND_A: return X86::JA;
+ case X86::COND_AE: return X86::JAE;
+ case X86::COND_S: return X86::JS;
+ case X86::COND_NS: return X86::JNS;
+ case X86::COND_P: return X86::JP;
+ case X86::COND_NP: return X86::JNP;
+ case X86::COND_O: return X86::JO;
+ case X86::COND_NO: return X86::JNO;
+ }
+ }
+
switch (CC) {
default: assert(0 && "Illegal condition code!");
- case X86::COND_E: return X86::JE;
- case X86::COND_NE: return X86::JNE;
- case X86::COND_L: return X86::JL;
- case X86::COND_LE: return X86::JLE;
- case X86::COND_G: return X86::JG;
- case X86::COND_GE: return X86::JGE;
- case X86::COND_B: return X86::JB;
- case X86::COND_BE: return X86::JBE;
- case X86::COND_A: return X86::JA;
- case X86::COND_AE: return X86::JAE;
- case X86::COND_S: return X86::JS;
- case X86::COND_NS: return X86::JNS;
- case X86::COND_P: return X86::JP;
- case X86::COND_NP: return X86::JNP;
- case X86::COND_O: return X86::JO;
- case X86::COND_NO: return X86::JNO;
+ case X86::COND_E: return X86::NEW_JE;
+ case X86::COND_NE: return X86::NEW_JNE;
+ case X86::COND_L: return X86::NEW_JL;
+ case X86::COND_LE: return X86::NEW_JLE;
+ case X86::COND_G: return X86::NEW_JG;
+ case X86::COND_GE: return X86::NEW_JGE;
+ case X86::COND_B: return X86::NEW_JB;
+ case X86::COND_BE: return X86::NEW_JBE;
+ case X86::COND_A: return X86::NEW_JA;
+ case X86::COND_AE: return X86::NEW_JAE;
+ case X86::COND_S: return X86::NEW_JS;
+ case X86::COND_NS: return X86::NEW_JNS;
+ case X86::COND_P: return X86::NEW_JP;
+ case X86::COND_NP: return X86::NEW_JNP;
+ case X86::COND_O: return X86::NEW_JO;
+ case X86::COND_NO: return X86::NEW_JNO;
}
}
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 17bb8e65fd..bdce50a76d 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -26,12 +26,21 @@ def SDTX86CmpTest : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
def SDTX86Cmov : SDTypeProfile<1, 3,
[SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
SDTCisVT<3, i8>]>;
+def SDTX86Cmov_NEW : SDTypeProfile<1, 4,
+ [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
+ SDTCisVT<3, i8>, SDTCisVT<4, i32>]>;
def SDTX86BrCond : SDTypeProfile<0, 2,
[SDTCisVT<0, OtherVT>, SDTCisVT<1, i8>]>;
+def SDTX86BrCond_NEW : SDTypeProfile<0, 3,
+ [SDTCisVT<0, OtherVT>,
+ SDTCisVT<1, i8>, SDTCisVT<2, i32>]>;
def SDTX86SetCC : SDTypeProfile<1, 1,
[SDTCisVT<0, i8>, SDTCisVT<1, i8>]>;
+def SDTX86SetCC_NEW : SDTypeProfile<1, 2,
+ [SDTCisVT<0, i8>,
+ SDTCisVT<1, i8>, SDTCisVT<2, i32>]>;
def SDTX86Ret : SDTypeProfile<0, 1, [SDTCisVT<0, i16>]>;
@@ -58,13 +67,18 @@ def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>;
def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest,
[SDNPHasChain, SDNPOutFlag]>;
+def X86cmp_new : SDNode<"X86ISD::CMP_NEW" , SDTX86CmpTest>;
-def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov,
+def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov,
[SDNPInFlag, SDNPOutFlag]>;
+def X86cmov_new: SDNode<"X86ISD::CMOV_NEW", SDTX86Cmov_NEW>;
def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond,
[SDNPHasChain, SDNPInFlag]>;
+def X86brcond_new : SDNode<"X86ISD::BRCOND_NEW", SDTX86BrCond_NEW,
+ [SDNPHasChain]>;
def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC,
[SDNPInFlag, SDNPOutFlag]>;
+def X86setcc_new : SDNode<"X86ISD::SETCC_NEW", SDTX86SetCC_NEW>;
def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret,
[SDNPHasChain, SDNPOptInFlag]>;
@@ -301,6 +315,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
}
// Conditional branches
+let Uses = [EFLAGS] in {
def JE : IBr<0x84, (ins brtarget:$dst), "je\t$dst",
[(X86brcond bb:$dst, X86_COND_E)]>, TB;
def JNE : IBr<0x85, (ins brtarget:$dst), "jne\t$dst",
@@ -335,6 +350,44 @@ def JO : IBr<0x80, (ins brtarget:$dst), "jo\t$dst",
[(X86brcond bb:$dst, X86_COND_O)]>, TB;
def JNO : IBr<0x81, (ins brtarget:$dst), "jno\t$dst",
[(X86brcond bb:$dst, X86_COND_NO)]>, TB;
+} // Uses = [EFLAGS]
+
+let Uses = [EFLAGS] in {
+def NEW_JE : IBr<0x84, (ins brtarget:$dst), "je\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_E, EFLAGS)]>, TB;
+def NEW_JNE : IBr<0x85, (ins brtarget:$dst), "jne\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_NE, EFLAGS)]>, TB;
+def NEW_JL : IBr<0x8C, (ins brtarget:$dst), "jl\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_L, EFLAGS)]>, TB;
+def NEW_JLE : IBr<0x8E, (ins brtarget:$dst), "jle\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_LE, EFLAGS)]>, TB;
+def NEW_JG : IBr<0x8F, (ins brtarget:$dst), "jg\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_G, EFLAGS)]>, TB;
+def NEW_JGE : IBr<0x8D, (ins brtarget:$dst), "jge\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_GE, EFLAGS)]>, TB;
+
+def NEW_JB : IBr<0x82, (ins brtarget:$dst), "jb\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_B, EFLAGS)]>, TB;
+def NEW_JBE : IBr<0x86, (ins brtarget:$dst), "jbe\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_BE, EFLAGS)]>, TB;
+def NEW_JA : IBr<0x87, (ins brtarget:$dst), "ja\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_A, EFLAGS)]>, TB;
+def NEW_JAE : IBr<0x83, (ins brtarget:$dst), "jae\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_AE, EFLAGS)]>, TB;
+
+def NEW_JS : IBr<0x88, (ins brtarget:$dst), "js\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_S, EFLAGS)]>, TB;
+def NEW_JNS : IBr<0x89, (ins brtarget:$dst), "jns\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_NS, EFLAGS)]>, TB;
+def NEW_JP : IBr<0x8A, (ins brtarget:$dst), "jp\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_P, EFLAGS)]>, TB;
+def NEW_JNP : IBr<0x8B, (ins brtarget:$dst), "jnp\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_NP, EFLAGS)]>, TB;
+def NEW_JO : IBr<0x80, (ins brtarget:$dst), "jo\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_O, EFLAGS)]>, TB;
+def NEW_JNO : IBr<0x81, (ins brtarget:$dst), "jno\t$dst",
+ [(X86brcond_new bb:$dst, X86_COND_NO, EFLAGS)]>, TB;
+} // Uses = [EFLAGS]
//===----------------------------------------------------------------------===//
// Call Instructions...
@@ -343,7 +396,7 @@ let isCall = 1 in
// All calls clobber the non-callee saved registers...
let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
- XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7] in {
+ XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, EFLAGS] in {
def CALLpcrel32 : I<0xE8, RawFrm, (outs), (ins i32imm:$dst, variable_ops),
"call\t${dst:call}", []>;
def CALL32r : I<0xFF, MRM2r, (outs), (ins GR32:$dst, variable_ops),
@@ -640,6 +693,7 @@ def IDIV32m: I<0xF7, MRM7m, (outs), (ins i32mem:$src), // EDX:EAX/[mem32] =
let isTwoAddress = 1 in {
// Conditional moves
+let Uses = [EFLAGS] in {
def CMOVB16rr : I<0x42, MRMSrcReg, // if <u, GR16 = GR16
(outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
"cmovb\t{$src2, $dst|$dst, $src2}",
@@ -991,6 +1045,358 @@ def CMOVNP32rm : I<0x4B, MRMSrcMem, // if !parity, GR32 = [mem32]
TB;
+def NEW_CMOVB16rr : I<0x42, MRMSrcReg, // if <u, GR16 = GR16
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "cmovb\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, GR16:$src2,
+ X86_COND_B, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVB16rm : I<0x42, MRMSrcMem, // if <u, GR16 = [mem16]
+ (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2),
+ "cmovb\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, (loadi16 addr:$src2),
+ X86_COND_B, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVB32rr : I<0x42, MRMSrcReg, // if <u, GR32 = GR32
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "cmovb\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, GR32:$src2,
+ X86_COND_B, EFLAGS))]>,
+ TB;
+def NEW_CMOVB32rm : I<0x42, MRMSrcMem, // if <u, GR32 = [mem32]
+ (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2),
+ "cmovb\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, (loadi32 addr:$src2),
+ X86_COND_B, EFLAGS))]>,
+ TB;
+
+def NEW_CMOVAE16rr: I<0x43, MRMSrcReg, // if >=u, GR16 = GR16
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "cmovae\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, GR16:$src2,
+ X86_COND_AE, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVAE16rm: I<0x43, MRMSrcMem, // if >=u, GR16 = [mem16]
+ (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2),
+ "cmovae\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, (loadi16 addr:$src2),
+ X86_COND_AE, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVAE32rr: I<0x43, MRMSrcReg, // if >=u, GR32 = GR32
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "cmovae\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, GR32:$src2,
+ X86_COND_AE, EFLAGS))]>,
+ TB;
+def NEW_CMOVAE32rm: I<0x43, MRMSrcMem, // if >=u, GR32 = [mem32]
+ (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2),
+ "cmovae\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, (loadi32 addr:$src2),
+ X86_COND_AE, EFLAGS))]>,
+ TB;
+
+def NEW_CMOVE16rr : I<0x44, MRMSrcReg, // if ==, GR16 = GR16
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "cmove\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, GR16:$src2,
+ X86_COND_E, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVE16rm : I<0x44, MRMSrcMem, // if ==, GR16 = [mem16]
+ (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2),
+ "cmove\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, (loadi16 addr:$src2),
+ X86_COND_E, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVE32rr : I<0x44, MRMSrcReg, // if ==, GR32 = GR32
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "cmove\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, GR32:$src2,
+ X86_COND_E, EFLAGS))]>,
+ TB;
+def NEW_CMOVE32rm : I<0x44, MRMSrcMem, // if ==, GR32 = [mem32]
+ (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2),
+ "cmove\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, (loadi32 addr:$src2),
+ X86_COND_E, EFLAGS))]>,
+ TB;
+
+def NEW_CMOVNE16rr: I<0x45, MRMSrcReg, // if !=, GR16 = GR16
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "cmovne\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, GR16:$src2,
+ X86_COND_NE, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVNE16rm: I<0x45, MRMSrcMem, // if !=, GR16 = [mem16]
+ (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2),
+ "cmovne\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, (loadi16 addr:$src2),
+ X86_COND_NE, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVNE32rr: I<0x45, MRMSrcReg, // if !=, GR32 = GR32
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "cmovne\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, GR32:$src2,
+ X86_COND_NE, EFLAGS))]>,
+ TB;
+def NEW_CMOVNE32rm: I<0x45, MRMSrcMem, // if !=, GR32 = [mem32]
+ (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2),
+ "cmovne\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, (loadi32 addr:$src2),
+ X86_COND_NE, EFLAGS))]>,
+ TB;
+
+def NEW_CMOVBE16rr: I<0x46, MRMSrcReg, // if <=u, GR16 = GR16
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "cmovbe\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, GR16:$src2,
+ X86_COND_BE, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVBE16rm: I<0x46, MRMSrcMem, // if <=u, GR16 = [mem16]
+ (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2),
+ "cmovbe\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, (loadi16 addr:$src2),
+ X86_COND_BE, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVBE32rr: I<0x46, MRMSrcReg, // if <=u, GR32 = GR32
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "cmovbe\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, GR32:$src2,
+ X86_COND_BE, EFLAGS))]>,
+ TB;
+def NEW_CMOVBE32rm: I<0x46, MRMSrcMem, // if <=u, GR32 = [mem32]
+ (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2),
+ "cmovbe\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, (loadi32 addr:$src2),
+ X86_COND_BE, EFLAGS))]>,
+ TB;
+
+def NEW_CMOVA16rr : I<0x47, MRMSrcReg, // if >u, GR16 = GR16
+ (outs GR16:$dst), (ins GR16:$src1, GR16:$src2),
+ "cmova\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, GR16:$src2,
+ X86_COND_A, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVA16rm : I<0x47, MRMSrcMem, // if >u, GR16 = [mem16]
+ (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2),
+ "cmova\t{$src2, $dst|$dst, $src2}",
+ [(set GR16:$dst, (X86cmov_new GR16:$src1, (loadi16 addr:$src2),
+ X86_COND_A, EFLAGS))]>,
+ TB, OpSize;
+def NEW_CMOVA32rr : I<0x47, MRMSrcReg, // if >u, GR32 = GR32
+ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+ "cmova\t{$src2, $dst|$dst, $src2}",
+ [(set GR32:$dst, (X86cmov_new GR32:$src1, GR32:$src2,
+ X86_COND_A, EFLAGS))]>,
+