diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 581b969957e..d76a89df8fe 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1621,6 +1621,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { Node->getOperand(2)); break; } + case TargetLowering::Custom: { + SDOperand Tmp = + TLI.LowerOperation(DAG.getNode(ISD::SETCC, Node->getValueType(0), + Tmp1, Tmp2, Node->getOperand(2)), DAG); + if (Tmp.Val) { + Result = LegalizeOp(Tmp); + break; + } + // FALLTHROUGH if the target thinks it is legal. + } case TargetLowering::Legal: if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1)) Result = DAG.getNode(ISD::SETCC, Node->getValueType(0), Tmp1, Tmp2, diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index ee6e320fc51..5e4fb412f19 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -119,6 +119,9 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) if (X86DAGIsel) { setOperationAction(ISD::SELECT , MVT::i16 , Custom); setOperationAction(ISD::SELECT , MVT::i32 , Custom); + setOperationAction(ISD::SETCC , MVT::i8 , Custom); + setOperationAction(ISD::SETCC , MVT::i16 , Custom); + setOperationAction(ISD::SETCC , MVT::i32 , Custom); } // We don't have line number support yet. @@ -256,7 +259,10 @@ SDOperand X86TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, } break; } - return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); + + return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, + Copy, DAG.getConstant(getBytesToPopOnReturn(), MVT::i16), + Copy.getValue(1)); } //===----------------------------------------------------------------------===// @@ -999,10 +1005,20 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { Tys.push_back(MVT::Other); return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops); } + case ISD::SETCC: { + assert(Op.getValueType() == MVT::i8 && "SetCC type must be 8-bit integer"); + SDOperand CC = Op.getOperand(2); + SDOperand Cond = DAG.getNode(X86ISD::CMP, MVT::Flag, + Op.getOperand(0), Op.getOperand(1)); + return DAG.getNode(X86ISD::SETCC, MVT::i8, CC, Cond); + } case ISD::SELECT: { SDOperand Cond = Op.getOperand(0); SDOperand CC; - if (Cond.getOpcode() == ISD::SETCC) { + if (Cond.getOpcode() == X86ISD::SETCC) { + CC = Cond.getOperand(0); + Cond = Cond.getOperand(1); + } else if (Cond.getOpcode() == ISD::SETCC) { CC = Cond.getOperand(2); Cond = DAG.getNode(X86ISD::CMP, MVT::Flag, Cond.getOperand(0), Cond.getOperand(1)); @@ -1014,12 +1030,14 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { Op.getOperand(1), Op.getOperand(2), CC, Cond); } case ISD::BRCOND: { - SDOperand Chain = Op.getOperand(0); SDOperand Cond = Op.getOperand(1); SDOperand Dest = Op.getOperand(2); SDOperand CC; // TODO: handle Cond == OR / AND / XOR - if (Cond.getOpcode() == ISD::SETCC) { + if (Cond.getOpcode() == X86ISD::SETCC) { + CC = Cond.getOperand(0); + Cond = Cond.getOperand(1); + } else if (Cond.getOpcode() == ISD::SETCC) { CC = Cond.getOperand(2); Cond = DAG.getNode(X86ISD::CMP, MVT::Flag, Cond.getOperand(0), Cond.getOperand(1)); @@ -1061,6 +1079,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::RDTSC_DAG: return "X86ISD::RDTSC_DAG"; case X86ISD::CMP: return "X86ISD::CMP"; case X86ISD::TEST: return "X86ISD::TEST"; + case X86ISD::SETCC: return "X86ISD::SETCC"; case X86ISD::CMOV: return "X86ISD::CMOV"; case X86ISD::BRCOND: return "X86ISD::BRCOND"; case X86ISD::RET_FLAG: return "X86ISD::RET_FLAG"; diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index a1c09136dca..c15e009c90a 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -81,13 +81,24 @@ namespace llvm { /// X86 compare and logical compare instructions. CMP, TEST, - /// X86 conditional moves. + /// X86 SetCC. Operand 1 is condition code, and operand 2 is the flag + /// operand produced by a CMP instruction. + SETCC, + + /// 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. CMOV, - /// X86 conditional branches. + /// 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, - // Return with a flag operand. + /// Return with a flag operand. Operand 1 is the number of bytes of stack + /// to pop, operand 2 is the chain and operand 3 is a flag operand. RET_FLAG, }; } diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index fc4e0b99871..9c7fcb0237f 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -28,25 +28,31 @@ def SDTX86BrCond : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>, SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>; -def SDTX86RetFlag : SDTypeProfile<0, 1, [SDTCisVT<0, FlagVT>]>; +def SDTX86SetCC : SDTypeProfile<1, 2, + [SDTCisVT<0, i8>, SDTCisVT<1, OtherVT>, + SDTCisVT<2, FlagVT>]>; + +def SDTX86RetFlag : SDTypeProfile<0, 2, [SDTCisVT<0, i16>, + SDTCisVT<1, FlagVT>]>; def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>; def SDTX86FpSet : SDTypeProfile<0, 1, [SDTCisFP<0>]>; -def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>; -def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>; +def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>; +def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>; -def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>; -def X86Brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>; +def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>; +def X86Brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>; +def X86SetCC : SDNode<"X86ISD::SETCC", SDTX86SetCC, []>; -def X86retflag: SDNode<"X86ISD::RET_FLAG", SDTX86RetFlag, [SDNPHasChain]>; +def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86RetFlag, [SDNPHasChain]>; -def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, [SDNPHasChain]>; +def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, [SDNPHasChain]>; -def X86fpset : SDNode<"X86ISD::FP_SET_RESULT", - SDTX86FpSet, [SDNPHasChain]>; +def X86fpset : SDNode<"X86ISD::FP_SET_RESULT", + SDTX86FpSet, [SDNPHasChain]>; //===----------------------------------------------------------------------===// // X86 Operand Definitions. @@ -283,12 +289,13 @@ let isTerminator = 1 in // // Return instructions. -let isTerminator = 1, isReturn = 1, isBarrier = 1 in - def RET : I<0xC3, RawFrm, (ops), "ret", [(ret)]>; -let isTerminator = 1, isReturn = 1, isBarrier = 1 in +let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 in + def RET : I<0xC3, RawFrm, (ops), "ret", []>; +let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 in def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", []>; -def : Pat<(X86retflag FLAG), (RET)>; +def : Pat<(X86retflag 0, FLAG), (RET)>; +def : Pat<(X86retflag imm:$amt, FLAG), (RETI imm:$amt)>; // All branches are RawFrm, Void, Branch, and Terminators let isBranch = 1, isTerminator = 1 in @@ -1800,42 +1807,87 @@ def TEST32mi : Ii32<0xF7, MRM0m, // flags = [mem32] & imm32 def SAHF : I<0x9E, RawFrm, (ops), "sahf", []>, Imp<[AH],[]>; // flags = AH def LAHF : I<0x9F, RawFrm, (ops), "lahf", []>, Imp<[],[AH]>; // AH = flags -def SETBr : I<0x92, MRM0r, - (ops R8 :$dst), - "setb $dst", []>, TB; // R8 = < unsign -def SETBm : I<0x92, MRM0m, - (ops i8mem:$dst), - "setb $dst", []>, TB; // [mem8] = < unsign -def SETAEr : I<0x93, MRM0r, - (ops R8 :$dst), - "setae $dst", []>, TB; // R8 = >= unsign -def SETAEm : I<0x93, MRM0m, - (ops i8mem:$dst), - "setae $dst", []>, TB; // [mem8] = >= unsign def SETEr : I<0x94, MRM0r, (ops R8 :$dst), - "sete $dst", []>, TB; // R8 = == + "sete $dst", [(set R8:$dst, (X86SetCC SETEQ, STATUS))]>, + TB; // R8 = == def SETEm : I<0x94, MRM0m, (ops i8mem:$dst), - "sete $dst", []>, TB; // [mem8] = == + "sete $dst", [(store (X86SetCC SETEQ, STATUS), addr:$dst)]>, + TB; // [mem8] = == def SETNEr : I<0x95, MRM0r, (ops R8 :$dst), - "setne $dst", []>, TB; // R8 = != + "setne $dst", [(set R8:$dst, (X86SetCC SETNE, STATUS))]>, + TB; // R8 = != def SETNEm : I<0x95, MRM0m, (ops i8mem:$dst), - "setne $dst", []>, TB; // [mem8] = != + "setne $dst", [(store (X86SetCC SETNE, STATUS), addr:$dst)]>, + TB; // [mem8] = != +def SETLr : I<0x9C, MRM0r, + (ops R8 :$dst), + "setl $dst", [(set R8:$dst, (X86SetCC SETLT, STATUS))]>, + TB; // R8 = < signed +def SETLm : I<0x9C, MRM0m, + (ops i8mem:$dst), + "setl $dst", [(store (X86SetCC SETLT, STATUS), addr:$dst)]>, + TB; // [mem8] = < signed +def SETGEr : I<0x9D, MRM0r, + (ops R8 :$dst), + "setge $dst", [(set R8:$dst, (X86SetCC SETGE, STATUS))]>, + TB; // R8 = >= signed +def SETGEm : I<0x9D, MRM0m, + (ops i8mem:$dst), + "setge $dst", [(store (X86SetCC SETGE, STATUS), addr:$dst)]>, + TB; // [mem8] = >= signed +def SETLEr : I<0x9E, MRM0r, + (ops R8 :$dst), + "setle $dst", [(set R8:$dst, (X86SetCC SETLE, STATUS))]>, + TB; // R8 = <= signed +def SETLEm : I<0x9E, MRM0m, + (ops i8mem:$dst), + "setle $dst", [(store (X86SetCC SETLE, STATUS), addr:$dst)]>, + TB; // [mem8] = <= signed +def SETGr : I<0x9F, MRM0r, + (ops R8 :$dst), + "setg $dst", [(set R8:$dst, (X86SetCC SETGT, STATUS))]>, + TB; // R8 = > signed +def SETGm : I<0x9F, MRM0m, + (ops i8mem:$dst), + "setg $dst", [(store (X86SetCC SETGT, STATUS), addr:$dst)]>, + TB; // [mem8] = > signed + +def SETBr : I<0x92, MRM0r, + (ops R8 :$dst), + "setb $dst", [(set R8:$dst, (X86SetCC SETULT, STATUS))]>, + TB; // R8 = < unsign +def SETBm : I<0x92, MRM0m, + (ops i8mem:$dst), + "setb $dst", [(store (X86SetCC SETULT, STATUS), addr:$dst)]>, + TB; // [mem8] = < unsign +def SETAEr : I<0x93, MRM0r, + (ops R8 :$dst), + "setae $dst", [(set R8:$dst, (X86SetCC SETUGE, STATUS))]>, + TB; // R8 = >= unsign +def SETAEm : I<0x93, MRM0m, + (ops i8mem:$dst), + "setae $dst", [(store (X86SetCC SETUGE, STATUS), addr:$dst)]>, + TB; // [mem8] = >= unsign def SETBEr : I<0x96, MRM0r, (ops R8 :$dst), - "setbe $dst", []>, TB; // R8 = <= unsign + "setbe $dst", [(set R8:$dst, (X86SetCC SETULE, STATUS))]>, + TB; // R8 = <= unsign def SETBEm : I<0x96, MRM0m, (ops i8mem:$dst), - "setbe $dst", []>, TB; // [mem8] = <= unsign + "setbe $dst", [(store (X86SetCC SETULE, STATUS), addr:$dst)]>, + TB; // [mem8] = <= unsign def SETAr : I<0x97, MRM0r, (ops R8 :$dst), - "seta $dst", []>, TB; // R8 = > signed + "seta $dst", [(set R8:$dst, (X86SetCC SETUGT, STATUS))]>, + TB; // R8 = > signed def SETAm : I<0x97, MRM0m, (ops i8mem:$dst), - "seta $dst", []>, TB; // [mem8] = > signed + "seta $dst", [(store (X86SetCC SETUGT, STATUS), addr:$dst)]>, + TB; // [mem8] = > signed def SETSr : I<0x98, MRM0r, (ops R8 :$dst), "sets $dst", []>, TB; // R8 = @@ -1860,30 +1912,6 @@ def SETNPr : I<0x9B, MRM0r, def SETNPm : I<0x9B, MRM0m, (ops i8mem:$dst), "setnp $dst", []>, TB; // [mem8] = not parity -def SETLr : I<0x9C, MRM0r, - (ops R8 :$dst), - "setl $dst", []>, TB; // R8 = < signed -def SETLm : I<0x9C, MRM0m, - (ops i8mem:$dst), - "setl $dst", []>, TB; // [mem8] = < signed -def SETGEr : I<0x9D, MRM0r, - (ops R8 :$dst), - "setge $dst", []>, TB; // R8 = >= signed -def SETGEm : I<0x9D, MRM0m, - (ops i8mem:$dst), - "setge $dst", []>, TB; // [mem8] = >= signed -def SETLEr : I<0x9E, MRM0r, - (ops R8 :$dst), - "setle $dst", []>, TB; // R8 = <= signed -def SETLEm : I<0x9E, MRM0m, - (ops i8mem:$dst), - "setle $dst", []>, TB; // [mem8] = <= signed -def SETGr : I<0x9F, MRM0r, - (ops R8 :$dst), - "setg $dst", []>, TB; // R8 = < signed -def SETGm : I<0x9F, MRM0m, - (ops i8mem:$dst), - "setg $dst", []>, TB; // [mem8] = < signed // Integer comparisons def CMP8rr : I<0x38, MRMDestReg,