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 (); }