Faster optimize_mode_switching
Jan Hubicka
jh@suse.cz
Mon Jan 14 12:39:00 GMT 2002
Hi,
this patch makes optimize_mode_switching to not rebuild whole life information from
the scratch after emitting code. This is done via new interface using BB flags - the
primitives to change insn stream set BB_DIRTY flag of clobbered basic block and life
info is updated on all such block, so it is easy to track down changes done
by commit_edge_insertions etc.
I plan to use the frameword for hard-reg-clobber-safe gcse patch, but I would like
to see this part in mainline, as it tends to save some time in large FP functions
and I hope the design is robust enought to make it safe and optimize_mode_switching
and his life info rebuild is one of major CPU hogs in nonoptimizing compilation.
It has passed mainline bootstrap/regtesting. I will bootstrap and install it to
cfg branch once I manage to fix the bootstrap failure I got after last mainline merger.
Honza
Mon Jan 14 23:43:26 CET 2002 Jan Hubicka <jh@suse.cz>
* basic-block.h (BB_NEW, BB_DIRTY): New flags.
(clear_bb_flags, update_life_info_in_dirty_blocks): New.
* cfg.c (clear_bb_flags): New function.
* cfgrtl.c (create_basic_block_structures): Set BB_NEW flag.
* emit-rtl.c (add_insn_after, add_insn_before, remove_insn,
reorder_insns, emit_insns_after): Set BB_DIRTY flags.
* flow.c (update_life_info_in_dirty_blocks): New function.
* lcm.c (optimize_mode_switching): Do nor rebuild whole life info.
* recog.c (apply_change_group): Set BB_DIRTY flags.
* toplev.c (rest_of_compilation): Do not set register_life_up_to_date
after optimize_mode_switching.
*** basic-block.h.nl Mon Jan 14 23:05:23 2002
--- basic-block.h Mon Jan 14 23:17:17 2002
*************** typedef struct basic_block_def {
*** 222,228 ****
#define BB_FREQ_MAX 10000
/* Masks for basic_block.flags. */
! #define BB_REACHABLE 1
/* Number of basic blocks in the current function. */
--- 222,230 ----
#define BB_FREQ_MAX 10000
/* Masks for basic_block.flags. */
! #define BB_DIRTY 1
! #define BB_NEW 2
! #define BB_REACHABLE 4
/* Number of basic blocks in the current function. */
*************** extern void redirect_edge_pred PARAMS (
*** 313,318 ****
--- 315,321 ----
extern basic_block create_basic_block_structure PARAMS ((int, rtx, rtx, rtx));
extern basic_block create_basic_block PARAMS ((int, rtx, rtx));
extern int flow_delete_block PARAMS ((basic_block));
+ extern void clear_bb_flags PARAMS ((void));
extern void merge_blocks_nomove PARAMS ((basic_block, basic_block));
extern void tidy_fallthru_edge PARAMS ((edge, basic_block,
basic_block));
*************** enum update_life_extent
*** 600,605 ****
--- 603,610 ----
extern void life_analysis PARAMS ((rtx, FILE *, int));
extern void update_life_info PARAMS ((sbitmap, enum update_life_extent,
int));
+ extern void update_life_info_in_dirty_blocks PARAMS ((enum update_life_extent,
+ int));
extern int count_or_remove_death_notes PARAMS ((sbitmap, int));
extern int propagate_block PARAMS ((basic_block, regset, regset, regset,
int));
*** cfg.c.nl Mon Jan 14 23:09:32 2002
--- cfg.c Mon Jan 14 23:18:22 2002
*************** Software Foundation, 59 Temple Place - S
*** 38,43 ****
--- 38,44 ----
dump_flow_info, debug_flow_info, dump_edge_info
- Allocation of AUX fields for basic blocks
alloc_aux_for_blocks, free_aux_for_blocks, alloc_aux_for_block
+ - clear_bb_flags
*/
#include "config.h"
*************** redirect_edge_pred (e, new_pred)
*** 439,444 ****
--- 440,455 ----
e->succ_next = new_pred->succ;
new_pred->succ = e;
e->src = new_pred;
+ }
+
+ void
+ clear_bb_flags ()
+ {
+ int i;
+ ENTRY_BLOCK_PTR->flags = 0;
+ EXIT_BLOCK_PTR->flags = 0;
+ for (i = 0; i < n_basic_blocks; i++)
+ BASIC_BLOCK (i)->flags = 0;
}
void
*** cfgrtl.c.nl Mon Jan 14 23:11:09 2002
--- cfgrtl.c Mon Jan 14 23:11:05 2002
*************** create_basic_block_structure (index, hea
*** 270,275 ****
--- 270,276 ----
bb->head = head;
bb->end = end;
bb->index = index;
+ bb->flags = BB_NEW;
BASIC_BLOCK (index) = bb;
if (basic_block_for_insn)
update_bb_for_insn (bb);
*** emit-rtl.c.nl Mon Jan 14 23:06:09 2002
--- emit-rtl.c Mon Jan 14 23:20:23 2002
*************** add_insn_after (insn, after)
*** 3250,3255 ****
--- 3250,3257 ----
&& (bb = BLOCK_FOR_INSN (after)))
{
set_block_for_insn (insn, bb);
+ if (INSN_P (insn))
+ bb->flags |= BB_DIRTY;
/* Should not happen as first in the BB is always
either NOTE or LABEL. */
if (bb->end == after
*************** add_insn_before (insn, before)
*** 3317,3322 ****
--- 3319,3326 ----
&& (bb = BLOCK_FOR_INSN (before)))
{
set_block_for_insn (insn, bb);
+ if (INSN_P (insn))
+ bb->flags |= BB_DIRTY;
/* Should not happen as first in the BB is always
either NOTE or LABEl. */
if (bb->head == insn
*************** remove_insn (insn)
*** 3394,3399 ****
--- 3398,3405 ----
&& (unsigned int)INSN_UID (insn) < basic_block_for_insn->num_elements
&& (bb = BLOCK_FOR_INSN (insn)))
{
+ if (INSN_P (insn))
+ bb->flags |= BB_DIRTY;
if (bb->head == insn)
{
/* Never ever delete the basic block note without deleting whole basic
*************** reorder_insns (from, to, after)
*** 3471,3476 ****
--- 3477,3485 ----
&& (bb = BLOCK_FOR_INSN (after)))
{
rtx x;
+ bb->flags |= BB_DIRTY;
+
+ bb->flags |= BB_DIRTY;
if (basic_block_for_insn
&& (unsigned int)INSN_UID (from) < basic_block_for_insn->num_elements
*************** reorder_insns (from, to, after)
*** 3478,3483 ****
--- 3487,3493 ----
{
if (bb2->end == to)
bb2->end = prev;
+ bb2->flags |= BB_DIRTY;
}
if (bb->end == after)
*************** emit_insns_after (first, after)
*** 4001,4006 ****
--- 4011,4017 ----
&& (unsigned int)INSN_UID (after) < basic_block_for_insn->num_elements
&& (bb = BLOCK_FOR_INSN (after)))
{
+ bb->flags |= BB_DIRTY;
for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
set_block_for_insn (last, bb);
set_block_for_insn (last, bb);
*** flow.c.nl Mon Jan 14 23:13:47 2002
--- flow.c Mon Jan 14 23:29:10 2002
*************** update_life_info (blocks, extent, prop_f
*** 741,746 ****
--- 741,764 ----
? TV_LIFE_UPDATE : TV_LIFE);
}
+ /* Update life information in all blocks where BB_DIRTY is set. */
+
+ void
+ update_life_info_in_dirty_blocks (extent, prop_flags)
+ enum update_life_extent extent;
+ int prop_flags;
+ {
+ sbitmap update_life_blocks = sbitmap_alloc (n_basic_blocks);
+ int block_num;
+
+ sbitmap_zero (update_life_blocks);
+ for (block_num = 0; block_num < n_basic_blocks; block_num++)
+ if (BASIC_BLOCK (block_num)->flags & BB_DIRTY)
+ SET_BIT (update_life_blocks, block_num);
+ update_life_info (update_life_blocks, extent, prop_flags);
+ sbitmap_free (update_life_blocks);
+ }
+
/* Free the variables allocated by find_basic_blocks.
KEEP_HEAD_END_P is non-zero if basic_block_info is not to be freed. */
*** lcm.c.nl Mon Jan 14 23:41:47 2002
--- lcm.c Mon Jan 14 23:43:11 2002
*************** optimize_mode_switching (file)
*** 1031,1036 ****
--- 1031,1037 ----
int max_num_modes = 0;
bool emited = false;
+ clear_bb_flags ();
#ifdef NORMAL_MODE
/* Increment n_basic_blocks before allocating bb_info. */
n_basic_blocks++;
*************** optimize_mode_switching (file)
*** 1398,1413 ****
if (!need_commit && !emited)
return 0;
! /* Ideally we'd figure out what blocks were affected and start from
! there, but this is enormously complicated by commit_edge_insertions,
! which would screw up any indices we'd collected, and also need to
! be involved in the update. Bail and recompute global life info for
! everything. */
!
! allocate_reg_life_data ();
! update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
! (PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
! | PROP_SCAN_DEAD_CODE | PROP_REG_INFO));
return 1;
}
--- 1399,1407 ----
if (!need_commit && !emited)
return 0;
! update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
! (PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
! | PROP_SCAN_DEAD_CODE));
return 1;
}
*** recog.c.nl Mon Jan 14 23:08:31 2002
--- recog.c Mon Jan 14 23:33:36 2002
*************** apply_change_group ()
*** 392,397 ****
--- 392,408 ----
if (i == num_changes)
{
+ basic_block bb;
+
+ for (i = 0; i < num_changes; i++)
+ if (changes[i].object
+ && INSN_P (changes[i].object)
+ && basic_block_for_insn
+ && ((unsigned int)INSN_UID (changes[i].object)
+ < basic_block_for_insn->num_elements)
+ && (bb = BLOCK_FOR_INSN (changes[i].object)))
+ bb->flags |= BB_DIRTY;
+
num_changes = 0;
return 1;
}
*** toplev.c.nl Mon Jan 14 23:36:21 2002
--- toplev.c Mon Jan 14 23:36:38 2002
*************** rest_of_compilation (decl)
*** 3232,3244 ****
timevar_push (TV_MODE_SWITCH);
no_new_pseudos = 0;
! if (optimize_mode_switching (NULL))
! {
! /* We did work, and so had to regenerate global life information.
! Take advantage of this and don't re-recompute register life
! information below. */
! register_life_up_to_date = 1;
! }
no_new_pseudos = 1;
timevar_pop (TV_MODE_SWITCH);
--- 3232,3238 ----
timevar_push (TV_MODE_SWITCH);
no_new_pseudos = 0;
! optimize_mode_switching (NULL);
no_new_pseudos = 1;
timevar_pop (TV_MODE_SWITCH);
More information about the Gcc-patches
mailing list