[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelLowering.cpp
Chris Lattner
sabre at nondot.org
Mon Feb 26 20:18:31 PST 2007
Changes in directory llvm/lib/Target/X86:
X86ISelLowering.cpp updated: 1.341 -> 1.342
---
Log message:
refactor x86-64 argument lowering yet again, this time eliminating templates,
'clients', etc, and adding CCValAssign instead.
---
Diffs of the changes: (+179 -166)
X86ISelLowering.cpp | 345 ++++++++++++++++++++++++++--------------------------
1 files changed, 179 insertions(+), 166 deletions(-)
Index: llvm/lib/Target/X86/X86ISelLowering.cpp
diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.341 llvm/lib/Target/X86/X86ISelLowering.cpp:1.342
--- llvm/lib/Target/X86/X86ISelLowering.cpp:1.341 Mon Feb 26 01:59:53 2007
+++ llvm/lib/Target/X86/X86ISelLowering.cpp Mon Feb 26 22:18:15 2007
@@ -1061,7 +1061,7 @@
class CallingConvState {
unsigned StackOffset;
const MRegisterInfo &MRI;
- SmallVector<uint32_t, 32> UsedRegs;
+ SmallVector<uint32_t, 16> UsedRegs;
public:
CallingConvState(const MRegisterInfo &mri) : MRI(mri) {
// No stack is used.
@@ -1119,19 +1119,88 @@
}
};
+/// CCValAssign - Represent assignment of one arg/retval to a location.
+class CCValAssign {
+public:
+ enum LocInfo {
+ Full, // The value fills the full location.
+ SExt, // The value is sign extended in the location.
+ ZExt, // The value is zero extended in the location.
+ AExt // The value is extended with undefined upper bits.
+ // TODO: a subset of the value is in the location.
+ };
+private:
+ /// ValNo - This is the value number begin assigned (e.g. an argument number).
+ unsigned ValNo;
+
+ /// Loc is either a stack offset or a register number.
+ unsigned Loc;
+
+ /// isMem - True if this is a memory loc, false if it is a register loc.
+ bool isMem : 1;
+
+ /// Information about how the value is assigned.
+ LocInfo HTP : 7;
+
+ /// ValVT - The type of the value being assigned.
+ MVT::ValueType ValVT : 8;
+
+ /// LocVT - The type of the location being assigned to.
+ MVT::ValueType LocVT : 8;
+public:
+
+ static CCValAssign getReg(unsigned ValNo, MVT::ValueType ValVT,
+ unsigned RegNo, MVT::ValueType LocVT,
+ LocInfo HTP) {
+ CCValAssign Ret;
+ Ret.ValNo = ValNo;
+ Ret.Loc = RegNo;
+ Ret.isMem = false;
+ Ret.HTP = HTP;
+ Ret.ValVT = ValVT;
+ Ret.LocVT = LocVT;
+ return Ret;
+ }
+ static CCValAssign getMem(unsigned ValNo, MVT::ValueType ValVT,
+ unsigned Offset, MVT::ValueType LocVT,
+ LocInfo HTP) {
+ CCValAssign Ret;
+ Ret.ValNo = ValNo;
+ Ret.Loc = Offset;
+ Ret.isMem = true;
+ Ret.HTP = HTP;
+ Ret.ValVT = ValVT;
+ Ret.LocVT = LocVT;
+ return Ret;
+ }
+
+ unsigned getValNo() const { return ValNo; }
+ MVT::ValueType getValVT() const { return ValVT; }
+
+ bool isRegLoc() const { return !isMem; }
+ bool isMemLoc() const { return isMem; }
+
+ unsigned getLocReg() const { assert(isRegLoc()); return Loc; }
+ unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; }
+ MVT::ValueType getLocVT() const { return LocVT; }
+
+ LocInfo getLocInfo() const { return HTP; }
+};
+
+
/// X86_64_CCC_AssignArgument - Implement the X86-64 C Calling Convention.
-template<typename Client, typename DataTy>
-static void X86_64_CCC_AssignArgument(Client &C, CallingConvState &State,
+static void X86_64_CCC_AssignArgument(unsigned ValNo,
MVT::ValueType ArgVT, unsigned ArgFlags,
- DataTy Data) {
+ CallingConvState &State,
+ SmallVector<CCValAssign, 16> &Locs) {
MVT::ValueType LocVT = ArgVT;
- unsigned ExtendType = ISD::ANY_EXTEND;
+ CCValAssign::LocInfo LocInfo = CCValAssign::Full;
// Promote the integer to 32 bits. If the input type is signed use a
// sign extend, otherwise use a zero extend.
if (ArgVT == MVT::i8 || ArgVT == MVT::i16) {
LocVT = MVT::i32;
- ExtendType = (ArgFlags & 1) ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
+ LocInfo = (ArgFlags & 1) ? CCValAssign::SExt : CCValAssign::ZExt;
}
// If this is a 32-bit value, assign to a 32-bit register if any are
@@ -1141,7 +1210,7 @@
X86::EDI, X86::ESI, X86::EDX, X86::ECX, X86::R8D, X86::R9D
};
if (unsigned Reg = State.AllocateReg(GPR32ArgRegs, 6)) {
- C.AssignToReg(Data, Reg, ArgVT, LocVT, ExtendType);
+ Locs.push_back(CCValAssign::getReg(ValNo, ArgVT, Reg, LocVT, LocInfo));
return;
}
}
@@ -1153,7 +1222,7 @@
X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8, X86::R9
};
if (unsigned Reg = State.AllocateReg(GPR64ArgRegs, 6)) {
- C.AssignToReg(Data, Reg, ArgVT, LocVT, ExtendType);
+ Locs.push_back(CCValAssign::getReg(ValNo, ArgVT, Reg, LocVT, LocInfo));
return;
}
}
@@ -1166,7 +1235,7 @@
X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
};
if (unsigned Reg = State.AllocateReg(XMMArgRegs, 8)) {
- C.AssignToReg(Data, Reg, ArgVT, LocVT, ExtendType);
+ Locs.push_back(CCValAssign::getReg(ValNo, ArgVT, Reg, LocVT, LocInfo));
return;
}
}
@@ -1176,144 +1245,19 @@
if (LocVT == MVT::i32 || LocVT == MVT::i64 ||
LocVT == MVT::f32 || LocVT == MVT::f64) {
unsigned Offset = State.AllocateStack(8, 8);
- C.AssignToStack(Data, Offset, ArgVT, LocVT, ExtendType);
+ Locs.push_back(CCValAssign::getMem(ValNo, ArgVT, Offset, LocVT, LocInfo));
return;
}
// Vectors get 16-byte stack slots that are 16-byte aligned.
if (MVT::isVector(LocVT)) {
unsigned Offset = State.AllocateStack(16, 16);
- C.AssignToStack(Data, Offset, ArgVT, LocVT, ExtendType);
+ Locs.push_back(CCValAssign::getMem(ValNo, ArgVT, Offset, LocVT, LocInfo));
return;
}
assert(0 && "Unknown argument type!");
}
-class LowerArgumentsClient {
- SelectionDAG &DAG;
- X86TargetLowering &TLI;
- SmallVector<SDOperand, 8> &ArgValues;
- SDOperand Chain;
-public:
- LowerArgumentsClient(SelectionDAG &dag, X86TargetLowering &tli,
- SmallVector<SDOperand, 8> &argvalues,
- SDOperand chain)
- : DAG(dag), TLI(tli), ArgValues(argvalues), Chain(chain) {
-
- }
-
- void AssignToReg(SDOperand Arg, unsigned RegNo,
- MVT::ValueType ArgVT, MVT::ValueType RegVT,
- unsigned ExtendType) {
- TargetRegisterClass *RC = NULL;
- if (RegVT == MVT::i32)
- RC = X86::GR32RegisterClass;
- else if (RegVT == MVT::i64)
- RC = X86::GR64RegisterClass;
- else if (RegVT == MVT::f32)
- RC = X86::FR32RegisterClass;
- else if (RegVT == MVT::f64)
- RC = X86::FR64RegisterClass;
- else {
- RC = X86::VR128RegisterClass;
- }
-
- SDOperand ArgValue = DAG.getCopyFromReg(Chain, RegNo, RegVT);
- AddLiveIn(DAG.getMachineFunction(), RegNo, RC);
-
- // If this is an 8 or 16-bit value, it is really passed promoted to 32
- // bits. Insert an assert[sz]ext to capture this, then truncate to the
- // right size.
- if (ArgVT < RegVT) {
- if (ExtendType == ISD::SIGN_EXTEND) {
- ArgValue = DAG.getNode(ISD::AssertSext, RegVT, ArgValue,
- DAG.getValueType(ArgVT));
- } else if (ExtendType == ISD::ZERO_EXTEND) {
- ArgValue = DAG.getNode(ISD::AssertZext, RegVT, ArgValue,
- DAG.getValueType(ArgVT));
- }
- ArgValue = DAG.getNode(ISD::TRUNCATE, ArgVT, ArgValue);
- }
-
- ArgValues.push_back(ArgValue);
- }
-
- void AssignToStack(SDOperand Arg, unsigned Offset,
- MVT::ValueType ArgVT, MVT::ValueType DestVT,
- unsigned ExtendType) {
- // Create the SelectionDAG nodes corresponding to a load from this
- // parameter.
- MachineFunction &MF = DAG.getMachineFunction();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- int FI = MFI->CreateFixedObject(MVT::getSizeInBits(ArgVT)/8, Offset);
- SDOperand FIN = DAG.getFrameIndex(FI, TLI.getPointerTy());
- ArgValues.push_back(DAG.getLoad(ArgVT, Chain, FIN, NULL, 0));
- }
-};
-
-class LowerCallArgumentsClient {
- SelectionDAG &DAG;
- X86TargetLowering &TLI;
- SmallVector<std::pair<unsigned, SDOperand>, 8> &RegsToPass;
- SmallVector<SDOperand, 8> &MemOpChains;
- SDOperand Chain;
- SDOperand StackPtr;
-public:
- LowerCallArgumentsClient(SelectionDAG &dag, X86TargetLowering &tli,
- SmallVector<std::pair<unsigned, SDOperand>, 8> &rtp,
- SmallVector<SDOperand, 8> &moc,
- SDOperand chain)
- : DAG(dag), TLI(tli), RegsToPass(rtp), MemOpChains(moc), Chain(chain) {
-
- }
-
- void AssignToReg(SDOperand Arg, unsigned RegNo,
- MVT::ValueType ArgVT, MVT::ValueType RegVT,
- unsigned ExtendType) {
- // If the argument has to be extended somehow before being passed, do so.
- if (ArgVT < RegVT)
- Arg = DAG.getNode(ExtendType, RegVT, Arg);
-
- RegsToPass.push_back(std::make_pair(RegNo, Arg));
- }
-
- void AssignToStack(SDOperand Arg, unsigned Offset,
- MVT::ValueType ArgVT, MVT::ValueType DestVT,
- unsigned ExtendType) {
- // If the argument has to be extended somehow before being stored, do so.
- if (ArgVT < DestVT)
- Arg = DAG.getNode(ExtendType, DestVT, Arg);
-
- SDOperand SP = getSP();
- SDOperand PtrOff = DAG.getConstant(Offset, SP.getValueType());
- PtrOff = DAG.getNode(ISD::ADD, SP.getValueType(), SP, PtrOff);
- MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
- }
-private:
- SDOperand getSP() {
- if (StackPtr.Val == 0) {
- MVT::ValueType PtrTy = TLI.getPointerTy();
- StackPtr = DAG.getRegister(TLI.getStackPtrReg(), PtrTy);
- }
- return StackPtr;
- }
-};
-
-class EmptyArgumentsClient {
-public:
- EmptyArgumentsClient() {}
-
- void AssignToReg(SDOperand Arg, unsigned RegNo,
- MVT::ValueType ArgVT, MVT::ValueType RegVT,
- unsigned ExtendType) {
- }
-
- void AssignToStack(SDOperand Arg, unsigned Offset,
- MVT::ValueType ArgVT, MVT::ValueType DestVT,
- unsigned ExtendType) {
- }
-};
-
SDOperand
X86TargetLowering::LowerX86_64CCCArguments(SDOperand Op, SelectionDAG &DAG) {
@@ -1335,15 +1279,62 @@
CallingConvState CCState(*getTargetMachine().getRegisterInfo());
- LowerArgumentsClient Client(DAG, *this, ArgValues, Root);
-
+ SmallVector<CCValAssign, 16> ArgLocs;
+
for (unsigned i = 0; i != NumArgs; ++i) {
MVT::ValueType ArgVT = Op.getValue(i).getValueType();
unsigned ArgFlags = cast<ConstantSDNode>(Op.getOperand(3+i))->getValue();
-
- X86_64_CCC_AssignArgument(Client, CCState, ArgVT, ArgFlags, SDOperand());
+ X86_64_CCC_AssignArgument(i, ArgVT, ArgFlags, CCState, ArgLocs);
}
-
+
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ CCValAssign &VA = ArgLocs[i];
+
+
+ if (VA.isRegLoc()) {
+ MVT::ValueType RegVT = VA.getLocVT();
+ TargetRegisterClass *RC;
+ if (RegVT == MVT::i32)
+ RC = X86::GR32RegisterClass;
+ else if (RegVT == MVT::i64)
+ RC = X86::GR64RegisterClass;
+ else if (RegVT == MVT::f32)
+ RC = X86::FR32RegisterClass;
+ else if (RegVT == MVT::f64)
+ RC = X86::FR64RegisterClass;
+ else {
+ assert(MVT::isVector(RegVT));
+ RC = X86::VR128RegisterClass;
+ }
+
+ SDOperand ArgValue = DAG.getCopyFromReg(Root, VA.getLocReg(), RegVT);
+ AddLiveIn(DAG.getMachineFunction(), VA.getLocReg(), RC);
+
+ // If this is an 8 or 16-bit value, it is really passed promoted to 32
+ // bits. Insert an assert[sz]ext to capture this, then truncate to the
+ // right size.
+ if (VA.getLocInfo() == CCValAssign::SExt)
+ ArgValue = DAG.getNode(ISD::AssertSext, RegVT, ArgValue,
+ DAG.getValueType(VA.getValVT()));
+ else if (VA.getLocInfo() == CCValAssign::ZExt)
+ ArgValue = DAG.getNode(ISD::AssertZext, RegVT, ArgValue,
+ DAG.getValueType(VA.getValVT()));
+
+ if (VA.getLocInfo() != CCValAssign::Full)
+ ArgValue = DAG.getNode(ISD::TRUNCATE, VA.getValVT(), ArgValue);
+
+ ArgValues.push_back(ArgValue);
+ } else {
+ assert(VA.isMemLoc());
+
+ // Create the nodes corresponding to a load from this parameter slot.
+ int FI = MFI->CreateFixedObject(MVT::getSizeInBits(VA.getValVT())/8,
+ VA.getLocMemOffset());
+ SDOperand FIN = DAG.getFrameIndex(FI, getPointerTy());
+ ArgValues.push_back(DAG.getLoad(VA.getValVT(), Root, FIN, NULL, 0));
+ }
+ }
+
unsigned StackSize = CCState.getNextStackOffset();
// If the function takes variable number of arguments, make a frame index for
@@ -1412,40 +1403,62 @@
SDOperand Callee = Op.getOperand(4);
unsigned NumOps = (Op.getNumOperands() - 5) / 2;
- // Count how many bytes are to be pushed on the stack.
- unsigned NumBytes = 0;
- {
- CallingConvState CCState(*getTargetMachine().getRegisterInfo());
- EmptyArgumentsClient Client;
-
- for (unsigned i = 0; i != NumOps; ++i) {
- SDOperand Arg = Op.getOperand(5+2*i);
- MVT::ValueType ArgVT = Arg.getValueType();
- unsigned ArgFlags =
- cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
- X86_64_CCC_AssignArgument(Client, CCState, ArgVT, ArgFlags, Arg);
- }
-
- NumBytes = CCState.getNextStackOffset();
+ CallingConvState CCState(*getTargetMachine().getRegisterInfo());
+ SmallVector<CCValAssign, 16> ArgLocs;
+
+ for (unsigned i = 0; i != NumOps; ++i) {
+ MVT::ValueType ArgVT = Op.getOperand(5+2*i).getValueType();
+ unsigned ArgFlags =cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
+ X86_64_CCC_AssignArgument(i, ArgVT, ArgFlags, CCState, ArgLocs);
}
-
+ // Get a count of how many bytes are to be pushed on the stack.
+ unsigned NumBytes = CCState.getNextStackOffset();
Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, getPointerTy()));
SmallVector<std::pair<unsigned, SDOperand>, 8> RegsToPass;
SmallVector<SDOperand, 8> MemOpChains;
- CallingConvState CCState(*getTargetMachine().getRegisterInfo());
- LowerCallArgumentsClient Client(DAG, *this, RegsToPass, MemOpChains, Chain);
+ SDOperand StackPtr;
+
+ // Walk the register/memloc assignments, inserting copies/loads.
+ unsigned LastVal = ~0U;
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ CCValAssign &VA = ArgLocs[i];
- for (unsigned i = 0; i != NumOps; ++i) {
- SDOperand Arg = Op.getOperand(5+2*i);
- MVT::ValueType ArgVT = Arg.getValueType();
- unsigned ArgFlags =
- cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
- X86_64_CCC_AssignArgument(Client, CCState, ArgVT, ArgFlags, Arg);
- }
+ assert(VA.getValNo() != LastVal &&
+ "Don't support value assigned to multiple locs yet");
+ LastVal = VA.getValNo();
+
+ SDOperand Arg = Op.getOperand(5+2*VA.getValNo());
+
+ // Promote the value if needed.
+ switch (VA.getLocInfo()) {
+ default: assert(0 && "Unknown loc info!");
+ case CCValAssign::Full: break;
+ case CCValAssign::SExt:
+ Arg = DAG.getNode(ISD::SIGN_EXTEND, VA.getLocVT(), Arg);
+ break;
+ case CCValAssign::ZExt:
+ Arg = DAG.getNode(ISD::ZERO_EXTEND, VA.getLocVT(), Arg);
+ break;
+ case CCValAssign::AExt:
+ Arg = DAG.getNode(ISD::ANY_EXTEND, VA.getLocVT(), Arg);
+ break;
+ }
+ if (VA.isRegLoc()) {
+ RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
+ } else {
+ assert(VA.isMemLoc());
+ if (StackPtr.Val == 0)
+ StackPtr = DAG.getRegister(getStackPtrReg(), getPointerTy());
+ SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(), getPointerTy());
+ PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+ MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
+ }
+ }
+
if (!MemOpChains.empty())
Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
&MemOpChains[0], MemOpChains.size());
More information about the llvm-commits
mailing list