Re: New RTL instruction for my port
Dear all, I've gone to using unspec and I think I know why I have a problem. It seems that actually, the problem lies with the fact that these instructions are touching an internal register and how I am handling that register. Since I don't want the register allocator to use that register, I put a 1 in FIXED_REGISTERS. However, it's state is persistent across function calls, meaning that if nothing changes its state, it will be still set in the same way after a return call. However, CALL_USED_REGISTERS is defined as 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any registers that can be used without being saved.. These two sentences seem in contradiction with what I want : - I want to define a register that is not available to the register allocator but is available across function calls. What seems to happen is if I do : __builtin_newins (x,y); /* Modifies the accumulator */ foo (); z = __builtin_retrieve_accum (); /* Retrieve the accumulator */ the first builtin is removed because the internal register is deemed to not conserve its value across the function call even if my retrieve_accum is defined as : (insn 12 11 13 3 mac3.c:8 (parallel [ (set (reg:DI 72 [ D.1223 ]) (unspec:DI [ (reg:DI 74 [ a.0 ]) (reg:DI 73 [ b.1 ]) (reg:DI 66 acc) ] 5)) (clobber (reg:DI 66 acc)) ]) -1 (nil)) We see that I say that acc is used by the unspec but is also clobbered by the instruction (which it is actually, we use the old value and update it in the same instruction). Any ideas on how I can solve this ? As always, thank you for your input, Jc On Tue, Dec 15, 2009 at 10:48 AM, Jean Christophe Beyler jean.christophe.bey...@gmail.com wrote: EPILOGUE_USES does not seem to work, the code still gets optimized out. However, unspec_volatile works but then, as you have said, the compiler doesn't optimize out things that it then could. I have for example an instruction to set this special register. Theoretically, if we had : set (x); set (y); The compiler should remove the first set. Which it does if I remove the volatile but keep a retrieval of the special register in the function. Any other ideas by any chance? Thanks again, Jc On Tue, Dec 15, 2009 at 10:20 AM, Daniel Jacobowitz d...@false.org wrote: On Tue, Dec 15, 2009 at 10:08:02AM -0500, Jean Christophe Beyler wrote: You are correct. So I should be changing things in the adjust_cost function instead. I was also wondering, these instructions modify an internal register that has been set as a fixed register. However, the compiler optimizes them out when the accumulator is not retrieved for a calculation. How can I tell the compiler that it should not remove these instructions. Here is an example code: uint64_t foo (uint64_t x, uint64_t y) { uint64_t z; __builtin_newins (x,y); /* Modifies the accumulator */ z = __builtin_retrieve_accum (); /* Retrieve the accumulator */ return z; } If I remove the instruction z = ...;, then the compiler will optimize out my first builtin call. I suppose you could use EPILOGUE_USES to say that changes to the accumulator should not be discarded. You could also use unspec_volatile instead of unspec, but that may further inhibit optimization. -- Daniel Jacobowitz CodeSourcery
Re: New RTL instruction for my port
On 01/07/2010 12:58 PM, Jean Christophe Beyler wrote: Dear all, I've gone to using unspec and I think I know why I have a problem. It seems that actually, the problem lies with the fact that these instructions are touching an internal register and how I am handling that register. Since I don't want the register allocator to use that register, I put a 1 in FIXED_REGISTERS. However, it's state is persistent across function calls, meaning that if nothing changes its state, it will be still set in the same way after a return call. However, CALL_USED_REGISTERS is defined as 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any registers that can be used without being saved.. These two sentences seem in contradiction with what I want : - I want to define a register that is not available to the register allocator but is available across function calls. See CALL_REALLY_USED_REGISTERS. r~
Re: New RTL instruction for my port
I am almost convinced I had tried that already but apparently not. This seems to have fixed my problem, thank you :-) Jc On Thu, Jan 7, 2010 at 4:14 PM, Richard Henderson r...@redhat.com wrote: On 01/07/2010 12:58 PM, Jean Christophe Beyler wrote: Dear all, I've gone to using unspec and I think I know why I have a problem. It seems that actually, the problem lies with the fact that these instructions are touching an internal register and how I am handling that register. Since I don't want the register allocator to use that register, I put a 1 in FIXED_REGISTERS. However, it's state is persistent across function calls, meaning that if nothing changes its state, it will be still set in the same way after a return call. However, CALL_USED_REGISTERS is defined as 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any registers that can be used without being saved.. These two sentences seem in contradiction with what I want : - I want to define a register that is not available to the register allocator but is available across function calls. See CALL_REALLY_USED_REGISTERS. r~
Re: New RTL instruction for my port
You are correct. So I should be changing things in the adjust_cost function instead. I was also wondering, these instructions modify an internal register that has been set as a fixed register. However, the compiler optimizes them out when the accumulator is not retrieved for a calculation. How can I tell the compiler that it should not remove these instructions. Here is an example code: uint64_t foo (uint64_t x, uint64_t y) { uint64_t z; __builtin_newins (x,y); /* Modifies the accumulator */ z = __builtin_retrieve_accum (); /* Retrieve the accumulator */ return z; } If I remove the instruction z = ...;, then the compiler will optimize out my first builtin call. Thanks for your help and input, Jc On Mon, Dec 14, 2009 at 6:10 PM, Daniel Jacobowitz d...@false.org wrote: On Mon, Dec 14, 2009 at 05:52:50PM -0500, Jean Christophe Beyler wrote: I thought of that but then how do I add the cost ? I also have another problem: there is a second instruction that would have the exact same signature if I use an unspec. Is there a solution for that and how do I handle the cost then ? - Just say that an unspec has a higher cost? Are you really talking about rtx_costs? It sounds to me more like you want to change your scheduler. -- Daniel Jacobowitz CodeSourcery
Re: New RTL instruction for my port
On Tue, Dec 15, 2009 at 10:08:02AM -0500, Jean Christophe Beyler wrote: You are correct. So I should be changing things in the adjust_cost function instead. I was also wondering, these instructions modify an internal register that has been set as a fixed register. However, the compiler optimizes them out when the accumulator is not retrieved for a calculation. How can I tell the compiler that it should not remove these instructions. Here is an example code: uint64_t foo (uint64_t x, uint64_t y) { uint64_t z; __builtin_newins (x,y); /* Modifies the accumulator */ z = __builtin_retrieve_accum (); /* Retrieve the accumulator */ return z; } If I remove the instruction z = ...;, then the compiler will optimize out my first builtin call. I suppose you could use EPILOGUE_USES to say that changes to the accumulator should not be discarded. You could also use unspec_volatile instead of unspec, but that may further inhibit optimization. -- Daniel Jacobowitz CodeSourcery
Re: New RTL instruction for my port
EPILOGUE_USES does not seem to work, the code still gets optimized out. However, unspec_volatile works but then, as you have said, the compiler doesn't optimize out things that it then could. I have for example an instruction to set this special register. Theoretically, if we had : set (x); set (y); The compiler should remove the first set. Which it does if I remove the volatile but keep a retrieval of the special register in the function. Any other ideas by any chance? Thanks again, Jc On Tue, Dec 15, 2009 at 10:20 AM, Daniel Jacobowitz d...@false.org wrote: On Tue, Dec 15, 2009 at 10:08:02AM -0500, Jean Christophe Beyler wrote: You are correct. So I should be changing things in the adjust_cost function instead. I was also wondering, these instructions modify an internal register that has been set as a fixed register. However, the compiler optimizes them out when the accumulator is not retrieved for a calculation. How can I tell the compiler that it should not remove these instructions. Here is an example code: uint64_t foo (uint64_t x, uint64_t y) { uint64_t z; __builtin_newins (x,y); /* Modifies the accumulator */ z = __builtin_retrieve_accum (); /* Retrieve the accumulator */ return z; } If I remove the instruction z = ...;, then the compiler will optimize out my first builtin call. I suppose you could use EPILOGUE_USES to say that changes to the accumulator should not be discarded. You could also use unspec_volatile instead of unspec, but that may further inhibit optimization. -- Daniel Jacobowitz CodeSourcery
Re: New RTL instruction for my port
On Mon, Dec 14, 2009 at 04:46:59PM -0500, Jean Christophe Beyler wrote: My current solution: - Define a new rtl in rtl.def Just use an unspec or unspec_volatile. You don't need a new RTL operation. - Add the new rtl in the MD file and the generated assembly instruction However, the solution seems to work, except in O0, where I get this error: This means whatever is calling gen_newrtl to create the insn is not checking operand predicates first. That's probably code you wrote too. -- Daniel Jacobowitz CodeSourcery
Re: New RTL instruction for my port
On Mon, Dec 14, 2009 at 5:04 PM, Daniel Jacobowitz d...@false.org wrote: On Mon, Dec 14, 2009 at 04:46:59PM -0500, Jean Christophe Beyler wrote: My current solution: - Define a new rtl in rtl.def Just use an unspec or unspec_volatile. You don't need a new RTL operation. I thought of that but then how do I add the cost ? I also have another problem: there is a second instruction that would have the exact same signature if I use an unspec. Is there a solution for that and how do I handle the cost then ? - Just say that an unspec has a higher cost? - Add the new rtl in the MD file and the generated assembly instruction However, the solution seems to work, except in O0, where I get this error: This means whatever is calling gen_newrtl to create the insn is not checking operand predicates first. That's probably code you wrote too. You are probably right, I'll move it into a register first before generating my instruction. Thanks a lot, Jc
Re: New RTL instruction for my port
On Mon, Dec 14, 2009 at 05:52:50PM -0500, Jean Christophe Beyler wrote: I thought of that but then how do I add the cost ? I also have another problem: there is a second instruction that would have the exact same signature if I use an unspec. Is there a solution for that and how do I handle the cost then ? - Just say that an unspec has a higher cost? Are you really talking about rtx_costs? It sounds to me more like you want to change your scheduler. -- Daniel Jacobowitz CodeSourcery