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:
Evan Cheng 2006-01-05 00:27:02 +00:00
parent 941334f0b0
commit d90eb7fb24
4 changed files with 197 additions and 41 deletions

View File

@ -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);

View File

@ -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";

View File

@ -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.

View File

@ -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, []>;