#include "X86TargetMachine.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Intrinsics.h"
#include "llvm/ADT/VectorExtras.h"
addRegisterClass(MVT::f32, X86::FR32RegisterClass);
addRegisterClass(MVT::f64, X86::FR64RegisterClass);
- // SSE has no load+extend ops
- setOperationAction(ISD::EXTLOAD, MVT::f32, Expand);
- setOperationAction(ISD::ZEXTLOAD, MVT::f32, Expand);
-
// Use ANDPD to simulate FABS.
setOperationAction(ISD::FABS , MVT::f64, Custom);
setOperationAction(ISD::FABS , MVT::f32, Custom);
std::vector<SDOperand> Args = TargetLowering::LowerArguments(F, DAG);
FormalArgs.clear();
- // This sets BytesToPopOnReturn, BytesCallerReserves, etc. which have to be set
- // before the rest of the function can be lowered.
+ FormalArgLocs.clear();
+
+ // This sets BytesToPopOnReturn, BytesCallerReserves, etc. which have to be
+ // set before the rest of the function can be lowered.
if (F.getCallingConv() == CallingConv::Fast && EnableFastCC)
- PreprocessFastCCArguments(Args[0], F, DAG);
+ PreprocessFastCCArguments(Args, F, DAG);
else
- PreprocessCCCArguments(Args[0], F, DAG);
+ PreprocessCCCArguments(Args, F, DAG);
return Args;
}
// C Calling Convention implementation
//===----------------------------------------------------------------------===//
-void X86TargetLowering::PreprocessCCCArguments(SDOperand Op, Function &F,
- SelectionDAG &DAG) {
- unsigned NumArgs = Op.Val->getNumValues();
+/// AddLiveIn - This helper function adds the specified physical register to the
+/// MachineFunction as a live in value. It also creates a corresponding virtual
+/// register for it.
+static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
+ TargetRegisterClass *RC) {
+ assert(RC->contains(PReg) && "Not the correct regclass!");
+ unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC);
+ MF.addLiveIn(PReg, VReg);
+ return VReg;
+}
+
+/// HowToPassCCCArgument - Returns how an formal argument of the specified type
+/// should be passed. If it is through stack, returns the size of the stack
+/// frame; if it is through XMM register, returns the number of XMM registers
+/// are needed.
+static void
+HowToPassCCCArgument(MVT::ValueType ObjectVT, unsigned NumXMMRegs,
+ unsigned &ObjSize, unsigned &ObjXMMRegs) {
+ switch (ObjectVT) {
+ default: assert(0 && "Unhandled argument type!");
+ case MVT::i1:
+ case MVT::i8: ObjSize = 1; break;
+ case MVT::i16: ObjSize = 2; break;
+ case MVT::i32: ObjSize = 4; break;
+ case MVT::i64: ObjSize = 8; break;
+ case MVT::f32: ObjSize = 4; break;
+ case MVT::f64: ObjSize = 8; break;
+ case MVT::v16i8:
+ case MVT::v8i16:
+ case MVT::v4i32:
+ case MVT::v2i64:
+ case MVT::v4f32:
+ case MVT::v2f64:
+ if (NumXMMRegs < 3)
+ ObjXMMRegs = 1;
+ else
+ ObjSize = 16;
+ break;
+ }
+}
+
+/// getFormalArgObjects - Returns itself if Op is a FORMAL_ARGUMENTS, otherwise
+/// returns the FORMAL_ARGUMENTS node(s) that made up parts of the node.
+static std::vector<SDOperand> getFormalArgObjects(SDOperand Op) {
+ unsigned Opc = Op.getOpcode();
+ std::vector<SDOperand> Objs;
+ if (Opc == ISD::TRUNCATE) {
+ Op = Op.getOperand(0);
+ assert(Op.getOpcode() == ISD::AssertSext ||
+ Op.getOpcode() == ISD::AssertZext);
+ Objs.push_back(Op.getOperand(0));
+ } else if (Opc == ISD::FP_ROUND || Opc == ISD::VBIT_CONVERT) {
+ Objs.push_back(Op.getOperand(0));
+ } else if (Opc == ISD::BUILD_PAIR) {
+ Objs.push_back(Op.getOperand(0));
+ Objs.push_back(Op.getOperand(1));
+ } else {
+ Objs.push_back(Op);
+ }
+ return Objs;
+}
+
+void X86TargetLowering::PreprocessCCCArguments(std::vector<SDOperand>Args,
+ Function &F, SelectionDAG &DAG) {
+ unsigned NumArgs = Args.size();
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
+ // Add DAG nodes to load the arguments... On entry to a function on the X86,
+ // the stack frame looks like this:
+ //
+ // [ESP] -- return address
+ // [ESP + 4] -- first argument (leftmost lexically)
+ // [ESP + 8] -- second argument, if first argument is four bytes in size
+ // ...
+ //
unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot
+ unsigned NumXMMRegs = 0; // XMM regs used for parameter passing.
+ unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2 };
for (unsigned i = 0; i < NumArgs; ++i) {
- MVT::ValueType ObjectVT = Op.Val->getValueType(i);
- unsigned ArgIncrement = 4;
- unsigned ObjSize;
- switch (ObjectVT) {
- default: assert(0 && "Unhandled argument type!");
- case MVT::i1:
- case MVT::i8: ObjSize = 1; break;
- case MVT::i16: ObjSize = 2; break;
- case MVT::i32: ObjSize = 4; break;
- case MVT::i64: ObjSize = ArgIncrement = 8; break;
- case MVT::f32: ObjSize = 4; break;
- case MVT::f64: ObjSize = ArgIncrement = 8; break;
+ SDOperand Op = Args[i];
+ std::vector<SDOperand> Objs = getFormalArgObjects(Op);
+ for (std::vector<SDOperand>::iterator I = Objs.begin(), E = Objs.end();
+ I != E; ++I) {
+ SDOperand Obj = *I;
+ MVT::ValueType ObjectVT = Obj.getValueType();
+ unsigned ArgIncrement = 4;
+ unsigned ObjSize = 0;
+ unsigned ObjXMMRegs = 0;
+ HowToPassCCCArgument(ObjectVT, NumXMMRegs, ObjSize, ObjXMMRegs);
+ if (ObjSize >= 8)
+ ArgIncrement = ObjSize;
+
+ if (ObjXMMRegs) {
+ // Passed in a XMM register.
+ unsigned Reg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs],
+ X86::VR128RegisterClass);
+ std::pair<FALocInfo, FALocInfo> Loc =
+ std::make_pair(FALocInfo(FALocInfo::LiveInRegLoc, Reg, ObjectVT),
+ FALocInfo());
+ FormalArgLocs.push_back(Loc);
+ NumXMMRegs += ObjXMMRegs;
+ } else {
+ // Create the frame index object for this incoming parameter...
+ int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
+ std::pair<FALocInfo, FALocInfo> Loc =
+ std::make_pair(FALocInfo(FALocInfo::StackFrameLoc, FI), FALocInfo());
+ FormalArgLocs.push_back(Loc);
+ ArgOffset += ArgIncrement; // Move on to the next argument...
+ }
}
- ArgOffset += ArgIncrement; // Move on to the next argument...
}
// If the function takes variable number of arguments, make a frame index for
}
void X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG) {
- unsigned NumArgs = Op.Val->getNumValues();
+ unsigned NumArgs = Op.Val->getNumValues() - 1;
MachineFunction &MF = DAG.getMachineFunction();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- // Add DAG nodes to load the arguments... On entry to a function on the X86,
- // the stack frame looks like this:
- //
- // [ESP] -- return address
- // [ESP + 4] -- first argument (leftmost lexically)
- // [ESP + 8] -- second argument, if first argument is four bytes in size
- // ...
- //
- unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot
for (unsigned i = 0; i < NumArgs; ++i) {
- MVT::ValueType ObjectVT = Op.Val->getValueType(i);
- unsigned ArgIncrement = 4;
- unsigned ObjSize;
- switch (ObjectVT) {
- default: assert(0 && "Unhandled argument type!");
- case MVT::i1:
- case MVT::i8: ObjSize = 1; break;
- case MVT::i16: ObjSize = 2; break;
- case MVT::i32: ObjSize = 4; break;
- case MVT::i64: ObjSize = ArgIncrement = 8; break;
- case MVT::f32: ObjSize = 4; break;
- case MVT::f64: ObjSize = ArgIncrement = 8; break;
+ std::pair<FALocInfo, FALocInfo> Loc = FormalArgLocs[i];
+ SDOperand ArgValue;
+ if (Loc.first.Kind == FALocInfo::StackFrameLoc) {
+ // Create the SelectionDAG nodes corresponding to a load from this
+ // parameter.
+ unsigned FI = FormalArgLocs[i].first.Loc;
+ SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
+ ArgValue = DAG.getLoad(Op.Val->getValueType(i),
+ DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL));
+ } else {
+ // Must be a CopyFromReg
+ ArgValue= DAG.getCopyFromReg(DAG.getEntryNode(), Loc.first.Loc,
+ Loc.first.Typ);
}
- // Create the frame index object for this incoming parameter...
- int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
-
- // Create the SelectionDAG nodes corresponding to a load from this parameter
- SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
-
- SDOperand ArgValue = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN,
- DAG.getSrcValue(NULL));
FormalArgs.push_back(ArgValue);
- ArgOffset += ArgIncrement; // Move on to the next argument...
}
}
// Count how many bytes are to be pushed on the stack.
unsigned NumBytes = 0;
+ // Keep track of the number of XMM regs passed so far.
+ unsigned NumXMMRegs = 0;
+ unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2 };
+
+ std::vector<SDOperand> RegValuesToPass;
if (Args.empty()) {
// Save zero bytes.
Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(0, getPointerTy()));
case MVT::f64:
NumBytes += 8;
break;
+ case MVT::Vector:
+ if (NumXMMRegs < 3)
+ ++NumXMMRegs;
+ else
+ NumBytes += 16;
+ break;
}
Chain = DAG.getCALLSEQ_START(Chain,
// Arguments go on the stack in reverse order, as specified by the ABI.
unsigned ArgOffset = 0;
+ NumXMMRegs = 0;
SDOperand StackPtr = DAG.getRegister(X86::ESP, MVT::i32);
std::vector<SDOperand> Stores;
-
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
- PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
-
switch (getValueType(Args[i].second)) {
default: assert(0 && "Unexpected ValueType for argument!");
case MVT::i1:
// FALL THROUGH
case MVT::i32:
- case MVT::f32:
+ case MVT::f32: {
+ SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
+ PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
Args[i].first, PtrOff,
DAG.getSrcValue(NULL)));
ArgOffset += 4;
break;
+ }
case MVT::i64:
- case MVT::f64:
+ case MVT::f64: {
+ SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
+ PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
Args[i].first, PtrOff,
DAG.getSrcValue(NULL)));
ArgOffset += 8;
break;
}
+ case MVT::Vector:
+ if (NumXMMRegs < 3) {
+ RegValuesToPass.push_back(Args[i].first);
+ NumXMMRegs++;
+ } else {
+ SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
+ PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
+ Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+ Args[i].first, PtrOff,
+ DAG.getSrcValue(NULL)));
+ ArgOffset += 16;
+ }
+ }
}
+ if (!Stores.empty())
Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, Stores);
}
break;
}
+ // Build a sequence of copy-to-reg nodes chained together with token chain
+ // and flag operands which copy the outgoing args into registers.
+ SDOperand InFlag;
+ for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
+ unsigned CCReg = XMMArgRegs[i];
+ SDOperand RegToPass = RegValuesToPass[i];
+ assert(RegToPass.getValueType() == MVT::Vector);
+ unsigned NumElems =
+ cast<ConstantSDNode>(*(RegToPass.Val->op_end()-2))->getValue();
+ MVT::ValueType EVT = cast<VTSDNode>(*(RegToPass.Val->op_end()-1))->getVT();
+ MVT::ValueType PVT = getVectorType(EVT, NumElems);
+ SDOperand CCRegNode = DAG.getRegister(CCReg, PVT);
+ RegToPass = DAG.getNode(ISD::VBIT_CONVERT, PVT, RegToPass);
+ Chain = DAG.getCopyToReg(Chain, CCRegNode, RegToPass, InFlag);
+ InFlag = Chain.getValue(1);
+ }
+
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);
+ if (InFlag.Val)
+ Ops.push_back(InFlag);
// FIXME: Do not generate X86ISD::TAILCALL for now.
Chain = DAG.getNode(X86ISD::CALL, NodeTys, Ops);
- SDOperand InFlag = Chain.getValue(1);
+ InFlag = Chain.getValue(1);
NodeTys.clear();
NodeTys.push_back(MVT::Other); // Returns a chain
RetVal = DAG.getNode(ISD::FP_ROUND, MVT::f32, RetVal);
break;
}
+ case MVT::Vector: {
+ const PackedType *PTy = cast<PackedType>(RetTy);
+ MVT::ValueType EVT;
+ MVT::ValueType LVT;
+ unsigned NumRegs = getPackedTypeBreakdown(PTy, EVT, LVT);
+ assert(NumRegs == 1 && "Unsupported type!");
+ RetVal = DAG.getCopyFromReg(Chain, X86::XMM0, EVT, InFlag);
+ Chain = RetVal.getValue(1);
+ break;
+ }
}
}
// (when we have a global fp allocator) and do other tricks.
//
-/// AddLiveIn - This helper function adds the specified physical register to the
-/// MachineFunction as a live in value. It also creates a corresponding virtual
-/// register for it.
-static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
- TargetRegisterClass *RC) {
- assert(RC->contains(PReg) && "Not the correct regclass!");
- unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC);
- MF.addLiveIn(PReg, VReg);
- return VReg;
-}
-
// FASTCC_NUM_INT_ARGS_INREGS - This is the max number of integer arguments
// to pass in registers. 0 is none, 1 is is "use EAX", 2 is "use EAX and
// EDX". Anything more is illegal.
static unsigned FASTCC_NUM_INT_ARGS_INREGS = 0;
+/// HowToPassFastCCArgument - Returns how an formal argument of the specified
+/// type should be passed. If it is through stack, returns the size of the stack
+/// frame; if it is through integer or XMM register, returns the number of
+/// integer or XMM registers are needed.
+static void
+HowToPassFastCCArgument(MVT::ValueType ObjectVT,
+ unsigned NumIntRegs, unsigned NumXMMRegs,
+ unsigned &ObjSize, unsigned &ObjIntRegs,
+ unsigned &ObjXMMRegs) {
+ ObjSize = 0;
+ NumIntRegs = 0;
+
+ switch (ObjectVT) {
+ default: assert(0 && "Unhandled argument type!");
+ case MVT::i1:
+ case MVT::i8:
+ if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS)
+ ObjIntRegs = 1;
+ else
+ ObjSize = 1;
+ break;
+ case MVT::i16:
+ if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS)
+ ObjIntRegs = 1;
+ else
+ ObjSize = 2;
+ break;
+ case MVT::i32:
+ if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS)
+ ObjIntRegs = 1;
+ else
+ ObjSize = 4;
+ break;
+ case MVT::i64:
+ if (NumIntRegs+2 <= FASTCC_NUM_INT_ARGS_INREGS) {
+ ObjIntRegs = 2;
+ } else if (NumIntRegs+1 <= FASTCC_NUM_INT_ARGS_INREGS) {
+ ObjIntRegs = 1;
+ ObjSize = 4;
+ } else
+ ObjSize = 8;
+ case MVT::f32:
+ ObjSize = 4;
+ break;
+ case MVT::f64:
+ ObjSize = 8;
+ break;
+ case MVT::v16i8:
+ case MVT::v8i16:
+ case MVT::v4i32:
+ case MVT::v2i64:
+ case MVT::v4f32:
+ case MVT::v2f64:
+ if (NumXMMRegs < 3)
+ ObjXMMRegs = 1;
+ else
+ ObjSize = 16;
+ break;
+ }
+}
+
void
-X86TargetLowering::PreprocessFastCCArguments(SDOperand Op, Function &F,
- SelectionDAG &DAG) {
- unsigned NumArgs = Op.Val->getNumValues();
+X86TargetLowering::PreprocessFastCCArguments(std::vector<SDOperand>Args,
+ Function &F, SelectionDAG &DAG) {
+ unsigned NumArgs = Args.size();
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
+ // Add DAG nodes to load the arguments... On entry to a function the stack
+ // frame looks like this:
+ //
+ // [ESP] -- return address
+ // [ESP + 4] -- first nonreg argument (leftmost lexically)
+ // [ESP + 8] -- second nonreg argument, if first argument is 4 bytes in size
+ // ...
unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot
// Keep track of the number of integer regs passed so far. This can be either
// 0 (neither EAX or EDX used), 1 (EAX is used) or 2 (EAX and EDX are both
// used).
unsigned NumIntRegs = 0;
+ unsigned NumXMMRegs = 0; // XMM regs used for parameter passing.
+ unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2 };
for (unsigned i = 0; i < NumArgs; ++i) {
- MVT::ValueType ObjectVT = Op.Val->getValueType(i);
- unsigned ArgIncrement = 4;
- unsigned ObjSize = 0;
- SDOperand ArgValue;
-
- switch (ObjectVT) {
- default: assert(0 && "Unhandled argument type!");
- case MVT::i1:
- case MVT::i8:
- if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS) {
- ++NumIntRegs;
- break;
- }
-
- ObjSize = 1;
- break;
- case MVT::i16:
- if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS) {
- ++NumIntRegs;
- break;
- }
- ObjSize = 2;
- break;
- case MVT::i32:
- if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS) {
- ++NumIntRegs;
- break;
+ SDOperand Op = Args[i];
+ std::vector<SDOperand> Objs = getFormalArgObjects(Op);
+ for (std::vector<SDOperand>::iterator I = Objs.begin(), E = Objs.end();
+ I != E; ++I) {
+ SDOperand Obj = *I;
+ MVT::ValueType ObjectVT = Obj.getValueType();
+ unsigned ArgIncrement = 4;
+ unsigned ObjSize = 0;
+ unsigned ObjIntRegs = 0;
+ unsigned ObjXMMRegs = 0;
+
+ HowToPassFastCCArgument(ObjectVT, NumIntRegs, NumXMMRegs,
+ ObjSize, ObjIntRegs, ObjXMMRegs);
+ if (ObjSize >= 8)
+ ArgIncrement = ObjSize;
+
+ unsigned Reg;
+ std::pair<FALocInfo,FALocInfo> Loc = std::make_pair(FALocInfo(),
+ FALocInfo());
+ if (ObjIntRegs) {
+ switch (ObjectVT) {
+ default: assert(0 && "Unhandled argument type!");
+ case MVT::i1:
+ case MVT::i8:
+ Reg = AddLiveIn(MF, NumIntRegs ? X86::DL : X86::AL,
+ X86::R8RegisterClass);
+ Loc.first.Kind = FALocInfo::LiveInRegLoc;
+ Loc.first.Loc = Reg;
+ Loc.first.Typ = MVT::i8;
+ break;
+ case MVT::i16:
+ Reg = AddLiveIn(MF, NumIntRegs ? X86::DX : X86::AX,
+ X86::R16RegisterClass);
+ Loc.first.Kind = FALocInfo::LiveInRegLoc;
+ Loc.first.Loc = Reg;
+ Loc.first.Typ = MVT::i16;
+ break;
+ case MVT::i32:
+ Reg = AddLiveIn(MF, NumIntRegs ? X86::EDX : X86::EAX,
+ X86::R32RegisterClass);
+ Loc.first.Kind = FALocInfo::LiveInRegLoc;
+ Loc.first.Loc = Reg;
+ Loc.first.Typ = MVT::i32;
+ break;
+ case MVT::i64:
+ Reg = AddLiveIn(MF, NumIntRegs ? X86::EDX : X86::EAX,
+ X86::R32RegisterClass);
+ Loc.first.Kind = FALocInfo::LiveInRegLoc;
+ Loc.first.Loc = Reg;
+ Loc.first.Typ = MVT::i32;
+ if (ObjIntRegs == 2) {
+ Reg = AddLiveIn(MF, X86::EDX, X86::R32RegisterClass);
+ Loc.second.Kind = FALocInfo::LiveInRegLoc;
+ Loc.second.Loc = Reg;
+ Loc.second.Typ = MVT::i32;
+ }
+ break;
+ case MVT::v16i8:
+ case MVT::v8i16:
+ case MVT::v4i32:
+ case MVT::v2i64:
+ case MVT::v4f32:
+ case MVT::v2f64:
+ Reg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs], X86::VR128RegisterClass);
+ Loc.first.Kind = FALocInfo::LiveInRegLoc;
+ Loc.first.Loc = Reg;
+ Loc.first.Typ = ObjectVT;
+ break;
+ }
+ NumIntRegs += ObjIntRegs;
+ NumXMMRegs += ObjXMMRegs;
}
- ObjSize = 4;
- break;
- case MVT::i64:
- if (NumIntRegs+2 <= FASTCC_NUM_INT_ARGS_INREGS) {
- NumIntRegs += 2;
- break;
- } else if (NumIntRegs+1 <= FASTCC_NUM_INT_ARGS_INREGS) {
- ArgOffset += 4;
- NumIntRegs = FASTCC_NUM_INT_ARGS_INREGS;
- break;
+ if (ObjSize) {
+ int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
+ if (ObjectVT == MVT::i64 && ObjIntRegs) {
+ Loc.second.Kind = FALocInfo::StackFrameLoc;
+ Loc.second.Loc = FI;
+ } else {
+ Loc.first.Kind = FALocInfo::StackFrameLoc;
+ Loc.first.Loc = FI;
+ }
+ ArgOffset += ArgIncrement; // Move on to the next argument.
}
- ObjSize = ArgIncrement = 8;
- break;
- case MVT::f32: ObjSize = 4; break;
- case MVT::f64: ObjSize = ArgIncrement = 8; break;
- }
- if (ObjSize)
- ArgOffset += ArgIncrement; // Move on to the next argument.
+ FormalArgLocs.push_back(Loc);
+ }
}
// Make sure the instruction takes 8n+4 bytes to make sure the start of the
case MVT::f64:
MF.addLiveOut(X86::ST0);
break;
+ case MVT::Vector: {
+ const PackedType *PTy = cast<PackedType>(F.getReturnType());
+ MVT::ValueType EVT;
+ MVT::ValueType LVT;
+ unsigned NumRegs = getPackedTypeBreakdown(PTy, EVT, LVT);
+ assert(NumRegs == 1 && "Unsupported type!");
+ MF.addLiveOut(X86::XMM0);
+ break;
+ }
}
}
+
void
X86TargetLowering::LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG) {
- unsigned NumArgs = Op.Val->getNumValues();
+ unsigned NumArgs = Op.Val->getNumValues()-1;
MachineFunction &MF = DAG.getMachineFunction();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- // Add DAG nodes to load the arguments... On entry to a function the stack
- // frame looks like this:
- //
- // [ESP] -- return address
- // [ESP + 4] -- first nonreg argument (leftmost lexically)
- // [ESP + 8] -- second nonreg argument, if first argument is 4 bytes in size
- // ...
- unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot
-
- // Keep track of the number of integer regs passed so far. This can be either
- // 0 (neither EAX or EDX used), 1 (EAX is used) or 2 (EAX and EDX are both
- // used).
- unsigned NumIntRegs = 0;
-
for (unsigned i = 0; i < NumArgs; ++i) {
- MVT::ValueType ObjectVT = Op.Val->getValueType(i);
- unsigned ArgIncrement = 4;
- unsigned ObjSize = 0;
+ MVT::ValueType VT = Op.Val->getValueType(i);
+ std::pair<FALocInfo, FALocInfo> Loc = FormalArgLocs[i];
SDOperand ArgValue;
- bool hasUse = !Op.Val->hasNUsesOfValue(0, i);
-
- switch (ObjectVT) {
- default: assert(0 && "Unhandled argument type!");
- case MVT::i1:
- case MVT::i8:
- if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS) {
- if (hasUse) {
- unsigned VReg = AddLiveIn(MF, NumIntRegs ? X86::DL : X86::AL,
- X86::R8RegisterClass);
- ArgValue = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i8);
- DAG.setRoot(ArgValue.getValue(1));
- if (ObjectVT == MVT::i1)
- // FIXME: Should insert a assertzext here.
- ArgValue = DAG.getNode(ISD::TRUNCATE, MVT::i1, ArgValue);
- }
- ++NumIntRegs;
- break;
- }
-
- ObjSize = 1;
- break;
- case MVT::i16:
- if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS) {
- if (hasUse) {
- unsigned VReg = AddLiveIn(MF, NumIntRegs ? X86::DX : X86::AX,
- X86::R16RegisterClass);
- ArgValue = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i16);
- DAG.setRoot(ArgValue.getValue(1));
- }
- ++NumIntRegs;
- break;
- }
- ObjSize = 2;
- break;
- case MVT::i32:
- if (NumIntRegs < FASTCC_NUM_INT_ARGS_INREGS) {
- if (hasUse) {
- unsigned VReg = AddLiveIn(MF, NumIntRegs ? X86::EDX : X86::EAX,
- X86::R32RegisterClass);
- ArgValue = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
- DAG.setRoot(ArgValue.getValue(1));
- }
- ++NumIntRegs;
- break;
- }
- ObjSize = 4;
- break;
- case MVT::i64:
- if (NumIntRegs+2 <= FASTCC_NUM_INT_ARGS_INREGS) {
- if (hasUse) {
- unsigned BotReg = AddLiveIn(MF, X86::EAX, X86::R32RegisterClass);
- unsigned TopReg = AddLiveIn(MF, X86::EDX, X86::R32RegisterClass);
-
- SDOperand Low = DAG.getCopyFromReg(DAG.getRoot(), BotReg, MVT::i32);
- SDOperand Hi = DAG.getCopyFromReg(Low.getValue(1), TopReg, MVT::i32);
- DAG.setRoot(Hi.getValue(1));
-
- ArgValue = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Low, Hi);
- }
- NumIntRegs += 2;
- break;
- } else if (NumIntRegs+1 <= FASTCC_NUM_INT_ARGS_INREGS) {
- if (hasUse) {
- unsigned BotReg = AddLiveIn(MF, X86::EDX, X86::R32RegisterClass);
- SDOperand Low = DAG.getCopyFromReg(DAG.getRoot(), BotReg, MVT::i32);
- DAG.setRoot(Low.getValue(1));
-
- // Load the high part from memory.
- // Create the frame index object for this incoming parameter...
- int FI = MFI->CreateFixedObject(4, ArgOffset);
- SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
- SDOperand Hi = DAG.getLoad(MVT::i32, DAG.getEntryNode(), FIN,
- DAG.getSrcValue(NULL));
- ArgValue = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Low, Hi);
- }
- ArgOffset += 4;
- NumIntRegs = FASTCC_NUM_INT_ARGS_INREGS;
- break;
- }
- ObjSize = ArgIncrement = 8;
- break;
- case MVT::f32: ObjSize = 4; break;
- case MVT::f64: ObjSize = ArgIncrement = 8; break;
- }
-
- if (ObjSize) {
- // Create the frame index object for this incoming parameter...
- int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
-
+ if (Loc.first.Kind == FALocInfo::StackFrameLoc) {
// Create the SelectionDAG nodes corresponding to a load from this
// parameter.
- SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
-
- ArgValue = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN,
+ SDOperand FIN = DAG.getFrameIndex(Loc.first.Loc, MVT::i32);
+ ArgValue = DAG.getLoad(Op.Val->getValueType(i), DAG.getEntryNode(), FIN,
DAG.getSrcValue(NULL));
- } else if (ArgValue.Val == 0) {
- if (MVT::isInteger(ObjectVT))
- ArgValue = DAG.getConstant(0, ObjectVT);
- else
- ArgValue = DAG.getConstantFP(0, ObjectVT);
+ } else {
+ // Must be a CopyFromReg
+ ArgValue= DAG.getCopyFromReg(DAG.getEntryNode(), Loc.first.Loc,
+ Loc.first.Typ);
+ }
+
+ if (Loc.second.Kind != FALocInfo::None) {
+ SDOperand ArgValue2;
+ if (Loc.second.Kind == FALocInfo::StackFrameLoc) {
+ // Create the SelectionDAG nodes corresponding to a load from this
+ // parameter.
+ SDOperand FIN = DAG.getFrameIndex(Loc.second.Loc, MVT::i32);
+ ArgValue2 = DAG.getLoad(Op.Val->getValueType(i), DAG.getEntryNode(),
+ FIN, DAG.getSrcValue(NULL));
+ } else {
+ // Must be a CopyFromReg
+ ArgValue2 = DAG.getCopyFromReg(DAG.getEntryNode(),
+ Loc.second.Loc, Loc.second.Typ);
+ }
+ ArgValue = DAG.getNode(ISD::BUILD_PAIR, VT, ArgValue, ArgValue2);
}
FormalArgs.push_back(ArgValue);
}
Ops.push_back(InFlag);
// FIXME: Do not generate X86ISD::TAILCALL for now.
- Chain = DAG.getNode(X86ISD::CALL, NodeTys, Ops);
+ Chain = DAG.getNode(isTailCall ? X86ISD::TAILCALL : X86ISD::CALL,
+ NodeTys, Ops);
InFlag = Chain.getValue(1);
NodeTys.clear();
}
if (NumElems == 4) {
- // Break it into (shuffle shuffle_hi, shuffle_lo).
MVT::ValueType MaskVT = PermMask.getValueType();
MVT::ValueType MaskEVT = MVT::getVectorBaseType(MaskVT);
- std::map<unsigned, std::pair<int, int> > Locs;
+ std::vector<std::pair<int, int> > Locs;
+ Locs.reserve(NumElems);
+ std::vector<SDOperand> Mask1(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT));
+ std::vector<SDOperand> Mask2(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT));
+ unsigned NumHi = 0;
+ unsigned NumLo = 0;
+ // If no more than two elements come from either vector. This can be
+ // implemented with two shuffles. First shuffle gather the elements.
+ // The second shuffle, which takes the first shuffle as both of its
+ // vector operands, put the elements into the right order.
+ for (unsigned i = 0; i != NumElems; ++i) {
+ SDOperand Elt = PermMask.getOperand(i);
+ if (Elt.getOpcode() == ISD::UNDEF) {
+ Locs[i] = std::make_pair(-1, -1);
+ } else {
+ unsigned Val = cast<ConstantSDNode>(Elt)->getValue();
+ if (Val < NumElems) {
+ Locs[i] = std::make_pair(0, NumLo);
+ Mask1[NumLo] = Elt;
+ NumLo++;
+ } else {
+ Locs[i] = std::make_pair(1, NumHi);
+ if (2+NumHi < NumElems)
+ Mask1[2+NumHi] = Elt;
+ NumHi++;
+ }
+ }
+ }
+ if (NumLo <= 2 && NumHi <= 2) {
+ V1 = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
+ DAG.getNode(ISD::BUILD_VECTOR, MaskVT, Mask1));
+ for (unsigned i = 0; i != NumElems; ++i) {
+ if (Locs[i].first == -1)
+ continue;
+ else {
+ unsigned Idx = (i < NumElems/2) ? 0 : NumElems;
+ Idx += Locs[i].first * (NumElems/2) + Locs[i].second;
+ Mask2[i] = DAG.getConstant(Idx, MaskEVT);
+ }
+ }
+
+ return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V1,
+ DAG.getNode(ISD::BUILD_VECTOR, MaskVT, Mask2));
+ }
+
+ // Break it into (shuffle shuffle_hi, shuffle_lo).
+ Locs.clear();
std::vector<SDOperand> LoMask(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT));
std::vector<SDOperand> HiMask(NumElems, DAG.getNode(ISD::UNDEF, MaskEVT));
std::vector<SDOperand> *MaskPtr = &LoMask;
}
}
- SDOperand LoShuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
- DAG.getNode(ISD::BUILD_VECTOR, MaskVT, LoMask));
- SDOperand HiShuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
- DAG.getNode(ISD::BUILD_VECTOR, MaskVT, HiMask));
+ SDOperand LoShuffle =
+ DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
+ DAG.getNode(ISD::BUILD_VECTOR, MaskVT, LoMask));
+ SDOperand HiShuffle =
+ DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V2,
+ DAG.getNode(ISD::BUILD_VECTOR, MaskVT, HiMask));
std::vector<SDOperand> MaskOps;
for (unsigned i = 0; i != NumElems; ++i) {
if (Locs[i].first == -1) {
X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
SDOperand Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(),
- DAG.getTargetGlobalAddress(GV, getPointerTy()));
+ DAG.getTargetGlobalAddress(GV,
+ getPointerTy()));
if (Subtarget->isTargetDarwin()) {
// With PIC, the address is actually $g + Offset.
if (getTargetMachine().getRelocationModel() == Reloc::PIC)
Result = DAG.getNode(ISD::ADD, getPointerTy(),
- DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Result);
+ DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()),
+ Result);
// For Darwin, external and weak symbols are indirect, so we want to load
// the value at address GV, not the value of GV itself. This means that
X86TargetLowering::LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
SDOperand Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(),
- DAG.getTargetExternalSymbol(Sym, getPointerTy()));
+ DAG.getTargetExternalSymbol(Sym,
+ getPointerTy()));
if (Subtarget->isTargetDarwin()) {
// With PIC, the address is actually $g + Offset.
if (getTargetMachine().getRelocationModel() == Reloc::PIC)
Result = DAG.getNode(ISD::ADD, getPointerTy(),
- DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Result);
+ DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()),
+ Result);
}
return Result;
// With PIC, the address is actually $g + Offset.
if (getTargetMachine().getRelocationModel() == Reloc::PIC)
Result = DAG.getNode(ISD::ADD, getPointerTy(),
- DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Result);
+ DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()),
+ Result);
}
return Result;
SDOperand
X86TargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) {
if (FormalArgs.size() == 0) {
- unsigned CC = cast<ConstantSDNode>(Op.getOperand(0))->getValue();
+ unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
if (CC == CallingConv::Fast && EnableFastCC)
LowerFastCCArguments(Op, DAG);
else
if ((Align & 3) != 0 ||
(I && I->getValue() < Subtarget->getMinRepStrSizeThreshold())) {
MVT::ValueType IntPtr = getPointerTy();
- const Type *IntPtrTy = getTargetData().getIntPtrType();
+ const Type *IntPtrTy = getTargetData()->getIntPtrType();
std::vector<std::pair<SDOperand, const Type*> > Args;
Args.push_back(std::make_pair(Op.getOperand(1), IntPtrTy));
// Extend the ubyte argument to be an int value for the call.
if ((Align & 3) != 0 ||
(I && I->getValue() < Subtarget->getMinRepStrSizeThreshold())) {
MVT::ValueType IntPtr = getPointerTy();
- const Type *IntPtrTy = getTargetData().getIntPtrType();
+ const Type *IntPtrTy = getTargetData()->getIntPtrType();
std::vector<std::pair<SDOperand, const Type*> > Args;
Args.push_back(std::make_pair(Op.getOperand(1), IntPtrTy));
Args.push_back(std::make_pair(Op.getOperand(2), IntPtrTy));
default: break; // Unknown constriant letter
case 'r': // GENERAL_REGS
case 'R': // LEGACY_REGS
- return make_vector<unsigned>(X86::EAX, X86::EBX, X86::ECX, X86::EDX,
- X86::ESI, X86::EDI, X86::EBP, X86::ESP, 0);
+ if (VT == MVT::i32)
+ return make_vector<unsigned>(X86::EAX, X86::EDX, X86::ECX, X86::EBX,
+ X86::ESI, X86::EDI, X86::EBP, X86::ESP, 0);
+ else if (VT == MVT::i16)
+ return make_vector<unsigned>(X86::AX, X86::DX, X86::CX, X86::BX,
+ X86::SI, X86::DI, X86::BP, X86::SP, 0);
+ else if (VT == MVT::i8)
+ return make_vector<unsigned>(X86::AL, X86::DL, X86::CL, X86::DL, 0);
+ break;
case 'l': // INDEX_REGS
- return make_vector<unsigned>(X86::EAX, X86::EBX, X86::ECX, X86::EDX,
- X86::ESI, X86::EDI, X86::EBP, 0);
+ if (VT == MVT::i32)
+ return make_vector<unsigned>(X86::EAX, X86::EDX, X86::ECX, X86::EBX,
+ X86::ESI, X86::EDI, X86::EBP, 0);
+ else if (VT == MVT::i16)
+ return make_vector<unsigned>(X86::AX, X86::DX, X86::CX, X86::BX,
+ X86::SI, X86::DI, X86::BP, 0);
+ else if (VT == MVT::i8)
+ return make_vector<unsigned>(X86::AL, X86::DL, X86::CL, X86::DL, 0);
+ break;
case 'q': // Q_REGS (GENERAL_REGS in 64-bit mode)
case 'Q': // Q_REGS
- return make_vector<unsigned>(X86::EAX, X86::EBX, X86::ECX, X86::EDX, 0);
+ if (VT == MVT::i32)
+ return make_vector<unsigned>(X86::EAX, X86::EDX, X86::ECX, X86::EBX, 0);
+ else if (VT == MVT::i16)
+ return make_vector<unsigned>(X86::AX, X86::DX, X86::CX, X86::BX, 0);
+ else if (VT == MVT::i8)
+ return make_vector<unsigned>(X86::AL, X86::DL, X86::CL, X86::DL, 0);
+ break;
case 'x': // SSE_REGS if SSE1 allowed
if (Subtarget->hasSSE1())
return make_vector<unsigned>(X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,