On Sep 24, 2007, at 1:12 AM, Andreas Fredriksson wrote:> On 9/24/07, Evan Cheng <evan.cheng at apple.com> wrote: > >> I am going to suggest something shocking. :) Since you will end up >> writing a >> bunch of target specific code anyway, you might a well write a target >> specific pass that change generic instructions into data register >> variant >> ones when necessary. > > Hi Evan, > wouldn't this generate fairly terrible code if each address register > use has to be preceded by instructions to make an address register > hold the right value?No. I would suggest doing this as a instruction selection post pass. It would operate on DAGs so you still get the benefit of SDNode CSE, etc. Scheduling and register allocation happen later. Let me clarify. Write "generic" instructions, i.e. those that use / def DR32, with patterns. So right after isel, all the DAG nodes will be of the dx variant, e.g. ADD_32_dx_dx. Also write AR instruction variants such as ADDA_32_dx. These do not have patterns so they aren't used during selection. Add a post pass to replace load / store operands by replacing them with identical nodes except for the "correct" opcodes. I think this mechanism will work. There is probably a cleaner solution. But I am not seeing it right now. Evan> > I'm a bit confused here, wouldn't this run after the register > allocator, or is there a way to have the register allocator run after > I've gone through and "target-legalized" all instructions? > > Thanks, > // A > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
On 9/25/07, Evan Cheng <evan.cheng at apple.com> wrote:> > Hi Evan, > > wouldn't this generate fairly terrible code if each address register > > use has to be preceded by instructions to make an address register > > hold the right value? > > No. I would suggest doing this as a instruction selection post pass. > It would operate on DAGs so you still get the benefit of SDNode CSE, > etc. Scheduling and register allocation happen later. > > Let me clarify. Write "generic" instructions, i.e. those that use / > def DR32, with patterns. So right after isel, all the DAG nodes will > be of the dx variant, e.g. ADD_32_dx_dx. Also write AR instruction > variants such as ADDA_32_dx. These do not have patterns so they > aren't used during selection. Add a post pass to replace load / store > operands by replacing them with identical nodes except for the > "correct" opcodes. > > I think this mechanism will work. There is probably a cleaner > solution. But I am not seeing it right now.Hi Evan, as per your suggestion on IRC I've tried creating a "shadow group" of registers in my data register class that aren't allocatable and map to the address registers; this allows me to deal with everything as data registers. Integer and FP code without loads and stores work fine with this scheme, and simple memory operations using global addresses work nicely as well. There are a couple of gotchas I keep running into though; 1) My ABI requires the two first pointer arguments to go into address registers A0, A1. I can't seem to express this in the cc td description, because there are no MVTs for pointers. Is there a way around that? This leads to pointer arguments entering functions in data registers because they are simply i32's. If I lower the calling convention stuff manually rather than relying on the generated CC analyzer, how do I determine that a formal argument I'm about to receive or pack together is supposed to be used as a pointer so I can stick it in an address register? 2) How do I implement getPointerRegClass() in my TargetInstrInfo subtype? Returning the proper thing (the address register class) makes the instruction scheduler very unhappy and it asserts complaining that the register classes don't agree (which they don't, obviously, because everything has been selected as data register instructions). Returning the data register class generates a bunch of illegal moves, such as move.l 8(d0), d1. Here, d0 has to be an address register. The root cause of this is instructions that get emitted with the M_LOOK_UP_PTR_REG_CLASS flag, because I have a ptr_rc in my address mode selection patterns for loads and stores. Also, I'm uncertain as to how this custom DR->AR op replacer pass fits into this whole soup and where it is supposed to happen, as I'm still pretty clueless with llvm internals. :) Thanks, Andreas
On Sep 29, 2007, at 2:57 PM, Andreas Fredriksson <deplinenoise at gmail.com> wrote:> On 9/25/07, Evan Cheng <evan.cheng at apple.com> wrote: >>> Hi Evan, >>> wouldn't this generate fairly terrible code if each address register >>> use has to be preceded by instructions to make an address register >>> hold the right value? >> >> No. I would suggest doing this as a instruction selection post pass. >> It would operate on DAGs so you still get the benefit of SDNode CSE, >> etc. Scheduling and register allocation happen later. >> >> Let me clarify. Write "generic" instructions, i.e. those that use / >> def DR32, with patterns. So right after isel, all the DAG nodes will >> be of the dx variant, e.g. ADD_32_dx_dx. Also write AR instruction >> variants such as ADDA_32_dx. These do not have patterns so they >> aren't used during selection. Add a post pass to replace load / store >> operands by replacing them with identical nodes except for the >> "correct" opcodes. >> >> I think this mechanism will work. There is probably a cleaner >> solution. But I am not seeing it right now. > > Hi Evan, > as per your suggestion on IRC I've tried creating a "shadow group" of > registers in my data register class that aren't allocatable and map to > the address registers; this allows me to deal with everything as data > registers. Integer and FP code without loads and stores work fine with > this scheme, and simple memory operations using global addresses work > nicely as well.Very nice.> > > There are a couple of gotchas I keep running into though; > > 1) My ABI requires the two first pointer arguments to go into address > registers A0, A1. I can't seem to express this in the cc td > description, because there are no MVTs for pointers. Is there a way > around that? This leads to pointer arguments entering functions in > data registers because they are simply i32's. > > If I lower the calling convention stuff manually rather than relying > on the generated CC analyzer, how do I determine that a formal > argument I'm about to receive or pack together is supposed to be used > as a pointer so I can stick it in an address register?I'd suggest custom lowering for now. Again use data registers during lowering and fix them during the isel post pass if the parameters are used as pointers. Do you think that would work?> > > 2) How do I implement getPointerRegClass() in my TargetInstrInfo > subtype? Returning the proper thing (the address register class) makes > the instruction scheduler very unhappy and it asserts complaining that > the register classes don't agree (which they don't, obviously, because > everything has been selected as data register instructions). > > Returning the data register class generates a bunch of illegal moves, > such as move.l 8(d0), d1. Here, d0 has to be an address register. The > root cause of this is instructions that get emitted with the > M_LOOK_UP_PTR_REG_CLASS flag, because I have a ptr_rc in my address > mode selection patterns for loads and stores.I think it should return DR register class. My theory is if all the nodes are already fixed right after selection, scheduling and allocation should just work.> > > Also, I'm uncertain as to how this custom DR->AR op replacer pass fits > into this whole soup and where it is supposed to happen, as I'm still > pretty clueless with llvm internals. :)It should happen right after selection and before scheduling (i.e. in InstructionSelectionBasicBlock before it calls ScheduleAndEmitDAG). I would suggest you focusing on getting this down before you start worrying about the downstream passes. Evan> > > Thanks, > Andreas > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev