[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelLowering.cpp X86ISelLowering.h
Chris Lattner
sabre at nondot.org
Sun Feb 25 00:15:30 PST 2007
Changes in directory llvm/lib/Target/X86:
X86ISelLowering.cpp updated: 1.327 -> 1.328
X86ISelLowering.h updated: 1.85 -> 1.86
---
Log message:
simplify result value lowering by splitting the selection of *where* to return
registers out from the logic of *how* to return them.
This changes X86-64 to mark EAX live out when returning a 32-bit value,
where before it marked RAX liveout.
---
Diffs of the changes: (+111 -91)
X86ISelLowering.cpp | 190 ++++++++++++++++++++++++++++------------------------
X86ISelLowering.h | 12 +--
2 files changed, 111 insertions(+), 91 deletions(-)
Index: llvm/lib/Target/X86/X86ISelLowering.cpp
diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.327 llvm/lib/Target/X86/X86ISelLowering.cpp:1.328
--- llvm/lib/Target/X86/X86ISelLowering.cpp:1.327 Sun Feb 25 01:18:38 2007
+++ llvm/lib/Target/X86/X86ISelLowering.cpp Sun Feb 25 02:15:11 2007
@@ -3915,96 +3915,116 @@
}
}
-SDOperand X86TargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG) {
- SDOperand Copy;
+/// GetRetValueLocs - If we are returning a set of values with the specified
+/// value types, determine the set of registers each one will land in. This
+/// sets one element of the ResultRegs array for each element in the VTs array.
+static void GetRetValueLocs(const MVT::ValueType *VTs, unsigned NumVTs,
+ unsigned *ResultRegs,
+ const X86Subtarget *Subtarget) {
+ if (NumVTs == 0) return;
+
+ if (NumVTs == 2) {
+ ResultRegs[0] = VTs[0] == MVT::i64 ? X86::RAX : X86::EAX;
+ ResultRegs[1] = VTs[1] == MVT::i64 ? X86::RDX : X86::EDX;
+ return;
+ }
+
+ // Otherwise, NumVTs is 1.
+ MVT::ValueType ArgVT = VTs[0];
+
+ if (MVT::isVector(ArgVT)) // Integer or FP vector result -> XMM0.
+ ResultRegs[0] = X86::XMM0;
+ else if (MVT::isFloatingPoint(ArgVT) && Subtarget->is64Bit())
+ // FP values in X86-64 go in XMM0.
+ ResultRegs[0] = X86::XMM0;
+ else if (MVT::isFloatingPoint(ArgVT))
+ // FP values in X86-32 go in ST0.
+ ResultRegs[0] = X86::ST0;
+ else {
+ assert(MVT::isInteger(ArgVT) && "Unknown return value type!");
+
+ // Integer result -> EAX / RAX.
+ // The C calling convention guarantees the return value has been
+ // promoted to at least MVT::i32. The X86-64 ABI doesn't require the
+ // value to be promoted MVT::i64. So we don't have to extend it to
+ // 64-bit.
+ ResultRegs[0] = (ArgVT == MVT::i64) ? X86::RAX : X86::EAX;
+ }
+}
- switch(Op.getNumOperands()) {
- default:
- assert(0 && "Do not know how to return this many arguments!");
- abort();
- case 1: // ret void.
- return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Op.getOperand(0),
- DAG.getConstant(getBytesToPopOnReturn(), MVT::i16));
- case 3: {
- MVT::ValueType ArgVT = Op.getOperand(1).getValueType();
-
- if (MVT::isVector(ArgVT) ||
- (Subtarget->is64Bit() && MVT::isFloatingPoint(ArgVT))) {
- // Integer or FP vector result -> XMM0.
- if (DAG.getMachineFunction().liveout_empty())
- DAG.getMachineFunction().addLiveOut(X86::XMM0);
- Copy = DAG.getCopyToReg(Op.getOperand(0), X86::XMM0, Op.getOperand(1),
- SDOperand());
- } else if (MVT::isInteger(ArgVT)) {
- // Integer result -> EAX / RAX.
- // The C calling convention guarantees the return value has been
- // promoted to at least MVT::i32. The X86-64 ABI doesn't require the
- // value to be promoted MVT::i64. So we don't have to extend it to
- // 64-bit. Return the value in EAX, but mark RAX as liveout.
- unsigned Reg = Subtarget->is64Bit() ? X86::RAX : X86::EAX;
- if (DAG.getMachineFunction().liveout_empty())
- DAG.getMachineFunction().addLiveOut(Reg);
-
- Reg = (ArgVT == MVT::i64) ? X86::RAX : X86::EAX;
- Copy = DAG.getCopyToReg(Op.getOperand(0), Reg, Op.getOperand(1),
- SDOperand());
- } else if (!X86ScalarSSE) {
- // FP return with fp-stack value.
- if (DAG.getMachineFunction().liveout_empty())
- DAG.getMachineFunction().addLiveOut(X86::ST0);
-
- SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
- SDOperand Ops[] = { Op.getOperand(0), Op.getOperand(1) };
- Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops, 2);
- } else {
- // FP return with ScalarSSE (return on fp-stack).
- if (DAG.getMachineFunction().liveout_empty())
- DAG.getMachineFunction().addLiveOut(X86::ST0);
-
- SDOperand MemLoc;
- SDOperand Chain = Op.getOperand(0);
- SDOperand Value = Op.getOperand(1);
-
- if (ISD::isNON_EXTLoad(Value.Val) &&
- (Chain == Value.getValue(1) || Chain == Value.getOperand(0))) {
- Chain = Value.getOperand(0);
- MemLoc = Value.getOperand(1);
- } else {
- // Spill the value to memory and reload it into top of stack.
- unsigned Size = MVT::getSizeInBits(ArgVT)/8;
- MachineFunction &MF = DAG.getMachineFunction();
- int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size);
- MemLoc = DAG.getFrameIndex(SSFI, getPointerTy());
- Chain = DAG.getStore(Op.getOperand(0), Value, MemLoc, NULL, 0);
- }
- SDVTList Tys = DAG.getVTList(MVT::f64, MVT::Other);
- SDOperand Ops[] = { Chain, MemLoc, DAG.getValueType(ArgVT) };
- Copy = DAG.getNode(X86ISD::FLD, Tys, Ops, 3);
-
- Tys = DAG.getVTList(MVT::Other, MVT::Flag);
- Ops[0] = Copy.getValue(1);
- Ops[1] = Copy;
- Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops, 2);
- }
- break;
+
+SDOperand X86TargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG) {
+ assert((Op.getNumOperands() & 1) == 1 && "ISD::RET should have odd # args");
+
+ // Support up returning up to two registers.
+ MVT::ValueType VTs[2];
+ unsigned DestRegs[2];
+ unsigned NumRegs = Op.getNumOperands() / 2;
+ assert(NumRegs <= 2 && "Can only return up to two regs!");
+
+ for (unsigned i = 0; i != NumRegs; ++i)
+ VTs[i] = Op.getOperand(i*2+1).getValueType();
+
+ // Determine which register each value should be copied into.
+ GetRetValueLocs(VTs, NumRegs, DestRegs, Subtarget);
+
+ // If this is the first return lowered for this function, add the regs to the
+ // liveout set for the function.
+ if (DAG.getMachineFunction().liveout_empty()) {
+ for (unsigned i = 0; i != NumRegs; ++i)
+ DAG.getMachineFunction().addLiveOut(DestRegs[i]);
+ }
+
+ SDOperand Chain = Op.getOperand(0);
+ SDOperand Flag;
+
+ // Copy the result values into the output registers.
+ if (NumRegs != 1 || DestRegs[0] != X86::ST0) {
+ for (unsigned i = 0; i != NumRegs; ++i) {
+ Chain = DAG.getCopyToReg(Chain, DestRegs[i], Op.getOperand(i*2+1), Flag);
+ Flag = Chain.getValue(1);
}
- case 5: {
- unsigned Reg1 = Subtarget->is64Bit() ? X86::RAX : X86::EAX;
- unsigned Reg2 = Subtarget->is64Bit() ? X86::RDX : X86::EDX;
- if (DAG.getMachineFunction().liveout_empty()) {
- DAG.getMachineFunction().addLiveOut(Reg1);
- DAG.getMachineFunction().addLiveOut(Reg2);
+ } else {
+ // We need to handle a destination of ST0 specially, because it isn't really
+ // a register.
+ SDOperand Value = Op.getOperand(1);
+
+ // If this is an FP return with ScalarSSE, we need to move the value from
+ // an XMM register onto the fp-stack.
+ if (X86ScalarSSE) {
+ SDOperand MemLoc;
+
+ // If this is a load into a scalarsse value, don't store the loaded value
+ // back to the stack, only to reload it: just replace the scalar-sse load.
+ if (ISD::isNON_EXTLoad(Value.Val) &&
+ (Chain == Value.getValue(1) || Chain == Value.getOperand(0))) {
+ Chain = Value.getOperand(0);
+ MemLoc = Value.getOperand(1);
+ } else {
+ // Spill the value to memory and reload it into top of stack.
+ unsigned Size = MVT::getSizeInBits(VTs[0])/8;
+ MachineFunction &MF = DAG.getMachineFunction();
+ int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size);
+ MemLoc = DAG.getFrameIndex(SSFI, getPointerTy());
+ Chain = DAG.getStore(Op.getOperand(0), Value, MemLoc, NULL, 0);
}
-
- Copy = DAG.getCopyToReg(Op.getOperand(0), Reg2, Op.getOperand(3),
- SDOperand());
- Copy = DAG.getCopyToReg(Copy, Reg1, Op.getOperand(1), Copy.getValue(1));
- break;
+ SDVTList Tys = DAG.getVTList(MVT::f64, MVT::Other);
+ SDOperand Ops[] = { Chain, MemLoc, DAG.getValueType(VTs[0]) };
+ Value = DAG.getNode(X86ISD::FLD, Tys, Ops, 3);
+ Chain = Value.getValue(1);
}
+
+ SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
+ SDOperand Ops[] = { Chain, Value };
+ Chain = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops, 2);
+ Flag = Chain.getValue(1);
}
- return DAG.getNode(X86ISD::RET_FLAG, MVT::Other,
- Copy, DAG.getConstant(getBytesToPopOnReturn(), MVT::i16),
- Copy.getValue(1));
+
+ SDOperand BytesToPop = DAG.getConstant(getBytesToPopOnReturn(), MVT::i16);
+ if (Flag.Val)
+ return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Chain, BytesToPop, Flag);
+ else
+ return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Chain, BytesToPop);
}
SDOperand
Index: llvm/lib/Target/X86/X86ISelLowering.h
diff -u llvm/lib/Target/X86/X86ISelLowering.h:1.85 llvm/lib/Target/X86/X86ISelLowering.h:1.86
--- llvm/lib/Target/X86/X86ISelLowering.h:1.85 Mon Jan 29 16:58:52 2007
+++ llvm/lib/Target/X86/X86ISelLowering.h Sun Feb 25 02:15:11 2007
@@ -76,14 +76,14 @@
/// 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 - This corresponds to FpGETRESULT pseudo instruction
+ /// 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.
+ /// FP_SET_RESULT - This corresponds to FpSETRESULT pseudo instruction
+ /// which copies the source operand to ST(0). It takes a chain+value and
+ /// returns a chain and a flag.
FP_SET_RESULT,
/// CALL/TAILCALL - These operations represent an abstract X86 call
More information about the llvm-commits
mailing list