On 9/28/26 8:15 AM, [email protected] wrote:
From: Kyrylo Tkachov <[email protected]>

Postreload GCSE searches single-predecessor chains and replaces loads by
copies on incoming edges.  It misses a fully redundant load after a join,
or when an earlier use of its destination prevents an edge copy:

   bb2: r0 = [sp + K]
   ... paths that preserve r0 and [sp + K] ...
   bb5: use (r1)
        r1 = [sp + K]

Replace the last load with r1 = r0 at its original position.  Select the
nearest eligible dominating occurrence, then use a backward worklist to
check memory transparency and register preservation on every path.  Reuse
the existing expression table, alias analysis and register-clobber checks.
Keep partial redundancy elimination as a fallback.  In cold blocks,
allow full forwarding only when it does not increase the size cost.

This removes some vector spills and reloads from video filter code
compiled with SVE that motivates this series.

A reduced SVE test covers forwarding across joins.  RTL tests cover a
join with an earlier destination use, a transparent loop, and register
alias, memory overwrite, address and loop clobbers.

Bootstrapped and tested on aarch64-none-linux-gnu.
Ok for trunk?
Thanks,
Kyrill

gcc/ChangeLog:

        * postreload-gcse.cc (stats): Add loads_forwarded.
        (available_from_dominator_p): New function.
        (replace_fully_redundant_load): Likewise.
        (eliminate_partially_redundant_load): Try full forwarding before
        partial elimination.  Keep the cold-block gate on partial elimination.
        (eliminate_partially_redundant_loads): Scan cold blocks too.
        (gcse_after_reload_main): Compute dominators when needed and record
        forwarded loads.

gcc/testsuite/ChangeLog:

        * gcc.dg/rtl/aarch64/postreload-gcse-forward.c: New test.
        * gcc.target/aarch64/sve/spill-gcse.c: New test.

Signed-off-by: Kyrylo Tkachov <[email protected]>

@@ -1002,6 +1004,101 @@ compute_expr_transp (expr **slot, FILE *dump_file 
ATTRIBUTE_UNUSED)
    return 1;
  }
+/* Return true if REG still holds EXPR at the entry to BB after SOURCE.
+   SOURCE must dominate BB.  Check every path backwards to SOURCE's block,
+   including queued edge instructions.  */
Ouch.  This seems like it could end up being expensive.  My memory is fuzzy on postreload-gcse, but would it be better from a compile-time standpoint to work more like gcse/pre by computing local properties and propagating them across the CFG?   While the on-demand could be more efficient in the common case if we only have to do a few lookups, it could explode on us in pathological cases it seems.

So generally supportive of the idea, just concerned about the potential for compile-time problems, particularly in pathological cases.

jeff

Reply via email to