diff options
author | Evan Cheng <evan.cheng@apple.com> | 2007-09-25 01:57:46 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2007-09-25 01:57:46 +0000 |
commit | 0488db9b99fcfca407e859ef5cccf40dea23de16 (patch) | |
tree | 19d2a6124364f9e5bbc91ed3f9c26d44419ccb1c | |
parent | a6fb1b6743ee1411accf2d6e636f73f2ee0a7f5b (diff) |
Added support for new condition code modeling scheme (i.e. physical register dependency). These are a bunch of instructions that are duplicated so the x86 backend can support both the old and new schemes at the same time. They will be deleted after
all the kinks are worked out.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42285 91177308-0d34-0410-b5e6-96231b3b80d8
-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 |