This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [mips] fix $gp restore bug


Adam Nemet <anemet@caviumnetworks.com> writes:
>>  I don't think (D)ADDIUPC would actually be of any help here -- the 16-bit 
>> immediate would not cover a range wider than the branch displacement 
>> already does.  I could imagine a "fix" where the addend would be shifted 
>> left by a few bits (the result could be masked to maintain some 
>> reasonable alignment), but that would only push the limit a little bit 
>> further, and then at a cost.
>
> No, I actually meant DADDUPC:
>
>         lui       $1,%hi(target-1f)
> 1:
>         (d)addiu  $1,$1,%lo(target-1b)
> 	(d)addupc $1,$1
>         jr        $1

Thanks for arguing the case here ;)  As well as getting us out of this hole,
it would remove the need for the "all calls must be through $25" rule.
That was the main reason why the new non-PIC executable support wasn't
entirely transparent to GCC.

Plus it would allow a nice PIC model for non-GOT-based bare-metal ABIs.
I know at least one customer in the past who needed this.

Oh well...

> Maciej W. Rozycki writes:
>>  I found the limitation of GCC that jumps cannot use a scratch register 
>> painful in the past already; my understanding is jumps are processed too 
>> late in the game for new register allocations to be possible (and the 
>> process would have to be iterative), correct?
>
> Yes if the scratch is only needed conditionally depending on the "final" code
> layout you need to preallocate the scratch register even though you might not
> use it at the end.

FWIW, the idea I'm toying with at the moment is:

  - Make every branch use pic_offset_table_rtx.

  - Try to detect cases where a function only needs a global pointer
    because of branches.  In this case, emit easily-identifiable "ghost"
    instructions (in the .md "type" attribute sense) to set, save and
    restore the gp.

    These ghost instructions would replace the sequences we'd normally use.
    They would have 0 length at this stage, and in theory shouldn't interfere
    with things like scheduling.

  - At the end of md_reorg, run shorten_branches to see whether
    all branches are in range.  This should be safe because we run
    dbr_schedule within mips_reorg.  Nothing after mips_reorg should
    change the insn stream besides shorten_branches itself.

  - If some branches are not in range, go through the insn stream and
    replace all the ghost instructions with real implementations.
    (This will of course invalidate the results of the shorten_branches
    call, but the "real" shorten_branches pass will then calculate new
    lengths.)

For added points, we could add some way of telling shorten_branches
that md_reorg has already calculated correct values (in the case
where all branches were in range).  This would avoid another,
redundant, pass.

Besides the complication, the main drawback I can see is that we'd be
unable to fill the delay slots of branches with insns that restore $gp,
even in the usual case where no long branches are needed.

That's certainly a problem for -Os.  I'm not sure it's much of a concern
for other options.  dbr_schedule doesn't take the pipeline into account
at all when filling delay slots, and postponing a restoration of $gp
isn't always a good idea performance-wise.

Richard


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]