#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"
addLegalAddressScale(3);
// Set up the register classes.
- addRegisterClass(MVT::i8, X86::R8RegisterClass);
- addRegisterClass(MVT::i16, X86::R16RegisterClass);
- addRegisterClass(MVT::i32, X86::R32RegisterClass);
+ addRegisterClass(MVT::i8, X86::GR8RegisterClass);
+ addRegisterClass(MVT::i16, X86::GR16RegisterClass);
+ addRegisterClass(MVT::i32, X86::GR32RegisterClass);
// Promote all UINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have this
// operation.
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);
FormalArgs.clear();
FormalArgLocs.clear();
- // This sets BytesToPopOnReturn, BytesCallerReserves, etc. which have to be set
- // before the rest of the function can be lowered.
+ // 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, F, DAG);
else
return VReg;
}
-/// getFormalArgSize - Return the minimum size of the stack frame needed to store
-/// an object of the specified type.
-static unsigned getFormalArgSize(MVT::ValueType ObjectVT) {
- unsigned ObjSize = 0;
+/// 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::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;
}
- return ObjSize;
}
/// getFormalArgObjects - Returns itself if Op is a FORMAL_ARGUMENTS, otherwise
assert(Op.getOpcode() == ISD::AssertSext ||
Op.getOpcode() == ISD::AssertZext);
Objs.push_back(Op.getOperand(0));
- } else if (Opc == ISD::FP_ROUND) {
+ } 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));
// ...
//
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) {
SDOperand Op = Args[i];
std::vector<SDOperand> Objs = getFormalArgObjects(Op);
SDOperand Obj = *I;
MVT::ValueType ObjectVT = Obj.getValueType();
unsigned ArgIncrement = 4;
- unsigned ObjSize = getFormalArgSize(ObjectVT);
- if (ObjSize == 8)
- ArgIncrement = 8;
-
- // 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...
+ 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...
+ }
}
}
}
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();
for (unsigned i = 0; i < NumArgs; ++i) {
- // Create the SelectionDAG nodes corresponding to a load from this parameter
- unsigned FI = FormalArgLocs[i].first.Loc;
- SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
- SDOperand ArgValue = DAG.getLoad(Op.Val->getValueType(i),DAG.getEntryNode(),
- FIN, DAG.getSrcValue(NULL));
+ 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);
+ }
FormalArgs.push_back(ArgValue);
}
+ // Provide a chain. Note that this isn't the right one, but it works as well
+ // as before.
+ FormalArgs.push_back(DAG.getEntryNode());
}
std::pair<SDOperand, SDOperand>
// 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;
+ }
}
}
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 &ObjSize, unsigned &ObjIntRegs) {
+HowToPassFastCCArgument(MVT::ValueType ObjectVT,
+ unsigned NumIntRegs, unsigned NumXMMRegs,
+ unsigned &ObjSize, unsigned &ObjIntRegs,
+ unsigned &ObjXMMRegs) {
ObjSize = 0;
NumIntRegs = 0;
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;
}
}
// 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) {
SDOperand Op = Args[i];
unsigned ArgIncrement = 4;
unsigned ObjSize = 0;
unsigned ObjIntRegs = 0;
+ unsigned ObjXMMRegs = 0;
- HowToPassFastCCArgument(ObjectVT, NumIntRegs, ObjSize, ObjIntRegs);
- if (ObjSize == 8)
- ArgIncrement = 8;
+ 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) {
- NumIntRegs += 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);
+ X86::GR8RegisterClass);
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);
+ X86::GR16RegisterClass);
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);
+ X86::GR32RegisterClass);
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);
+ X86::GR32RegisterClass);
Loc.first.Kind = FALocInfo::LiveInRegLoc;
Loc.first.Loc = Reg;
Loc.first.Typ = MVT::i32;
if (ObjIntRegs == 2) {
- Reg = AddLiveIn(MF, X86::EDX, X86::R32RegisterClass);
+ Reg = AddLiveIn(MF, X86::EDX, X86::GR32RegisterClass);
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;
}
if (ObjSize) {
int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
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();
for (unsigned i = 0; i < NumArgs; ++i) {
MVT::ValueType VT = Op.Val->getValueType(i);
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
+ // Create the SelectionDAG nodes corresponding to a load from this
+ // parameter.
SDOperand FIN = DAG.getFrameIndex(Loc.first.Loc, MVT::i32);
- ArgValue = DAG.getLoad(Op.Val->getValueType(i),DAG.getEntryNode(), FIN,
+ ArgValue = DAG.getLoad(Op.Val->getValueType(i), DAG.getEntryNode(), FIN,
DAG.getSrcValue(NULL));
} else {
// Must be a CopyFromReg
- ArgValue= DAG.getCopyFromReg(DAG.getRoot(), Loc.first.Loc, Loc.first.Typ);
+ 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
+ // 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));
+ ArgValue2 = DAG.getLoad(Op.Val->getValueType(i), DAG.getEntryNode(),
+ FIN, DAG.getSrcValue(NULL));
} else {
// Must be a CopyFromReg
- ArgValue2 = DAG.getCopyFromReg(DAG.getRoot(),
+ ArgValue2 = DAG.getCopyFromReg(DAG.getEntryNode(),
Loc.second.Loc, Loc.second.Typ);
}
ArgValue = DAG.getNode(ISD::BUILD_PAIR, VT, ArgValue, ArgValue2);
}
FormalArgs.push_back(ArgValue);
}
+
+ // Provide a chain. Note that this isn't the right one, but it works as well
+ // as before.
+ FormalArgs.push_back(DAG.getEntryNode());
}
std::pair<SDOperand, SDOperand>
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();
// Load the old value of the high byte of the control word...
unsigned OldCW =
- F->getSSARegMap()->createVirtualRegister(X86::R16RegisterClass);
+ F->getSSARegMap()->createVirtualRegister(X86::GR16RegisterClass);
addFrameReference(BuildMI(BB, X86::MOV16rm, 4, OldCW), CWFrameIdx);
// Set the high part to be round to zero...
}
}
- // Take advantage of the fact R32 to VR128 scalar_to_vector (i.e. movd)
+ // Take advantage of the fact GR32 to VR128 scalar_to_vector (i.e. movd)
// clears the upper bits.
// FIXME: we can do the same for v4f32 case when we know both parts of
// the lower half come from scalar_to_vector (loadf32). We should do
}
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) {
SDOperand
X86TargetLowering::LowerINSERT_VECTOR_ELT(SDOperand Op, SelectionDAG &DAG) {
- // Transform it so it match pinsrw which expects a 16-bit value in a R32
+ // Transform it so it match pinsrw which expects a 16-bit value in a GR32
// as its second argument.
MVT::ValueType VT = Op.getValueType();
MVT::ValueType BaseVT = MVT::getVectorBaseType(VT);
Idx <<= 1;
if (MVT::isFloatingPoint(N1.getValueType())) {
if (N1.getOpcode() == ISD::LOAD) {
- // Just load directly from f32mem to R32.
+ // Just load directly from f32mem to GR32.
N1 = DAG.getLoad(MVT::i32, N1.getOperand(0), N1.getOperand(1),
N1.getOperand(2));
} else {
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
LowerCCCArguments(Op, DAG);
}
- return FormalArgs[Op.ResNo];
+
+ // Return the new list of results.
+ std::vector<MVT::ValueType> RetVTs(Op.Val->value_begin(),
+ Op.Val->value_end());
+ return DAG.getNode(ISD::MERGE_VALUES, RetVTs, FormalArgs);
}
SDOperand X86TargetLowering::LowerMEMSET(SDOperand Op, SelectionDAG &DAG) {
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,