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.