On my target, the multiplication can involve all general purpose registers, but there's are still some restrictions: the first and the second operand as well as the result must be in different registers, and neither register can be gr7. How can I enforce this restriction on the register allocator? - Volodya
Vladimir Prus wrote:> On my target, the multiplication can involve all general purpose registers, > but there's are still some restrictions: the first and the second operand > as well as the result must be in different registers, and neither register > can be gr7. How can I enforce this restriction on the register allocator?And the other side of the question is now to inform register allocator that mul instruction clobbers gr7? I see some support for getting "implicit operands" in MachineInstr.cpp, but the only method which can set them: MachineInstr::SetRegForImplicitRef is marked as SPARC-specific and is not documented. - Volodya
On Thu, 1 Jul 2004, Vladimir Prus wrote:> Vladimir Prus wrote: > > On my target, the multiplication can involve all general purpose registers, > > but there's are still some restrictions: the first and the second operand > > as well as the result must be in different registers, and neither register > > can be gr7. How can I enforce this restriction on the register allocator? > > And the other side of the question is now to inform register allocator that > mul instruction clobbers gr7? I see some support for getting "implicit > operands" in MachineInstr.cpp, but the only method which can set them:In the entry for that instruction in your .td file, just set the 'Defs' value to gr7. something like this: let Defs = [GR7] in def YOURMUL ... There is also an implicit uses value "Uses" which you should also fill in all of the implicit uses of instructions. The X86 backend uses a little "Imp" helper class, defined like this: class Imp<list<Register> uses, list<Register> defs> { list<Register> Uses = uses; list<Register> Defs = defs; } Which allows instructions to do this more tersely: e.g. def LEAVE : I<"leave", 0xC9, RawFrm>, Imp<[EBP,ESP],[EBP,ESP]>; def REP_MOVSB : I<"rep movsb", 0xA4, RawFrm>, REP, Imp<[ECX,EDI,ESI], [ECX,EDI,ESI]>; def MUL32m : Im32<"mul", 0xF7, MRM4m>, Imp<[EAX],[EAX,EDX]>; The X86 is big on implicit uses and definitions :) -Chris -- http://llvm.cs.uiuc.edu/ http://www.nondot.org/~sabre/Projects/
On Thu, 1 Jul 2004, Vladimir Prus wrote:> On my target, the multiplication can involve all general purpose registers, > but there's are still some restrictions: the first and the second operand as > well as the result must be in different registers, and neither register can > be gr7. How can I enforce this restriction on the register allocator?This is a good question, one that I don't have a great answer for. In order to just get things working for you in the short term, you can just force the operands into specific physical registers, by outputting a template like this: gr5 = reg1024 gr6 = reg1025 gr4 = mul gr5, gr6 reg1026 = gr4 This is obviously not going to generate wonderful code over the long term, but should work. In the longer term, we need to increase the expressivity of the register classes a bit. In particular we need to be able to support nested register classes (important on the X86), be able to specify aliasing more precisely, and be able to handle other strange constraints like you ran into here. I imagine that you are more interested in getting things working than tuning the generated code at this point, but if you get interested in working on this, please bring it back up :) -Chris -- http://llvm.cs.uiuc.edu/ http://www.nondot.org/~sabre/Projects/