mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-22 13:29:44 +00:00
Change a whole bunch of code to be built around RegsForValue instead of
a single register number. This fully implements promotion for inline asms, expand is close but not quite right yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26316 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4c1aa86657
commit
864635ad7b
@ -78,6 +78,43 @@ namespace {
|
|||||||
clEnumValEnd));
|
clEnumValEnd));
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/// RegsForValue - This struct represents the physical registers that a
|
||||||
|
/// particular value is assigned and the type information about the value.
|
||||||
|
/// This is needed because values can be promoted into larger registers and
|
||||||
|
/// expanded into multiple smaller registers than the value.
|
||||||
|
struct RegsForValue {
|
||||||
|
/// Regs - This list hold the register (for legal and promoted values)
|
||||||
|
/// or register set (for expanded values) that the value should be assigned
|
||||||
|
/// to.
|
||||||
|
std::vector<unsigned> Regs;
|
||||||
|
|
||||||
|
/// RegVT - The value type of each register.
|
||||||
|
///
|
||||||
|
MVT::ValueType RegVT;
|
||||||
|
|
||||||
|
/// ValueVT - The value type of the LLVM value, which may be promoted from
|
||||||
|
/// RegVT or made from merging the two expanded parts.
|
||||||
|
MVT::ValueType ValueVT;
|
||||||
|
|
||||||
|
RegsForValue() : RegVT(MVT::Other), ValueVT(MVT::Other) {}
|
||||||
|
|
||||||
|
RegsForValue(unsigned Reg, MVT::ValueType regvt, MVT::ValueType valuevt)
|
||||||
|
: RegVT(regvt), ValueVT(valuevt) {
|
||||||
|
Regs.push_back(Reg);
|
||||||
|
}
|
||||||
|
RegsForValue(const std::vector<unsigned> ®s,
|
||||||
|
MVT::ValueType regvt, MVT::ValueType valuevt)
|
||||||
|
: Regs(regs), RegVT(regvt), ValueVT(valuevt) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from
|
||||||
|
/// this value and returns the result as a ValueVT value. This uses
|
||||||
|
/// Chain/Flag as the input and updates them for the output Chain/Flag.
|
||||||
|
SDOperand getCopyFromRegs(SelectionDAG &DAG,
|
||||||
|
SDOperand &Chain, SDOperand &Flag);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
@ -120,7 +157,7 @@ namespace llvm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If this value is represented with multiple target registers, make sure
|
// If this value is represented with multiple target registers, make sure
|
||||||
// to create enough consequtive registers of the right (smaller) type.
|
// to create enough consecutive registers of the right (smaller) type.
|
||||||
unsigned NT = VT-1; // Find the type to use.
|
unsigned NT = VT-1; // Find the type to use.
|
||||||
while (TLI.getNumElements((MVT::ValueType)NT) != 1)
|
while (TLI.getNumElements((MVT::ValueType)NT) != 1)
|
||||||
--NT;
|
--NT;
|
||||||
@ -412,8 +449,9 @@ public:
|
|||||||
return N = NewN;
|
return N = NewN;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetAvailableRegister(bool OutReg, bool InReg,
|
RegsForValue GetRegistersForValue(const std::string &ConstrCode,
|
||||||
const std::vector<unsigned> &RegChoices,
|
MVT::ValueType VT,
|
||||||
|
bool OutReg, bool InReg,
|
||||||
std::set<unsigned> &OutputRegs,
|
std::set<unsigned> &OutputRegs,
|
||||||
std::set<unsigned> &InputRegs);
|
std::set<unsigned> &InputRegs);
|
||||||
|
|
||||||
@ -1130,49 +1168,145 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
|
|||||||
DAG.setRoot(Result.second);
|
DAG.setRoot(Result.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GetAvailableRegister - Pick a register from RegChoices that is available
|
SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
|
||||||
/// for input and/or output as specified by isOutReg/isInReg. If an allocatable
|
SDOperand &Chain, SDOperand &Flag) {
|
||||||
/// register is found, it is returned and added to the specified set of used
|
SDOperand Val = DAG.getCopyFromReg(Chain, Regs[0], RegVT, Flag);
|
||||||
/// registers. If not, zero is returned.
|
Chain = Val.getValue(1);
|
||||||
unsigned SelectionDAGLowering::
|
Flag = Val.getValue(2);
|
||||||
GetAvailableRegister(bool isOutReg, bool isInReg,
|
|
||||||
const std::vector<unsigned> &RegChoices,
|
|
||||||
std::set<unsigned> &OutputRegs,
|
|
||||||
std::set<unsigned> &InputRegs) {
|
|
||||||
const MRegisterInfo *MRI = DAG.getTarget().getRegisterInfo();
|
|
||||||
MachineFunction &MF = *CurMBB->getParent();
|
|
||||||
for (unsigned i = 0, e = RegChoices.size(); i != e; ++i) {
|
|
||||||
unsigned Reg = RegChoices[i];
|
|
||||||
// See if this register is available.
|
|
||||||
if (isOutReg && OutputRegs.count(Reg)) continue; // Already used.
|
|
||||||
if (isInReg && InputRegs.count(Reg)) continue; // Already used.
|
|
||||||
|
|
||||||
// Check to see if this register is allocatable (i.e. don't give out the
|
// If the result was expanded, copy from the top part.
|
||||||
// stack pointer).
|
if (Regs.size() > 1) {
|
||||||
bool Found = false;
|
assert(Regs.size() == 2 &&
|
||||||
|
"Cannot expand to more than 2 elts yet!");
|
||||||
|
SDOperand Hi = DAG.getCopyFromReg(Chain, Regs[1], RegVT, Flag);
|
||||||
|
Chain = Val.getValue(1);
|
||||||
|
Flag = Val.getValue(2);
|
||||||
|
return DAG.getNode(ISD::MERGE_VALUES, ValueVT, Val, Hi);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, if the return value was promoted, truncate it to the
|
||||||
|
// appropriate type.
|
||||||
|
if (RegVT == ValueVT)
|
||||||
|
return Val;
|
||||||
|
|
||||||
|
if (MVT::isInteger(RegVT))
|
||||||
|
return DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
|
||||||
|
else
|
||||||
|
return DAG.getNode(ISD::FP_ROUND, ValueVT, Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// isAllocatableRegister - If the specified register is safe to allocate,
|
||||||
|
/// i.e. it isn't a stack pointer or some other special register, return the
|
||||||
|
/// register class for the register. Otherwise, return null.
|
||||||
|
static const TargetRegisterClass *
|
||||||
|
isAllocatableRegister(unsigned Reg, MachineFunction &MF,
|
||||||
|
const MRegisterInfo *MRI) {
|
||||||
for (MRegisterInfo::regclass_iterator RC = MRI->regclass_begin(),
|
for (MRegisterInfo::regclass_iterator RC = MRI->regclass_begin(),
|
||||||
E = MRI->regclass_end(); !Found && RC != E; ++RC) {
|
E = MRI->regclass_end(); RC != E; ++RC) {
|
||||||
// NOTE: This isn't ideal. In particular, this might allocate the
|
// NOTE: This isn't ideal. In particular, this might allocate the
|
||||||
// frame pointer in functions that need it (due to them not being taken
|
// frame pointer in functions that need it (due to them not being taken
|
||||||
// out of allocation, because a variable sized allocation hasn't been seen
|
// out of allocation, because a variable sized allocation hasn't been seen
|
||||||
// yet). This is a slight code pessimization, but should still work.
|
// yet). This is a slight code pessimization, but should still work.
|
||||||
for (TargetRegisterClass::iterator I = (*RC)->allocation_order_begin(MF),
|
for (TargetRegisterClass::iterator I = (*RC)->allocation_order_begin(MF),
|
||||||
E = (*RC)->allocation_order_end(MF); I != E; ++I)
|
E = (*RC)->allocation_order_end(MF); I != E; ++I)
|
||||||
if (*I == Reg) {
|
if (*I == Reg)
|
||||||
Found = true;
|
return *RC;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!Found) continue;
|
|
||||||
|
|
||||||
// Okay, this register is good, return it.
|
|
||||||
if (isOutReg) OutputRegs.insert(Reg); // Mark used.
|
|
||||||
if (isInReg) InputRegs.insert(Reg); // Mark used.
|
|
||||||
return Reg;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegsForValue SelectionDAGLowering::
|
||||||
|
GetRegistersForValue(const std::string &ConstrCode,
|
||||||
|
MVT::ValueType VT, bool isOutReg, bool isInReg,
|
||||||
|
std::set<unsigned> &OutputRegs,
|
||||||
|
std::set<unsigned> &InputRegs) {
|
||||||
|
std::pair<unsigned, const TargetRegisterClass*> PhysReg =
|
||||||
|
TLI.getRegForInlineAsmConstraint(ConstrCode, VT);
|
||||||
|
std::vector<unsigned> Regs;
|
||||||
|
|
||||||
|
unsigned NumRegs = VT != MVT::Other ? TLI.getNumElements(VT) : 1;
|
||||||
|
MVT::ValueType RegVT;
|
||||||
|
MVT::ValueType ValueVT = VT;
|
||||||
|
|
||||||
|
if (PhysReg.first) {
|
||||||
|
if (VT == MVT::Other)
|
||||||
|
ValueVT = *PhysReg.second->vt_begin();
|
||||||
|
RegVT = VT;
|
||||||
|
|
||||||
|
// This is a explicit reference to a physical register.
|
||||||
|
Regs.push_back(PhysReg.first);
|
||||||
|
|
||||||
|
// If this is an expanded reference, add the rest of the regs to Regs.
|
||||||
|
if (NumRegs != 1) {
|
||||||
|
RegVT = *PhysReg.second->vt_begin();
|
||||||
|
TargetRegisterClass::iterator I = PhysReg.second->begin();
|
||||||
|
TargetRegisterClass::iterator E = PhysReg.second->end();
|
||||||
|
for (; *I != PhysReg.first; ++I)
|
||||||
|
assert(I != E && "Didn't find reg!");
|
||||||
|
|
||||||
|
// Already added the first reg.
|
||||||
|
--NumRegs; ++I;
|
||||||
|
for (; NumRegs; --NumRegs, ++I) {
|
||||||
|
assert(I != E && "Ran out of registers to allocate!");
|
||||||
|
Regs.push_back(*I);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return RegsForValue(Regs, RegVT, ValueVT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a reference to a register class. Allocate NumRegs consecutive,
|
||||||
|
// available, registers from the class.
|
||||||
|
std::vector<unsigned> RegClassRegs =
|
||||||
|
TLI.getRegClassForInlineAsmConstraint(ConstrCode, VT);
|
||||||
|
|
||||||
|
const MRegisterInfo *MRI = DAG.getTarget().getRegisterInfo();
|
||||||
|
MachineFunction &MF = *CurMBB->getParent();
|
||||||
|
unsigned NumAllocated = 0;
|
||||||
|
for (unsigned i = 0, e = RegClassRegs.size(); i != e; ++i) {
|
||||||
|
unsigned Reg = RegClassRegs[i];
|
||||||
|
// See if this register is available.
|
||||||
|
if ((isOutReg && OutputRegs.count(Reg)) || // Already used.
|
||||||
|
(isInReg && InputRegs.count(Reg))) { // Already used.
|
||||||
|
// Make sure we find consecutive registers.
|
||||||
|
NumAllocated = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if this register is allocatable (i.e. don't give out the
|
||||||
|
// stack pointer).
|
||||||
|
const TargetRegisterClass *RC = isAllocatableRegister(Reg, MF, MRI);
|
||||||
|
if (!RC) {
|
||||||
|
// Make sure we find consecutive registers.
|
||||||
|
NumAllocated = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Okay, this register is good, we can use it.
|
||||||
|
++NumAllocated;
|
||||||
|
|
||||||
|
// If we allocated enough consecutive
|
||||||
|
if (NumAllocated == NumRegs) {
|
||||||
|
unsigned RegStart = (i-NumAllocated)+1;
|
||||||
|
unsigned RegEnd = i+1;
|
||||||
|
// Mark all of the allocated registers used.
|
||||||
|
for (unsigned i = RegStart; i != RegEnd; ++i) {
|
||||||
|
unsigned Reg = RegClassRegs[i];
|
||||||
|
Regs.push_back(Reg);
|
||||||
|
if (isOutReg) OutputRegs.insert(Reg); // Mark reg used.
|
||||||
|
if (isInReg) InputRegs.insert(Reg); // Mark reg used.
|
||||||
|
}
|
||||||
|
|
||||||
|
return RegsForValue(Regs, *RC->vt_begin(), VT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we couldn't allocate enough registers for this.
|
||||||
|
return RegsForValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// visitInlineAsm - Handle a call to an InlineAsm object.
|
/// visitInlineAsm - Handle a call to an InlineAsm object.
|
||||||
///
|
///
|
||||||
void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
||||||
@ -1235,39 +1369,40 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
|||||||
|
|
||||||
ConstraintVTs.push_back(OpVT);
|
ConstraintVTs.push_back(OpVT);
|
||||||
|
|
||||||
std::pair<unsigned, const TargetRegisterClass*> Reg =
|
if (TLI.getRegForInlineAsmConstraint(ConstraintCode, OpVT).first == 0)
|
||||||
TLI.getRegForInlineAsmConstraint(ConstraintCode, OpVT);
|
continue; // Not assigned a fixed reg.
|
||||||
if (Reg.first == 0) continue; // Not assigned a fixed reg.
|
|
||||||
unsigned TheReg = Reg.first;
|
|
||||||
|
|
||||||
// FIXME: Handle expanded physreg refs!
|
// Build a list of regs that this operand uses. This always has a single
|
||||||
|
// element for promoted/expanded operands.
|
||||||
|
RegsForValue Regs = GetRegistersForValue(ConstraintCode, OpVT,
|
||||||
|
false, false,
|
||||||
|
OutputRegs, InputRegs);
|
||||||
|
|
||||||
switch (Constraints[i].Type) {
|
switch (Constraints[i].Type) {
|
||||||
case InlineAsm::isOutput:
|
case InlineAsm::isOutput:
|
||||||
// We can't assign any other output to this register.
|
// We can't assign any other output to this register.
|
||||||
OutputRegs.insert(TheReg);
|
OutputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
|
||||||
// If this is an early-clobber output, it cannot be assigned to the same
|
// If this is an early-clobber output, it cannot be assigned to the same
|
||||||
// value as the input reg.
|
// value as the input reg.
|
||||||
if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
|
if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
|
||||||
InputRegs.insert(TheReg);
|
InputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
|
||||||
break;
|
break;
|
||||||
case InlineAsm::isInput:
|
case InlineAsm::isInput:
|
||||||
// We can't assign any other input to this register.
|
// We can't assign any other input to this register.
|
||||||
InputRegs.insert(TheReg);
|
InputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
|
||||||
break;
|
break;
|
||||||
case InlineAsm::isClobber:
|
case InlineAsm::isClobber:
|
||||||
// Clobbered regs cannot be used as inputs or outputs.
|
// Clobbered regs cannot be used as inputs or outputs.
|
||||||
InputRegs.insert(TheReg);
|
InputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
|
||||||
OutputRegs.insert(TheReg);
|
OutputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop over all of the inputs, copying the operand values into the
|
// Loop over all of the inputs, copying the operand values into the
|
||||||
// appropriate registers and processing the output regs.
|
// appropriate registers and processing the output regs.
|
||||||
unsigned RetValReg = 0;
|
RegsForValue RetValRegs;
|
||||||
std::vector<std::pair<unsigned, Value*> > IndirectStoresToEmit;
|
std::vector<std::pair<RegsForValue, Value*> > IndirectStoresToEmit;
|
||||||
bool FoundOutputConstraint = false;
|
|
||||||
OpNum = 1;
|
OpNum = 1;
|
||||||
|
|
||||||
for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
|
||||||
@ -1276,58 +1411,47 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
|||||||
|
|
||||||
switch (Constraints[i].Type) {
|
switch (Constraints[i].Type) {
|
||||||
case InlineAsm::isOutput: {
|
case InlineAsm::isOutput: {
|
||||||
// Copy the output from the appropriate register. Find a regsister that
|
|
||||||
// we can use.
|
|
||||||
|
|
||||||
// Check to see if this is a physreg reference.
|
|
||||||
std::pair<unsigned, const TargetRegisterClass*> PhysReg =
|
|
||||||
TLI.getRegForInlineAsmConstraint(ConstraintCode, ConstraintVTs[i]);
|
|
||||||
unsigned DestReg;
|
|
||||||
if (PhysReg.first)
|
|
||||||
DestReg = PhysReg.first;
|
|
||||||
else {
|
|
||||||
std::vector<unsigned> Regs =
|
|
||||||
TLI.getRegClassForInlineAsmConstraint(ConstraintCode,
|
|
||||||
ConstraintVTs[i]);
|
|
||||||
|
|
||||||
// If this is an early-clobber output, or if there is an input
|
// If this is an early-clobber output, or if there is an input
|
||||||
// constraint that matches this, we need to reserve the input register
|
// constraint that matches this, we need to reserve the input register
|
||||||
// so no other inputs allocate to it.
|
// so no other inputs allocate to it.
|
||||||
bool UsesInputRegister = false;
|
bool UsesInputRegister = false;
|
||||||
if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
|
if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
|
||||||
UsesInputRegister = true;
|
UsesInputRegister = true;
|
||||||
DestReg = GetAvailableRegister(true, UsesInputRegister,
|
|
||||||
Regs, OutputRegs, InputRegs);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(DestReg && "Couldn't allocate output reg!");
|
// Copy the output from the appropriate register. Find a register that
|
||||||
|
// we can use.
|
||||||
|
RegsForValue Regs =
|
||||||
|
GetRegistersForValue(ConstraintCode, ConstraintVTs[i],
|
||||||
|
true, UsesInputRegister,
|
||||||
|
OutputRegs, InputRegs);
|
||||||
|
assert(!Regs.Regs.empty() && "Couldn't allocate output reg!");
|
||||||
|
|
||||||
const Type *OpTy;
|
|
||||||
if (!Constraints[i].isIndirectOutput) {
|
if (!Constraints[i].isIndirectOutput) {
|
||||||
assert(!FoundOutputConstraint &&
|
assert(RetValRegs.Regs.empty() &&
|
||||||
"Cannot have multiple output constraints yet!");
|
"Cannot have multiple output constraints yet!");
|
||||||
FoundOutputConstraint = true;
|
|
||||||
assert(I.getType() != Type::VoidTy && "Bad inline asm!");
|
assert(I.getType() != Type::VoidTy && "Bad inline asm!");
|
||||||
|
RetValRegs = Regs;
|
||||||
RetValReg = DestReg;
|
|
||||||
} else {
|
} else {
|
||||||
Value *CallOperand = I.getOperand(OpNum);
|
Value *CallOperand = I.getOperand(OpNum);
|
||||||
IndirectStoresToEmit.push_back(std::make_pair(DestReg, CallOperand));
|
IndirectStoresToEmit.push_back(std::make_pair(Regs, CallOperand));
|
||||||
OpNum++; // Consumes a call operand.
|
OpNum++; // Consumes a call operand.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add information to the INLINEASM node to know that this register is
|
// Add information to the INLINEASM node to know that this register is
|
||||||
// set.
|
// set.
|
||||||
AsmNodeOperands.push_back(DAG.getRegister(DestReg, ConstraintVTs[i]));
|
|
||||||
AsmNodeOperands.push_back(DAG.getConstant(2, MVT::i32)); // ISDEF
|
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
// FIXME: Handle multiple regs here.
|
||||||
|
// FIXME:
|
||||||
|
unsigned DestReg = Regs.Regs[0];
|
||||||
|
AsmNodeOperands.push_back(DAG.getRegister(DestReg, Regs.RegVT));
|
||||||
|
AsmNodeOperands.push_back(DAG.getConstant(2, MVT::i32)); // ISDEF
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case InlineAsm::isInput: {
|
case InlineAsm::isInput: {
|
||||||
Value *CallOperand = I.getOperand(OpNum);
|
Value *CallOperand = I.getOperand(OpNum);
|
||||||
OpNum++; // Consumes a call operand.
|
OpNum++; // Consumes a call operand.
|
||||||
|
|
||||||
unsigned SrcReg;
|
|
||||||
SDOperand ResOp;
|
SDOperand ResOp;
|
||||||
unsigned ResOpType;
|
unsigned ResOpType;
|
||||||
SDOperand InOperandVal = getValue(CallOperand);
|
SDOperand InOperandVal = getValue(CallOperand);
|
||||||
@ -1336,6 +1460,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
|||||||
// If this is required to match an output register we have already set,
|
// If this is required to match an output register we have already set,
|
||||||
// just use its register.
|
// just use its register.
|
||||||
unsigned OperandNo = atoi(ConstraintCode.c_str());
|
unsigned OperandNo = atoi(ConstraintCode.c_str());
|
||||||
|
unsigned SrcReg;
|
||||||
SrcReg = cast<RegisterSDNode>(AsmNodeOperands[OperandNo*2+2])->getReg();
|
SrcReg = cast<RegisterSDNode>(AsmNodeOperands[OperandNo*2+2])->getReg();
|
||||||
ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
|
ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
|
||||||
ResOpType = 1;
|
ResOpType = 1;
|
||||||
@ -1343,39 +1468,46 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
|||||||
Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
|
Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
|
||||||
Flag = Chain.getValue(1);
|
Flag = Chain.getValue(1);
|
||||||
} else {
|
} else {
|
||||||
TargetLowering::ConstraintType CTy = TargetLowering::C_Register;
|
TargetLowering::ConstraintType CTy = TargetLowering::C_RegisterClass;
|
||||||
if (ConstraintCode.size() == 1) // not a physreg name.
|
if (ConstraintCode.size() == 1) // not a physreg name.
|
||||||
CTy = TLI.getConstraintType(ConstraintCode[0]);
|
CTy = TLI.getConstraintType(ConstraintCode[0]);
|
||||||
|
|
||||||
switch (CTy) {
|
switch (CTy) {
|
||||||
default: assert(0 && "Unknown constraint type! FAIL!");
|
default: assert(0 && "Unknown constraint type! FAIL!");
|
||||||
case TargetLowering::C_Register: {
|
|
||||||
std::pair<unsigned, const TargetRegisterClass*> PhysReg =
|
|
||||||
TLI.getRegForInlineAsmConstraint(ConstraintCode, ConstraintVTs[i]);
|
|
||||||
// FIXME: should be match fail.
|
|
||||||
assert(PhysReg.first && "Unknown physical register name!");
|
|
||||||
SrcReg = PhysReg.first;
|
|
||||||
|
|
||||||
Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
|
|
||||||
Flag = Chain.getValue(1);
|
|
||||||
|
|
||||||
ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
|
|
||||||
ResOpType = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TargetLowering::C_RegisterClass: {
|
case TargetLowering::C_RegisterClass: {
|
||||||
// Copy the input into the appropriate register.
|
// Copy the input into the appropriate registers.
|
||||||
std::vector<unsigned> Regs =
|
RegsForValue InRegs =
|
||||||
TLI.getRegClassForInlineAsmConstraint(ConstraintCode,
|
GetRegistersForValue(ConstraintCode, ConstraintVTs[i],
|
||||||
ConstraintVTs[i]);
|
false, true, OutputRegs, InputRegs);
|
||||||
SrcReg = GetAvailableRegister(false, true, Regs,
|
|
||||||
OutputRegs, InputRegs);
|
|
||||||
// FIXME: should be match fail.
|
// FIXME: should be match fail.
|
||||||
assert(SrcReg && "Wasn't able to allocate register!");
|
assert(!InRegs.Regs.empty() && "Couldn't allocate input reg!");
|
||||||
Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
|
|
||||||
|
if (InRegs.Regs.size() == 1) {
|
||||||
|
// If there is a single register and the types differ, this must be
|
||||||
|
// a promotion.
|
||||||
|
if (InRegs.RegVT != InRegs.ValueVT) {
|
||||||
|
if (MVT::isInteger(InRegs.RegVT))
|
||||||
|
InOperandVal = DAG.getNode(ISD::ANY_EXTEND, InRegs.RegVT,
|
||||||
|
InOperandVal);
|
||||||
|
else
|
||||||
|
InOperandVal = DAG.getNode(ISD::FP_EXTEND, InRegs.RegVT,
|
||||||
|
InOperandVal);
|
||||||
|
}
|
||||||
|
Chain = DAG.getCopyToReg(Chain, InRegs.Regs[0], InOperandVal, Flag);
|
||||||
Flag = Chain.getValue(1);
|
Flag = Chain.getValue(1);
|
||||||
|
|
||||||
ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
|
ResOp = DAG.getRegister(InRegs.Regs[0], InRegs.RegVT);
|
||||||
|
} else {
|
||||||
|
for (unsigned i = 0, e = InRegs.Regs.size(); i != e; ++i) {
|
||||||
|
SDOperand Part = DAG.getNode(ISD::EXTRACT_ELEMENT, InRegs.RegVT,
|
||||||
|
InOperandVal,
|
||||||
|
DAG.getConstant(i, MVT::i32));
|
||||||
|
Chain = DAG.getCopyToReg(Chain, InRegs.Regs[i], Part, Flag);
|
||||||
|
Flag = Chain.getValue(1);
|
||||||
|
}
|
||||||
|
ResOp = DAG.getRegister(InRegs.Regs[0], InRegs.RegVT);
|
||||||
|
}
|
||||||
|
|
||||||
ResOpType = 1;
|
ResOpType = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1411,26 +1543,18 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
|
|||||||
|
|
||||||
// If this asm returns a register value, copy the result from that register
|
// If this asm returns a register value, copy the result from that register
|
||||||
// and set it as the value of the call.
|
// and set it as the value of the call.
|
||||||
if (RetValReg) {
|
if (!RetValRegs.Regs.empty())
|
||||||
SDOperand Val = DAG.getCopyFromReg(Chain, RetValReg,
|
setValue(&I, RetValRegs.getCopyFromRegs(DAG, Chain, Flag));
|
||||||
TLI.getValueType(I.getType()), Flag);
|
|
||||||
Chain = Val.getValue(1);
|
|
||||||
Flag = Val.getValue(2);
|
|
||||||
setValue(&I, Val);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::pair<SDOperand, Value*> > StoresToEmit;
|
std::vector<std::pair<SDOperand, Value*> > StoresToEmit;
|
||||||
|
|
||||||
// Process indirect outputs, first output all of the flagged copies out of
|
// Process indirect outputs, first output all of the flagged copies out of
|
||||||
// physregs.
|
// physregs.
|
||||||
for (unsigned i = 0, e = IndirectStoresToEmit.size(); i != e; ++i) {
|
for (unsigned i = 0, e = IndirectStoresToEmit.size(); i != e; ++i) {
|
||||||
|
RegsForValue &OutRegs = IndirectStoresToEmit[i].first;
|
||||||
Value *Ptr = IndirectStoresToEmit[i].second;
|
Value *Ptr = IndirectStoresToEmit[i].second;
|
||||||
const Type *Ty = cast<PointerType>(Ptr->getType())->getElementType();
|
SDOperand OutVal = OutRegs.getCopyFromRegs(DAG, Chain, Flag);
|
||||||
SDOperand Val = DAG.getCopyFromReg(Chain, IndirectStoresToEmit[i].first,
|
StoresToEmit.push_back(std::make_pair(OutVal, Ptr));
|
||||||
TLI.getValueType(Ty), Flag);
|
|
||||||
Chain = Val.getValue(1);
|
|
||||||
Flag = Val.getValue(2);
|
|
||||||
StoresToEmit.push_back(std::make_pair(Val, Ptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit the non-flagged stores from the physregs.
|
// Emit the non-flagged stores from the physregs.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user