split register class handling from explicit physreg handling.

llvm-svn: 26308
This commit is contained in:
Chris Lattner 2006-02-22 00:56:39 +00:00
parent cd78df1e85
commit 7ad77dfc2a
7 changed files with 124 additions and 63 deletions

View File

@ -481,6 +481,7 @@ public:
//
enum ConstraintType {
C_Register, // Constraint represents a single register.
C_RegisterClass, // Constraint represents one or more registers.
C_Other, // Something else.
C_Unknown // Unsupported constraint.
@ -491,13 +492,22 @@ public:
/// constraint it is for this target.
virtual ConstraintType getConstraintType(char ConstraintLetter) const;
/// getRegForInlineAsmConstraint - Given a constraint letter or register
/// name (e.g. "r" or "edx"), return a list of registers that can be used to
/// satisfy the constraint. This should only be used for physregs and
/// C_RegisterClass constraints.
/// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"),
/// return a list of registers that can be used to satisfy the constraint.
/// This should only be used for C_RegisterClass constraints.
virtual std::vector<unsigned>
getRegForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const;
getRegClassForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const;
/// getRegForInlineAsmConstraint - Given a physical register constraint (e.g.
/// {edx}), return the register number and the register class for the
/// register. This should only be used for C_Register constraints. On error,
/// this returns a register number of 0.
virtual std::pair<unsigned, const TargetRegisterClass*>
getRegForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const;
/// isOperandValidForConstraint - Return true if the specified SDOperand is
/// valid for the specified target constraint letter.

View File

@ -1187,6 +1187,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
bool hasSideEffects = IA->hasSideEffects();
std::vector<InlineAsm::ConstraintInfo> Constraints = IA->ParseConstraints();
std::vector<MVT::ValueType> ConstraintVTs;
/// AsmNodeOperands - A list of pairs. The first element is a register, the
/// second is a bitfield where bit #0 is set if it is a use and bit #1 is set
@ -1203,14 +1204,43 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
// could let the LLVM RA do its thing, but we currently don't. Do a prepass
// over the constraints, collecting fixed registers that we know we can't use.
std::set<unsigned> OutputRegs, InputRegs;
unsigned OpNum = 1;
for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
assert(Constraints[i].Codes.size() == 1 && "Only handles one code so far!");
std::string &ConstraintCode = Constraints[i].Codes[0];
std::vector<unsigned> Regs =
TLI.getRegForInlineAsmConstraint(ConstraintCode, MVT::Other);
if (Regs.size() != 1) continue; // Not assigned a fixed reg.
unsigned TheReg = Regs[0];
MVT::ValueType OpVT;
// Compute the value type for each operand and add it to ConstraintVTs.
switch (Constraints[i].Type) {
case InlineAsm::isOutput:
if (!Constraints[i].isIndirectOutput) {
assert(I.getType() != Type::VoidTy && "Bad inline asm!");
OpVT = TLI.getValueType(I.getType());
} else {
Value *CallOperand = I.getOperand(OpNum);
const Type *OpTy = CallOperand->getType();
OpVT = TLI.getValueType(cast<PointerType>(OpTy)->getElementType());
OpNum++; // Consumes a call operand.
}
break;
case InlineAsm::isInput:
OpVT = TLI.getValueType(I.getOperand(OpNum)->getType());
OpNum++; // Consumes a call operand.
break;
case InlineAsm::isClobber:
OpVT = MVT::Other;
break;
}
ConstraintVTs.push_back(OpVT);
std::pair<unsigned, const TargetRegisterClass*> Reg =
TLI.getRegForInlineAsmConstraint(ConstraintCode, OpVT);
if (Reg.first == 0) continue; // Not assigned a fixed reg.
unsigned TheReg = Reg.first;
// FIXME: Handle expanded physreg refs!
switch (Constraints[i].Type) {
case InlineAsm::isOutput:
@ -1221,15 +1251,15 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
InputRegs.insert(TheReg);
break;
case InlineAsm::isInput:
// We can't assign any other input to this register.
InputRegs.insert(TheReg);
break;
case InlineAsm::isClobber:
// Clobbered regs cannot be used as inputs or outputs.
InputRegs.insert(TheReg);
OutputRegs.insert(TheReg);
break;
case InlineAsm::isInput:
// We can't assign any other input to this register.
InputRegs.insert(TheReg);
break;
}
}
@ -1238,28 +1268,32 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
unsigned RetValReg = 0;
std::vector<std::pair<unsigned, Value*> > IndirectStoresToEmit;
bool FoundOutputConstraint = false;
unsigned OpNum = 1;
OpNum = 1;
for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
assert(Constraints[i].Codes.size() == 1 && "Only handles one code so far!");
std::string &ConstraintCode = Constraints[i].Codes[0];
Value *CallOperand = I.getOperand(OpNum);
MVT::ValueType CallOpVT = TLI.getValueType(CallOperand->getType());
switch (Constraints[i].Type) {
case InlineAsm::isOutput: {
// Copy the output from the appropriate register.
std::vector<unsigned> Regs =
TLI.getRegForInlineAsmConstraint(ConstraintCode, CallOpVT);
// Find a regsister that we can use.
// 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 (Regs.size() == 1)
DestReg = Regs[0];
if (PhysReg.first)
DestReg = PhysReg.first;
else {
bool UsesInputRegister = false;
std::vector<unsigned> Regs =
TLI.getRegClassForInlineAsmConstraint(ConstraintCode,
ConstraintVTs[i]);
// If this is an early-clobber output, or if there is an input
// constraint that matches this, we need to reserve the input register
// so no other inputs allocate to it.
bool UsesInputRegister = false;
if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
UsesInputRegister = true;
DestReg = GetAvailableRegister(true, UsesInputRegister,
@ -1276,24 +1310,21 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
assert(I.getType() != Type::VoidTy && "Bad inline asm!");
RetValReg = DestReg;
OpTy = I.getType();
} else {
Value *CallOperand = I.getOperand(OpNum);
IndirectStoresToEmit.push_back(std::make_pair(DestReg, CallOperand));
OpTy = CallOperand->getType();
OpTy = cast<PointerType>(OpTy)->getElementType();
OpNum++; // Consumes a call operand.
}
// Add information to the INLINEASM node to know that this register is
// set.
AsmNodeOperands.push_back(DAG.getRegister(DestReg,
TLI.getValueType(OpTy)));
AsmNodeOperands.push_back(DAG.getRegister(DestReg, ConstraintVTs[i]));
AsmNodeOperands.push_back(DAG.getConstant(2, MVT::i32)); // ISDEF
break;
}
case InlineAsm::isInput: {
const Type *OpTy = CallOperand->getType();
Value *CallOperand = I.getOperand(OpNum);
OpNum++; // Consumes a call operand.
unsigned SrcReg;
@ -1306,33 +1337,45 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
// just use its register.
unsigned OperandNo = atoi(ConstraintCode.c_str());
SrcReg = cast<RegisterSDNode>(AsmNodeOperands[OperandNo*2+2])->getReg();
ResOp = DAG.getRegister(SrcReg, CallOpVT);
ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
ResOpType = 1;
Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
Flag = Chain.getValue(1);
} else {
TargetLowering::ConstraintType CTy = TargetLowering::C_RegisterClass;
TargetLowering::ConstraintType CTy = TargetLowering::C_Register;
if (ConstraintCode.size() == 1) // not a physreg name.
CTy = TLI.getConstraintType(ConstraintCode[0]);
switch (CTy) {
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: {
// Copy the input into the appropriate register.
std::vector<unsigned> Regs =
TLI.getRegForInlineAsmConstraint(ConstraintCode, CallOpVT);
if (Regs.size() == 1)
SrcReg = Regs[0];
else
SrcReg = GetAvailableRegister(false, true, Regs,
OutputRegs, InputRegs);
TLI.getRegClassForInlineAsmConstraint(ConstraintCode,
ConstraintVTs[i]);
SrcReg = GetAvailableRegister(false, true, Regs,
OutputRegs, InputRegs);
// FIXME: should be match fail.
assert(SrcReg && "Wasn't able to allocate register!");
Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
Flag = Chain.getValue(1);
ResOp = DAG.getRegister(SrcReg, CallOpVT);
ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
ResOpType = 1;
break;
}

View File

@ -999,8 +999,8 @@ PPCTargetLowering::getConstraintType(char ConstraintLetter) const {
std::vector<unsigned> PPCTargetLowering::
getRegForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const {
getRegClassForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const {
if (Constraint.size() == 1) {
switch (Constraint[0]) { // GCC RS6000 Constraint Letters
default: break; // Unknown constriant letter
@ -1051,8 +1051,7 @@ getRegForInlineAsmConstraint(const std::string &Constraint,
}
}
// Handle explicit register names.
return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
return std::vector<unsigned>();
}
// isOperandValidForConstraint

View File

@ -99,8 +99,8 @@ namespace llvm {
ConstraintType getConstraintType(char ConstraintLetter) const;
std::vector<unsigned>
getRegForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const;
getRegClassForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const;
bool isOperandValidForConstraint(SDOperand Op, char ConstraintLetter);
};
}

View File

@ -745,24 +745,34 @@ bool TargetLowering::isOperandValidForConstraint(SDOperand Op,
std::vector<unsigned> TargetLowering::
getRegClassForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const {
return std::vector<unsigned>();
}
std::pair<unsigned, const TargetRegisterClass*> TargetLowering::
getRegForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const {
// Not a physreg, must not be a register reference or something.
if (Constraint[0] != '{') return std::vector<unsigned>();
if (Constraint[0] != '{')
return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
assert(*(Constraint.end()-1) == '}' && "Not a brace enclosed constraint?");
// Remove the braces from around the name.
std::string RegName(Constraint.begin()+1, Constraint.end()-1);
// Scan to see if this constraint is a register name.
// Figure out which register class contains this reg.
const MRegisterInfo *RI = TM.getRegisterInfo();
for (unsigned i = 1, e = RI->getNumRegs(); i != e; ++i) {
if (const char *Name = RI->get(i).Name)
if (StringsEqualNoCase(RegName, Name))
return std::vector<unsigned>(1, i);
for (MRegisterInfo::regclass_iterator RCI = RI->regclass_begin(),
E = RI->regclass_end(); RCI != E; ++RCI) {
const TargetRegisterClass *RC = *RCI;
for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
I != E; ++I) {
if (StringsEqualNoCase(RegName, RI->get(*I).Name)) {
return std::make_pair(*I, RC);
}
}
}
// Unknown physreg.
return std::vector<unsigned>();
return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
}

View File

@ -1961,8 +1961,8 @@ void X86TargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
}
std::vector<unsigned> X86TargetLowering::
getRegForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const {
getRegClassForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const {
if (Constraint.size() == 1) {
// FIXME: not handling fp-stack yet!
// FIXME: not handling MMX registers yet ('y' constraint).
@ -1993,6 +1993,5 @@ getRegForInlineAsmConstraint(const std::string &Constraint,
}
}
// Handle explicit register names.
return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
return std::vector<unsigned>();
}

View File

@ -224,8 +224,8 @@ namespace llvm {
SDOperand getReturnAddressFrameIndex(SelectionDAG &DAG);
std::vector<unsigned>
getRegForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const;
getRegClassForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const;
private:
// C Calling Convention implementation.
std::vector<SDOperand> LowerCCCArguments(Function &F, SelectionDAG &DAG);