mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-26 14:25:18 +00:00
DAG based isel call support.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25103 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
941334f0b0
commit
d90eb7fb24
@ -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<ConstantFPSDNode>(N)->isExactlyValue(+0.0) &&
|
||||
"SSE only supports +0.0");
|
||||
Opc = (NVT == MVT::f32) ? X86::FLD0SS : X86::FLD0SD;
|
||||
}
|
||||
|
||||
if (cast<ConstantFPSDNode>(N)->isExactlyValue(+0.0) ||
|
||||
cast<ConstantFPSDNode>(N)->isExactlyValue(-0.0))
|
||||
Opc = X86::FpLD0;
|
||||
else if (cast<ConstantFPSDNode>(N)->isExactlyValue(+1.0) ||
|
||||
cast<ConstantFPSDNode>(N)->isExactlyValue(-1.0))
|
||||
Opc = X86::FpLD1;
|
||||
|
||||
assert(Opc != 0 && "Unexpected constant!");
|
||||
|
||||
SDOperand Result = CurDAG->getTargetNode(Opc, NVT);
|
||||
|
||||
if (cast<ConstantFPSDNode>(N)->getValue() < 0.0 ||
|
||||
cast<ConstantFPSDNode>(N)->isExactlyValue(-0.0))
|
||||
Result = CurDAG->getTargetNode(X86::FpCHS, NVT, Result);
|
||||
|
||||
CodeGenMap[N] = Result;
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
return SelectCode(N);
|
||||
|
@ -457,38 +457,117 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy,
|
||||
RetVals.push_back(MVT::i32);
|
||||
break;
|
||||
}
|
||||
std::vector<SDOperand> 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<MVT::ValueType> NodeTys;
|
||||
NodeTys.push_back(MVT::Other); // Returns a chain
|
||||
NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
|
||||
|
||||
std::vector<SDOperand> 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<MVT::ValueType> Tys;
|
||||
Tys.push_back(MVT::f64);
|
||||
Tys.push_back(MVT::Other);
|
||||
std::vector<SDOperand> 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<SDOperand> 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);
|
||||
}
|
||||
|
||||
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";
|
||||
|
@ -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.
|
||||
|
@ -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<bits<8> o, Format f, dag ops, string asm, list<dag> 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<bits<8> opcode, dag ops, string asm, list<dag> 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<dag ops, FPFormat fp, list<dag> 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, []>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user