From d90eb7fb2435e2abedb4694edc44fa45642edbe9 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 5 Jan 2006 00:27:02 +0000 Subject: [PATCH] DAG based isel call support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25103 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelDAGToDAG.cpp | 27 +++++++ lib/Target/X86/X86ISelLowering.cpp | 141 +++++++++++++++++++++++++++++-------- lib/Target/X86/X86ISelLowering.h | 11 +++ lib/Target/X86/X86InstrInfo.td | 59 +++++++++++++--- 4 files changed, 197 insertions(+), 41 deletions(-) diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 1a926d076e9..c5aa6c8acb1 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -410,6 +410,33 @@ SDOperand X86DAGToDAGISel::Select(SDOperand N) { return CodeGenMap[N] = CurDAG->getTargetNode(Opc, VT, Result); break; } + + case ISD::ConstantFP: { + Opc = 0; + if (X86ScalarSSE) { + assert(cast(N)->isExactlyValue(+0.0) && + "SSE only supports +0.0"); + Opc = (NVT == MVT::f32) ? X86::FLD0SS : X86::FLD0SD; + } + + if (cast(N)->isExactlyValue(+0.0) || + cast(N)->isExactlyValue(-0.0)) + Opc = X86::FpLD0; + else if (cast(N)->isExactlyValue(+1.0) || + cast(N)->isExactlyValue(-1.0)) + Opc = X86::FpLD1; + + assert(Opc != 0 && "Unexpected constant!"); + + SDOperand Result = CurDAG->getTargetNode(Opc, NVT); + + if (cast(N)->getValue() < 0.0 || + cast(N)->isExactlyValue(-0.0)) + Result = CurDAG->getTargetNode(X86::FpCHS, NVT, Result); + + CodeGenMap[N] = Result; + return Result; + } } return SelectCode(N); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index a5b261c8374..1811f62b0b0 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -457,38 +457,117 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy, RetVals.push_back(MVT::i32); break; } - std::vector Ops; - Ops.push_back(Chain); - Ops.push_back(Callee); - Ops.push_back(DAG.getConstant(NumBytes, getPointerTy())); - Ops.push_back(DAG.getConstant(0, getPointerTy())); - SDOperand TheCall = DAG.getNode(isTailCall ? X86ISD::TAILCALL : X86ISD::CALL, - RetVals, Ops); - Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, TheCall); - SDOperand ResultVal; - switch (RetTyVT) { - case MVT::isVoid: break; - default: - ResultVal = TheCall.getValue(1); - break; - case MVT::i1: - case MVT::i8: - case MVT::i16: - ResultVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, TheCall.getValue(1)); - break; - case MVT::f32: - // FIXME: we would really like to remember that this FP_ROUND operation is - // okay to eliminate if we allow excess FP precision. - ResultVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, TheCall.getValue(1)); - break; - case MVT::i64: - ResultVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, TheCall.getValue(1), - TheCall.getValue(2)); - break; - } + if (X86DAGIsel) { + std::vector NodeTys; + NodeTys.push_back(MVT::Other); // Returns a chain + NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use. - return std::make_pair(ResultVal, Chain); + std::vector Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + Chain = DAG.getNode(isTailCall ? X86ISD::TAILCALL : X86ISD::CALL, + NodeTys, Ops); + SDOperand InFlag = Chain.getValue(1); + + SDOperand RetVal; + if (RetTyVT != MVT::isVoid) { + switch (RetTyVT) { + default: assert(0 && "Unknown value type to return!"); + case MVT::i1: + case MVT::i8: + RetVal = DAG.getCopyFromReg(Chain, X86::AL, MVT::i8, InFlag); + Chain = RetVal.getValue(1); + break; + case MVT::i16: + RetVal = DAG.getCopyFromReg(Chain, X86::AX, MVT::i16, InFlag); + Chain = RetVal.getValue(1); + break; + case MVT::i32: + RetVal = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag); + Chain = RetVal.getValue(1); + break; + case MVT::i64: { + SDOperand Lo = DAG.getCopyFromReg(Chain, X86::EAX, MVT::i32, InFlag); + SDOperand Hi = DAG.getCopyFromReg(Lo.getValue(1), X86::EDX, MVT::i32, + Lo.getValue(2)); + RetVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi); + Chain = Hi.getValue(1); + break; + } + case MVT::f32: + case MVT::f64: { + std::vector Tys; + Tys.push_back(MVT::f64); + Tys.push_back(MVT::Other); + std::vector Ops; + Ops.push_back(Chain); + Ops.push_back(InFlag); + RetVal = DAG.getNode(X86ISD::FP_GET_RESULT, Tys, Ops); + Chain = RetVal.getValue(1); + if (X86ScalarSSE) { + unsigned Size = MVT::getSizeInBits(MVT::f64)/8; + MachineFunction &MF = DAG.getMachineFunction(); + int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size); + SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); + Tys.clear(); + Tys.push_back(MVT::Other); + Ops.clear(); + Ops.push_back(Chain); + Ops.push_back(RetVal); + Ops.push_back(StackSlot); + Ops.push_back(DAG.getValueType(RetTyVT)); + Chain = DAG.getNode(X86ISD::FST, Tys, Ops); + RetVal = DAG.getLoad(RetTyVT, Chain, StackSlot, + DAG.getSrcValue(NULL)); + Chain = RetVal.getValue(1); + } else if (RetTyVT == MVT::f32) + RetVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, RetVal); + break; + } + } + } + + Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain, + DAG.getConstant(NumBytes, getPointerTy()), + DAG.getConstant(0, getPointerTy())); + return std::make_pair(RetVal, Chain); + } else { + std::vector Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + Ops.push_back(DAG.getConstant(NumBytes, getPointerTy())); + Ops.push_back(DAG.getConstant(0, getPointerTy())); + + SDOperand TheCall = DAG.getNode(isTailCall ? X86ISD::TAILCALL : X86ISD::CALL, + RetVals, Ops); + + SDOperand ResultVal; + switch (RetTyVT) { + case MVT::isVoid: break; + default: + ResultVal = TheCall.getValue(1); + break; + case MVT::i1: + case MVT::i8: + case MVT::i16: + ResultVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, TheCall.getValue(1)); + break; + case MVT::f32: + // FIXME: we would really like to remember that this FP_ROUND operation is + // okay to eliminate if we allow excess FP precision. + ResultVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, TheCall.getValue(1)); + break; + case MVT::i64: + ResultVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, TheCall.getValue(1), + TheCall.getValue(2)); + break; + } + + Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, TheCall); + return std::make_pair(ResultVal, Chain); + } } SDOperand @@ -1085,6 +1164,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::FP_TO_INT32_IN_MEM: return "X86ISD::FP_TO_INT32_IN_MEM"; case X86ISD::FP_TO_INT64_IN_MEM: return "X86ISD::FP_TO_INT64_IN_MEM"; case X86ISD::FLD: return "X86ISD::FLD"; + case X86ISD::FST: return "X86ISD::FST"; + case X86ISD::FP_GET_RESULT: return "X86ISD::FP_GET_RESULT"; case X86ISD::FP_SET_RESULT: return "X86ISD::FP_SET_RESULT"; case X86ISD::CALL: return "X86ISD::CALL"; case X86ISD::TAILCALL: return "X86ISD::TAILCALL"; diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index fbe5c4cc95e..c8d2dab663e 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -46,6 +46,17 @@ namespace llvm { /// to load to. FLD, + /// FST - This instruction implements a truncating store to FP stack + /// slots. This corresponds to the X86::FST32m / X86::FST64m. It takes a + /// chain operand, value to store, address, and a ValueType to store it + /// as. + FST, + + /// FP_SET_RESULT - This corresponds to FpGETRESULT pseudo instrcuction + /// which copies from ST(0) to the destination. It takes a chain and writes + /// a RFP result and a chain. + FP_GET_RESULT, + /// FP_SET_RESULT - This corresponds to FpSETRESULT pseudo instrcuction /// which copies the source operand to ST(0). It takes a chain and writes /// a chain and a flag. diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index edb7285c0d8..399f641a194 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -36,7 +36,11 @@ def SDTX86RetFlag : SDTypeProfile<0, 1, [SDTCisVT<0, i16>]>; def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>; +def SDTX86Fst : SDTypeProfile<0, 3, [SDTCisFP<0>, + SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>; + +def SDTX86FpGet : SDTypeProfile<1, 0, [SDTCisVT<0, f64>]>; def SDTX86FpSet : SDTypeProfile<0, 1, [SDTCisFP<0>]>; def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>; @@ -49,10 +53,24 @@ def X86SetCC : SDNode<"X86ISD::SETCC", SDTX86SetCC, []>; def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86RetFlag, [SDNPHasChain]>; def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, [SDNPHasChain]>; +def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, [SDNPHasChain]>; +def X86fpget : SDNode<"X86ISD::FP_GET_RESULT", + SDTX86FpGet, [SDNPHasChain]>; def X86fpset : SDNode<"X86ISD::FP_SET_RESULT", SDTX86FpSet, [SDNPHasChain]>; +def SDT_X86CallSeqStart : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>; +def SDT_X86CallSeqEnd : SDTypeProfile<0, 2, [ SDTCisVT<0, i32>, + SDTCisVT<1, i32> ]>; +def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, + [SDNPHasChain]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, + [SDNPHasChain]>; + +def SDT_X86Call : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; +def call : SDNode<"X86ISD::CALL", SDT_X86Call, [SDNPHasChain]>; + //===----------------------------------------------------------------------===// // X86 Operand Definitions. // @@ -275,9 +293,11 @@ class Ii32 o, Format f, dag ops, string asm, list pattern> def PHI : I<0, Pseudo, (ops variable_ops), "PHINODE", []>; // PHI node. def NOOP : I<0x90, RawFrm, (ops), "nop", []>; // nop -def ADJCALLSTACKDOWN : I<0, Pseudo, (ops i32imm:$amt), "#ADJCALLSTACKDOWN", []>; +def ADJCALLSTACKDOWN : I<0, Pseudo, (ops i32imm:$amt), "#ADJCALLSTACKDOWN", + [(callseq_start imm:$amt)]>; def ADJCALLSTACKUP : I<0, Pseudo, (ops i32imm:$amt1, i32imm:$amt2), - "#ADJCALLSTACKUP", []>; + "#ADJCALLSTACKUP", + [(callseq_end imm:$amt1, imm:$amt2)]>; def IMPLICIT_USE : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_USE", []>; def IMPLICIT_DEF : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_DEF", []>; let isTerminator = 1 in @@ -301,9 +321,6 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1, } } -def : Pat<(X86retflag 0), (RET)>; -def : Pat<(X86retflag imm:$amt), (RETI imm:$amt)>; - // All branches are RawFrm, Void, Branch, and Terminators let isBranch = 1, isTerminator = 1, noResults = 1 in class IBr opcode, dag ops, string asm, list pattern> : @@ -342,15 +359,25 @@ def JNP : IBr<0x8B, (ops brtarget:$dst), "jnp $dst", []>, TB; //===----------------------------------------------------------------------===// // Call Instructions... // -let isCall = 1, noResults = 1 in +// FIXME: How about hasInFlag = 1? A fastcall would require an incoming flag +// to stick the CopyToRegs to the call. +let isCall = 1, noResults = 1, hasOutFlag = 1 in // All calls clobber the non-callee saved registers... let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7] in { - def CALLpcrel32 : I<0xE8, RawFrm, (ops calltarget:$dst), "call $dst", []>; - def CALL32r : I<0xFF, MRM2r, (ops R32:$dst), "call {*}$dst", []>; - def CALL32m : I<0xFF, MRM2m, (ops i32mem:$dst), "call {*}$dst", []>; + def CALLpcrel32 : I<0xE8, RawFrm, (ops calltarget:$dst), "call $dst", + []>; + def CALL32r : I<0xFF, MRM2r, (ops R32:$dst), "call {*}$dst", + []>; + def CALL32m : I<0xFF, MRM2m, (ops i32mem:$dst), "call {*}$dst", + []>; } +def : Pat<(call tglobaladdr:$dst), + (CALLpcrel32 tglobaladdr:$dst)>; +def : Pat<(call externalsym:$dst), + (CALLpcrel32 externalsym:$dst)>; + // Tail call stuff. let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, noResults = 1 in def TAILJMPd : IBr<0xE9, (ops calltarget:$dst), "jmp $dst # TAIL CALL", []>; @@ -2309,11 +2336,17 @@ class FpI pattern> } // Random Pseudo Instructions. -def FpGETRESULT : FpI<(ops RFP:$dst), SpecialFP, []>; // FPR = ST(0) +let hasInFlag = 1 in + def FpGETRESULT : FpI<(ops RFP:$dst), SpecialFP, []>; // FPR = ST(0) + +// Do not inline into instruction def. since it isn't predicated on FPStack. +def : Pat<(X86fpget), (FpGETRESULT)>; + let noResults = 1, hasOutFlag = 1 in def FpSETRESULT : FpI<(ops RFP:$src), SpecialFP, []>, Imp<[], [ST0]>; // ST(0) = FPR +// Do not inline into instruction def. since it isn't predicated on FPStack. def : Pat<(X86fpset RFP:$src), (FpSETRESULT RFP:$src)>; def FpMOV : FpI<(ops RFP:$dst, RFP:$src), SpecialFP, []>; // f1 = fmov f2 @@ -2359,7 +2392,7 @@ def FpSUB64m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, [(set RFP:$dst, (fsub RFP:$src1, (loadf64 addr:$src2)))]>; // ST(0) = ST(0) - [mem64] def FpSUBR32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, - [(set RFP:$dst, (fadd (extloadf64f32 addr:$src2), + [(set RFP:$dst, (fsub (extloadf64f32 addr:$src2), RFP:$src1))]>; // ST(0) = [mem32] - ST(0) def FpSUBR64m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, @@ -2503,6 +2536,10 @@ def FpST32m : FpI<(ops f32mem:$op, RFP:$src), OneArgFP, [(truncstore RFP:$src, addr:$op, f32)]>; def FpST64m : FpI<(ops f64mem:$op, RFP:$src), OneArgFP, [(store RFP:$src, addr:$op)]>; + +def : Pat<(X86fst RFP:$src, addr:$op, f32), (FpST32m addr:$op, RFP:$src)>; +def : Pat<(X86fst RFP:$src, addr:$op, f64), (FpST64m addr:$op, RFP:$src)>; + def FpSTP32m : FpI<(ops f32mem:$op, RFP:$src), OneArgFP, []>; def FpSTP64m : FpI<(ops f64mem:$op, RFP:$src), OneArgFP, []>; def FpIST16m : FpI<(ops i16mem:$op, RFP:$src), OneArgFP, []>; -- 2.11.0