[RFC] Cse reducing performance of register allocation with -O2

Jeff Law law@redhat.com
Tue Oct 13 17:06:00 GMT 2015


On 10/13/2015 07:12 AM, Dominik Vogt wrote:
> In some cases, the work of the cse1 pass is counterproductive, as
> we noticed on s390x.  The effect described below is present since
> at least 4.8.0.  Note that this may not become manifest in a
> performance issue problem on all platforms.  Also note that -O1
> does not show this behaviour because the responsible code is only
> executed with -O2 or higher.
>
> The core of the problem is the was cse1 sometimes handles function
> parameters.  Roughly, the observed situation is
>
> Before cse1
>
>    start of function
>    set pseudoreg Rp to the first argument from hardreg R2
>    (some code that uses Rp)
>    set R2 to Rp
>
> After cse1:
>
>    start of function
>    set pseudoreg Rp to the first argument from hardreg R2
>    (some code that uses Rp)  <--- The use of Rp is still present
>    set R2 to R2              <--- cse1 has replaced Rp with R2
>
> After that, the set pattern is removed completely, and now we have
> both, Rp and R2 live in the drafted code snippet.  Because R2 ist
> still supposed to be live later on, the ira pass chooses a
> different hard register (R1) for Rp, and code to copy R1 back to
> R2 is added later.  (See further down for Rtl and assembly code.)
>
> --
>
> There seems to be code to prevent this in cse.c:hash_rtx_cb() as a
> comment from that function suggests:
>
>      /* On some machines, we can't record any non-fixed hard register,
>         because extending its life will cause reload problems.  We
>         consider ap, fp, sp, gp to be fixed for this purpose.
This is referring to the inability to reload those objects.  It's a 
correctness not a performance concern with those registers.


>      ...
>
> Unfortunately this is not caused by hashing but by the code
> dealing with src_related in cse_insn().  When cse_insn() handles
> the "copy Rp to R2" instruction, it does nothing up to line 5020
> and sets src_related there:
>
>    /* This is the same as the destination of the insns, we want
>       to prefer it.  Copy it to src_related.  The code below will
>       then give it a negative cost.  */
>    if (GET_CODE (dest) == code && rtx_equal_p (p->exp, dest))
>      src_related = dest;
>
> Eventually, the term src_related is used to replace the source
> expression of the set pattern.  So, while the above comment may be
> applicable to hashed expressions that are considered for
> replacement, there's no such "safety net" for the expressions
> src_related, src_folded etc.  I guess if there was, that would fix
> the issue.
>
> --
>
> So, I've made an experimental hack (see attachment) and treid
> that.  In a larger test suite, register copies could be saved in
> quite some places (including the test program below), but in other
> places new register copies were introduced, resulting in about
> twice as much "issues" as without the patch.
>
> Maybe the patch is just too coarse.  In general I'd assume that
> the register allocator does a better job of assigning hard
> registers to pseudo registers.  Is it possible to better describe
> when cse1 should keep its hands off pseudo registers?
We don't really have a way to describe this.

I know Vlad looked at problems in this space -- essentially knowing when 
two registers had the same value in the allocators/reload and exploiting 
that information.

My recollection was it didn't help in any measurable way -- I think he 
discussed it during one of the old GCC summit conferences.  That was 
also in the reload era.

Ultimately this feels like all the issues around coalescing and 
copy-propagation. With that in mind, if we had lifetime & conflict 
information, then we'd be able to query that and perhaps be able to make 
different choices.

I wonder if the web-izer pass could help here or something based on it. 
  Essentially what you want to do is a range split.


Jeff




More information about the Gcc mailing list