[PATCH 1/3] powerpc: Don't use local named register variable in current_thread_info

Alan Modra amodra at gmail.com
Thu Jan 8 17:36:24 AEDT 2015


On Wed, Jan 07, 2015 at 04:12:47PM +1100, Anton Blanchard wrote:
> Hi Alan,
> 
> > Right.  This is really an rs6000 backend bug.  We describe one of the
> > indirect calls that go wrong here as
> > 
> > (call_insn 108 107 109 13 (parallel [
> >             (set (reg:DI 3 3)
> >                 (call (mem:SI (reg:DI 288) [0 *_67 S4 A8])
> >                     (const_int 64 [0x40])))
> >             (use (mem:DI (plus:DI (reg/f:DI 287 [ ops_44(D)->update ])
> >                         (const_int 8 [0x8])) [0  S8 A8]))
> >             (set (reg:DI 2 2)
> >                 (mem/v/c:DI (plus:DI (reg/f:DI 1 1)
> >                         (const_int 40 [0x28])) [0  S8 A8]))
> >             (clobber (reg:DI 65 lr))
> >         ]) net/core/skbuff.c:2085 680 {*call_value_indirect_aixdi}
> > 	<notes and arg uses omitted for clarity>
> > )
> > 
> > Notice that the RTL contains a "parallel".  As you might guess, gcc
> > treats the vector of expressions inside the square brackets of the
> > parallel as happening "in parallel".  Meaning that as far as gcc is
> > concerned the toc restore part (third element) happens at the same
> > time as the call (first element).  So if gcc replaces (reg:DI 1) in
> > the toc restore with some other register known to have the same value
> > *before* the call, gcc's RTL analysis will conclude that such a
> > replacement is valid.
> 
> Thanks for looking into this. Does that mean we were just getting lucky
> with the previous version:
> 
> static inline struct thread_info *current_thread_info(void)
> {
>         register unsigned long sp asm("r1");
> 
>         return (struct thread_info *)(sp & ~(THREAD_SIZE-1));
> }

With both versions, the original rtl for current_thread_info consists
of two instructions, copy r1 to a pseudo reg, then the "and".  With
the above version, fwprop1 manages to combine this to a single "and"
insn.  When using a global reg var, fprop1 leaves the two
instructions, the copy causing the trouble in the following cprop1
pass.  So it's not that we are getting lucky in cprop1, but that
fwprop1 behaves differently with global vs. local registers.

-- 
Alan Modra
Australia Development Lab, IBM


More information about the Linuxppc-dev mailing list