Changes in directory llvm/lib/CodeGen/SelectionDAG:
SelectionDAGISel.cpp updated: 1.144 -> 1.145 --- Log message: Implement simple register assignment for inline asms. This allows us to compile: int %test(int %A, int %B) { %C = call int asm "xyz $0, $1, $2", "=r,r,r"(int %A, int %B) ret int %C } into: (0x8906130, LLVM BB @0x8902220): %r2 = OR4 %r3, %r3 %r3 = OR4 %r4, %r4 INLINEASM <es:xyz $0, $1, $2>, %r2<def>, %r2, %r3 %r3 = OR4 %r2, %r2 BLR which asmprints as: _test: or r2, r3, r3 or r3, r4, r4 xyz $0, $1, $2 ;; need to print the operands now :) or r3, r2, r2 blr --- Diffs of the changes: (+103 -8) SelectionDAGISel.cpp | 111 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 103 insertions(+), 8 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.144 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.145 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.144 Tue Jan 31 19:28:23 2006 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Wed Feb 1 12:59:47 2006 @@ -40,6 +40,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Debug.h" #include <map> +#include <set> #include <iostream> using namespace llvm; @@ -410,6 +411,11 @@ assert(N.Val == 0 && "Already set a value for this node!"); return N = NewN; } + + unsigned GetAvailableRegister(bool OutReg, bool InReg, + const std::vector<unsigned> &RegChoices, + std::set<unsigned> &OutputRegs, + std::set<unsigned> &InputRegs); // Terminator instructions. void visitRet(ReturnInst &I); @@ -1143,6 +1149,49 @@ DAG.setRoot(Result.second); } +/// GetAvailableRegister - Pick a register from RegChoices that is available +/// for input and/or output as specified by isOutReg/isInReg. If an allocatable +/// register is found, it is returned and added to the specified set of used +/// registers. If not, zero is returned. +unsigned SelectionDAGLowering:: +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 + // stack pointer). + bool Found = false; + for (MRegisterInfo::regclass_iterator RC = MRI->regclass_begin(), + E = MRI->regclass_end(); !Found && RC != E; ++RC) { + // NOTE: This isn't ideal. In particular, this might allocate the + // 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 + // yet). This is a slight code pessimization, but should still work. + for (TargetRegisterClass::iterator I = (*RC)->allocation_order_begin(MF), + E = (*RC)->allocation_order_end(MF); I != E; ++I) + if (*I == Reg) { + Found = true; + 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; +} + /// visitInlineAsm - Handle a call to an InlineAsm object. /// void SelectionDAGLowering::visitInlineAsm(CallInst &I) { @@ -1174,21 +1223,60 @@ std::vector<std::pair<unsigned, Value*> > IndirectStoresToEmit; unsigned OpNum = 1; bool FoundOutputConstraint = false; - //std::set<unsigned> OutputRegs; - //std::set<unsigned> InputRegs; + + // We fully assign registers here at isel time. This is not optimal, but + // should work. For register classes that correspond to LLVM classes, we + // 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; + 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); + if (Regs.size() != 1) continue; // Not assigned a fixed reg. + unsigned TheReg = Regs[0]; + + switch (Constraints[i].Type) { + case InlineAsm::isOutput: + // We can't assign any other output to this register. + OutputRegs.insert(TheReg); + // If this is an early-clobber output, it cannot be assigned to the same + // value as the input reg. + if (Constraints[i].isEarlyClobber) + 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; + } + } 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]; switch (Constraints[i].Type) { case InlineAsm::isOutput: { - bool isEarlyClobber = Constraints[i].isEarlyClobber; // Copy the output from the appropriate register. std::vector<unsigned> Regs = TLI.getRegForInlineAsmConstraint(ConstraintCode); - assert(Regs.size() == 1 && "Only handle simple regs right now!"); - unsigned DestReg = Regs[0]; + + // Find a regsister that we can use. + unsigned DestReg; + if (Regs.size() == 1) + DestReg = Regs[0]; + else + DestReg = GetAvailableRegister(true, Constraints[i].isEarlyClobber, + Regs, OutputRegs, InputRegs); + + assert(DestReg && "Couldn't allocate output reg!"); const Type *OpTy; if (!Constraints[i].isIndirectOutput) { @@ -1218,12 +1306,20 @@ case InlineAsm::isInput: { Value *Operand = I.getOperand(OpNum); const Type *OpTy = Operand->getType(); + OpNum++; // Consumes a call operand. // Copy the input into the appropriate register. std::vector<unsigned> Regs = TLI.getRegForInlineAsmConstraint(ConstraintCode); - assert(Regs.size() == 1 && "Only handle simple regs right now!"); - unsigned SrcReg = Regs[0]; + unsigned SrcReg; + if (Regs.size() == 1) + SrcReg = Regs[0]; + else + SrcReg = GetAvailableRegister(false, true, Regs, + OutputRegs, InputRegs); + + assert(SrcReg && "Couldn't allocate input reg!"); + Chain = DAG.getCopyToReg(Chain, SrcReg, getValue(Operand), Flag); Flag = Chain.getValue(1); @@ -1271,7 +1367,6 @@ Chain = Val.getValue(1); Flag = Val.getValue(2); StoresToEmit.push_back(std::make_pair(Val, Ptr)); - OpNum++; // Consumes a call operand. } // Emit the non-flagged stores from the physregs. _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits