Re: New RTL instruction for my port

2010-01-07 Thread Jean Christophe Beyler
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

2010-01-07 Thread Richard Henderson

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

2010-01-07 Thread Jean Christophe Beyler
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

2009-12-15 Thread Jean Christophe Beyler
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

2009-12-15 Thread Daniel Jacobowitz
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

2009-12-15 Thread Jean Christophe Beyler
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

2009-12-14 Thread Daniel Jacobowitz
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

2009-12-14 Thread Jean Christophe Beyler
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

2009-12-14 Thread Daniel Jacobowitz
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