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