diff options
-rw-r--r-- | lib/Target/X86/X86FloatingPoint.cpp | 27 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 215 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelLowering.h | 7 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrFPStack.td | 25 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.cpp | 73 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.td | 726 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrSSE.td | 99 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrX86-64.td | 200 | ||||
-rw-r--r-- | lib/Target/X86/X86RegisterInfo.cpp | 82 |
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))]>, + |