Fix twolf -funroll-loops -O3 miscompilation (a semi-latent web.c bug)

Steven Bosscher stevenb.gcc@gmail.com
Tue Nov 27 12:01:00 GMT 2012


On Tue, Nov 27, 2012 at 11:34 AM, Steven Bosscher wrote:
>>> gcc/
>>>       * loop-unroll.c (struct iv_to_split): Add new 'orig_var' member.
>>>       (analyze_iv_to_split_insn): Record it.
>>>       (maybe_strip_eq_note_for_split_iv): New function to remove REG_EQUAL
>>>       notes that refer to IVs that are being split.
>>>       (apply_opt_in_copies): Use maybe_strip_eq_note_for_split_iv.  Twice.
>>>       Use FOR_BB_INSNS_SAFE.
>>
>> That's fine with me, thanks.  You might want to defer applying it until the
>> reason why it isn't apparently sufficient for aermod.f90 is understood though.
>
> Thanks. Yes, I'm first going to try and figure out why this doesn't
> fix aermod for Dominique. I suspect the problem is in variable
> expansion in the unroller. A previous patch of mine updates REG_EQUAL
> notes in variable expansion, but it doesn't clean up notes that refer
> to maybe dead registers.

Well, that's not it. But what I said below:


> I have to say, I've got a uncomfortable feeling about REG_EQUAL notes
> not being allowed to refer to dead registers.

applies even more after analyzing Dominique's bug.

At the start of RTL PRE we have:

 2000 {r719:DI=r719:DI+0x4;clobber flags:CC;}
      REG_UNUSED: flags:CC

where r719:DI+0x4 is found to be partially redundant. So PRE optimizes this to:

 2889 r719:DI=r1562:DI
      REG_EQUAL: r719:DI+0x4
...
 2913 r1562:DI=r719:DI+0x4

This self-reference in the REG_EQUAL note is the problem. The SET
kills r719, but there is a USE in the PRE'ed expression that keeps
r719 alive. But this use is copy-propagated away in CPROP2:

 2913 r1562:DI=r1562:DI+0x4

Now that USE of r719 is a use of a dead register, rendering the
REG_EQUAL invalid. From there on the problem is the same as the ones I
had to "fix" in loop-unroll.c. First the webizer puts the USE in a
different web and renames the USE to r1591:

 2889 r719:DI=r1562:DI
      REG_EQUAL: r1591:DI+0x4

CSE2 uses this and the equivalence of r719 and r1562 to "optimize" the
PRE expression:

 2913 r1562:DI=r1591:DI+0x8

Then init-regs notices that this reg is quasi-used uninitialized:

 3122 r1591:DI=0
 2913 r1562:DI=r1591:DI+0x8
      REG_DEAD: r1591:DI

And combine finally produces:

 2913 r1562:DI=0x8


I'm not sure what to name as the "root cause" for all of this. It all
starts with PRE creating a REG_EQUAL note that references the register
that's SET in the insn the note is attached to, but the register is
live after the insn so from that point of view the note is not
invalid. CPROP2 kills r179 by propagating it out and making the note
invalid. I think CPROP2 could do that to any register, and if passes
should make sure REG_EQUAL notes are updated or removed then this is a
bug in RTL CPROP.

Very, very messy...

Ciao!
Steven



More information about the Gcc-patches mailing list