Patch for PR 33755: orphaned high-part relocations

Richard Sandiford rsandifo@nildram.co.uk
Mon Oct 22 22:28:00 GMT 2007


PR 33755 is about a case in which 4.2 generates a %hi or local %got
relocation without a partnering %lo relocation.  This is wrong code,
and leads to a linker error.

The problem comes from dbr_schedule, although it's not really a bug there.
We have:

        bne     $5,$0,L1        # A
        ...stuff...
L1:
        bne     $5,$0,L2        # B
        ...printk call...
L2:

and nothing before dbr_schedule has managed to thread A to L2.
dbr_schedule first fills B's delay slot with an lui from the printk
block, then steal_delay_list_from_target realises that A can steal B's
delay slot and branch directly to L2.  There is no other path to L1,
so the rest of the printk call is now dead.

4.3 doesn't manage to thread the jump due to differences further up
the chain.  Both 4.2 and 4.3 versions expand the switch statement to
the following rtl:

   tmp = val & 1
   if (tmp == 0) goto ...
   tmp2 = 1
   if (tmp == tmp2) goto ...
   ...printk() code...

4.2 keeps the block in essentially this form up until combine,
which uses nonzero_bits checks to optimise the second branch into
"if (tmp != 0) goto ...".  4.3's loop-invariant motion can hoist
the setting of tmp2, thus stopping combine from doing the optimisation.

dbr_schedule isn't really where we'd want to optimise this case anyway.
The dbr_schedule is there for other situations, where the threading is
only possible when the delay slot is filled with an instruction from
the target of the branch.  We should ideally thread A to L2 much earlier,
preferably at the tree level, and delete the whole printk block as dead.
E.g. we probably ought to have some "nonzero bits" optimisations in tree
VRP, if we don't already.  (And if we don't already, I doubt I'll have been
the first person to say that.)

As far as 4.3 goes: if we need to keep the branch, what LIM is doing is
perfectly reasonable; if we don't need to keep the branch, we should have
optimised it away before LIM.

For most targets, this is at worst a missed optimisation.  I don't think
the MIPS port can rely on the optimisation for correctness.  So (alas!)
I think the upshot is simply that we need to add some special code to
mips_reorg to delete high-part relocations that have no matching lows.
This sort of bug is something that has happened off and on since at
least GCC 2 days, although the testcases tend to vary between releases,
so this particular example is a 4.2 regression.

Here are the patches I'm thinking of, one for mainline and 4.2.
I've tested both on mips-linux-gnu.  I'll hold off applying for
a couple of days for comments.

Richard


-------------- next part --------------
A non-text attachment was scrubbed...
Name: mainline.diff
Type: text/x-diff
Size: 10740 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20071022/ec2a1d35/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 4.2.diff
Type: text/x-diff
Size: 10486 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20071022/ec2a1d35/attachment-0001.bin>


More information about the Gcc-patches mailing list