After the fix to RPO VN in loop header copying DF via RTL invariant
motion takes 50% of the compile-time for the second testcase in
PR46590.  This is caused by the DF live problem iterating over
all dirty blocks for the local problem which is all blocks of
the function because while loop-invariant uses df_analyze_loop
it always marks all blocks of the function as dirty via
df_live_set_all_dirty.  One of the possible fixes is to add
a df_live_set_loop_dirty () function which causes the problem
to only iterate over one loop blocks.

It turns out the LIVE problem is always present so we cannot
remove it which in turn means we have to mark blocks possibly
not visited by invaraint motion as dirty (thus the new
df_live_set_all_dirty at the end of move_loop_invariants).

Anyhow - I'm not really into how DF should ideally work here
but thought this issue was "easy" enough to fix...

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

This brings down DF live time from 50% to 0% for the testcase
(IIRC I've seen loop-invaraint as time-hog several times,
surprising me)

Richard.

2019-04-01  Richard Biener  <rguent...@suse.de>

        PR rtl-optimization/46590
        * df.h (df_live_set_loop_dirty): Declare.
        * df-problems.c: Include cfgloop.h.
        (df_live_set_loop_dirty): New function.
        * loop-invariant.c (find_defs): Use df_live_set_loop_dirty
        instead of df_live_set_all_dirty.
        (move_loop_invariants): Mark all of live dirty at the end.

Index: gcc/df.h
===================================================================
--- gcc/df.h    (revision 270054)
+++ gcc/df.h    (working copy)
@@ -1023,6 +1023,7 @@ extern void df_lr_verify_transfer_functi
 extern void df_live_verify_transfer_functions (void);
 extern void df_live_add_problem (void);
 extern void df_live_set_all_dirty (void);
+extern void df_live_set_loop_dirty (struct loop *);
 extern void df_chain_add_problem (unsigned int);
 extern void df_word_lr_add_problem (void);
 extern bool df_word_lr_mark_ref (df_ref, bool, bitmap);
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c   (revision 270054)
+++ gcc/df-problems.c   (working copy)
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.
 #include "valtrack.h"
 #include "dumpfile.h"
 #include "rtl-iter.h"
+#include "cfgloop.h"
 
 /* Note that turning REG_DEAD_DEBUGGING on will cause
    gcc.c-torture/unsorted/dump-noaddr.c to fail because it prints
@@ -1774,6 +1775,19 @@ df_live_set_all_dirty (void)
 }
 
 
+/* Set all of the blocks of LOOP as dirty.  This needs to be done if this
+   problem is added after all of the insns have been scanned.  */
+
+void
+df_live_set_loop_dirty (struct loop *loop)
+{
+  basic_block *bbs = get_loop_body (loop);
+  for (unsigned i = 0; i < loop->num_nodes; ++i)
+    bitmap_set_bit (df_live->out_of_date_transfer_functions, bbs[i]->index);
+  free (bbs);
+}
+
+
 /* Verify that all of the lr related info is consistent and
    correct.  */
 
Index: gcc/loop-invariant.c
===================================================================
--- gcc/loop-invariant.c        (revision 270054)
+++ gcc/loop-invariant.c        (working copy)
@@ -685,7 +685,7 @@ find_defs (struct loop *loop)
   df_process_deferred_rescans ();
   df_chain_add_problem (DF_UD_CHAIN);
   df_live_add_problem ();
-  df_live_set_all_dirty ();
+  df_live_set_loop_dirty (loop);
   df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
   df_analyze_loop (loop);
   check_invariant_table_size ();
@@ -2286,5 +2286,9 @@ move_loop_invariants (void)
   invariant_table = NULL;
   invariant_table_size = 0;
 
+  /* Mark all of DF_LIVE dirty, we've likely not covered all blocks
+     sofar.  */
+  df_live_set_all_dirty ();
+
   checking_verify_flow_info ();
 }

Reply via email to