https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46590

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ebotcazou at gcc dot gnu.org,
                   |                            |jakub at gcc dot gnu.org

--- Comment #50 from Richard Biener <rguenth at gcc dot gnu.org> ---
The issue with loop-invariant and DF is that while loop-invariant tries to
use df_analyze_loop to constrain work we do

  df_remove_problem (df_chain);
  df_process_deferred_rescans ();
  df_chain_add_problem (DF_UD_CHAIN);
  df_live_add_problem ();
  df_live_set_all_dirty ();
  df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
  df_analyze_loop (loop);

where df_live_set_all_dirty sets bits for all blocks in the function
to df_live->out_of_date_transfer_functions and for example
df_live_local_compute
iterates over df_live->out_of_date_transfer_functions instead of
the blocks set by df_set_blocks.

Now I'm not sure DF_LIVE results are even correct if computed only for
a loop, but certainly df_analyze_loop sets up the postorder arrays to
only contain blocks in the loop.

The most localized fix would be to somehow split df_analyze_loop ()
into df_set_loop_to_analyze () and the (existing) df_analyze_1 () so
df_live_set_all_dirty could look at the to be analyzed blocks instead
of iterating over all blocks.

Of course df_analyze () itself computes postorder and friends :/

Just cutting out df_live_local_compute via the hack below improves
the DF time to

 df live&initialized regs           :   0.11 (  1%)   0.00 (  0%)   0.18 (  2%)
      0 kB (  0%)

but I believe the proper way of action would be to split DF setup
from DF analyse but that needs changes in all consumers.  That way
the problem setup could already restrict work (that part is still
quadratic with the hack below - I see multiple iterations over
out_of_date_transfer_functions left).  Other live methods already
iterate only over the input bitmap but there are some left iterating
over out_of_date_transfer_functions as well.

Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c   (revision 270053)
+++ gcc/df-problems.c   (working copy)
@@ -1470,18 +1470,16 @@ df_live_bb_local_compute (unsigned int b
 /* Compute local uninitialized register info.  */

 static void
-df_live_local_compute (bitmap all_blocks ATTRIBUTE_UNUSED)
+df_live_local_compute (bitmap all_blocks)
 {
   unsigned int bb_index;
   bitmap_iterator bi;

   df_grow_insn_info ();

-  EXECUTE_IF_SET_IN_BITMAP (df_live->out_of_date_transfer_functions,
+  EXECUTE_IF_AND_IN_BITMAP (all_blocks,
df_live->out_of_date_transfer_functions,
                            0, bb_index, bi)
-    {
-      df_live_bb_local_compute (bb_index);
-    }
+    df_live_bb_local_compute (bb_index);

   bitmap_clear (df_live->out_of_date_transfer_functions);
 }


Any opinions?  I'm going to test the above in any way since I've seen
this pop up multiple times (loop-iv is another consumer of df_analyze_loop,
but it uses the UD_CHAIN problem only).  It's out_of_date_transfer_functions
state gets adjusted by df_scan_blocks appearantly (it's docs say), so maybe
not calling df_live_set_all_dirty at all from loop-invariant.c would be
a better fix but I see a lot of calls to df_live_set_all_dirty...
(find_defs doesn't remove the LIVE problem but just adds it all the time,
also "leaking" out_of_date_transfer_functions).

As expected not calling df_live_set_all_dirty also solves the issue.
Note df_live_add_problem says:

void
df_live_add_problem (void)
{
  df_add_problem (&problem_LIVE);
  /* These will be initialized when df_scan_blocks processes each
     block.  */
  df_live->out_of_date_transfer_functions = BITMAP_ALLOC (&df_bitmap_obstack);

supporting that change.  And df_live_set_all_dirty is commented as

/* Set all of the blocks as dirty.  This needs to be done if this
   problem is added after all of the insns have been scanned.  */

but the incosistency betwee the UD and LIVE problems here is disturbing.
Removing the set_all_dirty call shows the visiting doesn't happen.

Reply via email to