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
>>
>

Reply via email to