[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp X86ISelLowering.cpp X86ISelLowering.h X86InstrInfo.td
Evan Cheng
evan.cheng at apple.com
Wed Jan 4 16:27:14 PST 2006
Changes in directory llvm/lib/Target/X86:
X86ISelDAGToDAG.cpp updated: 1.19 -> 1.20
X86ISelLowering.cpp updated: 1.18 -> 1.19
X86ISelLowering.h updated: 1.9 -> 1.10
X86InstrInfo.td updated: 1.186 -> 1.187
---
Log message:
DAG based isel call support.
---
Diffs of the changes: (+197 -41)
X86ISelDAGToDAG.cpp | 27 +++++++++
X86ISelLowering.cpp | 141 ++++++++++++++++++++++++++++++++++++++++------------
X86ISelLowering.h | 11 ++++
X86InstrInfo.td | 59 +++++++++++++++++----
4 files changed, 197 insertions(+), 41 deletions(-)
Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
diff -u llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.19 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.20
--- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.19 Wed Dec 21 17:05:39 2005
+++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp Wed Jan 4 18:27:02 2006
@@ -410,6 +410,33 @@
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);
Index: llvm/lib/Target/X86/X86ISelLowering.cpp
diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.18 llvm/lib/Target/X86/X86ISelLowering.cpp:1.19
--- llvm/lib/Target/X86/X86ISelLowering.cpp:1.18 Mon Dec 26 21:02:18 2005
+++ llvm/lib/Target/X86/X86ISelLowering.cpp Wed Jan 4 18:27:02 2006
@@ -457,38 +457,117 @@
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.
- return std::make_pair(ResultVal, Chain);
+ 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);
+ }
}
SDOperand
@@ -1085,6 +1164,8 @@
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";
Index: llvm/lib/Target/X86/X86ISelLowering.h
diff -u llvm/lib/Target/X86/X86ISelLowering.h:1.9 llvm/lib/Target/X86/X86ISelLowering.h:1.10
--- llvm/lib/Target/X86/X86ISelLowering.h:1.9 Fri Dec 23 01:31:11 2005
+++ llvm/lib/Target/X86/X86ISelLowering.h Wed Jan 4 18:27:02 2006
@@ -46,6 +46,17 @@
/// 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.
Index: llvm/lib/Target/X86/X86InstrInfo.td
diff -u llvm/lib/Target/X86/X86InstrInfo.td:1.186 llvm/lib/Target/X86/X86InstrInfo.td:1.187
--- llvm/lib/Target/X86/X86InstrInfo.td:1.186 Mon Dec 26 03:11:45 2005
+++ llvm/lib/Target/X86/X86InstrInfo.td Wed Jan 4 18:27:02 2006
@@ -36,7 +36,11 @@
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 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 @@
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 @@
}
}
-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 @@
//===----------------------------------------------------------------------===//
// 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 @@
}
// 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 @@
[(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 @@
[(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, []>;
More information about the llvm-commits
mailing list