diff options
| author | Chris Lattner <sabre@nondot.org> | 2006-02-22 00:56:39 +0000 |
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2006-02-22 00:56:39 +0000 |
| commit | 7ad77dfc2add2ccfe65318a984ee17435bc02a3c (patch) | |
| tree | f2ea5616f40a850e8c81d941533672ae7eb751b4 /llvm | |
| parent | cd78df1e85a9993b7c9f3a44888eead2195a5161 (diff) | |
| download | bcm5719-llvm-7ad77dfc2add2ccfe65318a984ee17435bc02a3c.tar.gz bcm5719-llvm-7ad77dfc2add2ccfe65318a984ee17435bc02a3c.zip | |
split register class handling from explicit physreg handling.
llvm-svn: 26308
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/Target/TargetLowering.h | 22 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 111 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 7 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.h | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/TargetLowering.cpp | 32 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 7 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.h | 4 |
7 files changed, 124 insertions, 63 deletions
diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h index 0e51930442e..4757a4a56a7 100644 --- a/llvm/include/llvm/Target/TargetLowering.h +++ b/llvm/include/llvm/Target/TargetLowering.h @@ -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. diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index c8e94019e32..d16b070c51f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/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/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 243c51d7c9d..003d16c26b1 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/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/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index a1ce5545c32..86264aec38b 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/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/llvm/lib/Target/TargetLowering.cpp b/llvm/lib/Target/TargetLowering.cpp index 79211debc99..e82e7f768ea 100644 --- a/llvm/lib/Target/TargetLowering.cpp +++ b/llvm/lib/Target/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/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index bbf590b8ac3..e32cc0f2bd8 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/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/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index 375320c7714..d45afa4a184 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/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); |

