aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-02-22 00:56:39 +0000
committerChris Lattner <sabre@nondot.org>2006-02-22 00:56:39 +0000
commit1efa40f6a4b561cf8f80fe018684236010645cd0 (patch)
treec0952ccdc9f90c9ae390c5b03583d5bd7382c53c /lib
parent16d597a20d405d8cb13f89f15b8c1fed20428808 (diff)
downloadexternal_llvm-1efa40f6a4b561cf8f80fe018684236010645cd0.zip
external_llvm-1efa40f6a4b561cf8f80fe018684236010645cd0.tar.gz
external_llvm-1efa40f6a4b561cf8f80fe018684236010645cd0.tar.bz2
split register class handling from explicit physreg handling.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26308 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp111
-rw-r--r--lib/CodeGen/SelectionDAG/TargetLowering.cpp32
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp7
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.h4
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp7
-rw-r--r--lib/Target/X86/X86ISelLowering.h4
6 files changed, 108 insertions, 57 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index c8e9401..d16b070 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -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;
}
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 79211de..e82e7f7 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -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);
}
-
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index 243c51d..003d16c 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -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
diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h
index a1ce554..86264ae 100644
--- a/lib/Target/PowerPC/PPCISelLowering.h
+++ b/lib/Target/PowerPC/PPCISelLowering.h
@@ -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);
};
}
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index bbf590b..e32cc0f 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -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>();
}
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index 375320c..d45afa4 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -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);