This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix PR rtl-optimization/15242 - duplicate computed gotos


Hello,

this patch duplicates computed gotos so that there are no jumps to
computed jumps. This has a positive impact on performance.
The duplication is done as late as possible because it makes a dense CFG.

Bootstrapped/regtested x86-64.
OK?

Josef


2004-05-24  Josef Zlomek  <zlomekj@suse.cz>

	PR rtl-optimization/15242
	* basic-block.h (duplicate_computed_gotos): New.
	* bb-reorder.c (bb_insn_length): New, moved code from ...
	(copy_bb_p): ... here.
	(duplicate_computed_gotos): New.
	* passes.c (rest_of_compilation): Call duplicate_computed_gotos
	if compiling with optimization.

Index: basic-block.h
===================================================================
RCS file: /cvs/gcc-cvs/gcc/gcc/basic-block.h,v
retrieving revision 1.196
diff -c -p -r1.196 basic-block.h
*** basic-block.h	15 May 2004 09:39:28 -0000	1.196
--- basic-block.h	15 May 2004 22:00:00 -0000
*************** extern bool control_flow_insn_p (rtx);
*** 675,680 ****
--- 675,681 ----
  
  /* In bb-reorder.c */
  extern void reorder_basic_blocks (void);
+ extern void duplicate_computed_gotos (void);
  extern void partition_hot_cold_basic_blocks (void);
  
  /* In cfg.c */
Index: bb-reorder.c
===================================================================
RCS file: /cvs/gcc-cvs/gcc/gcc/bb-reorder.c,v
retrieving revision 1.74
diff -c -p -r1.74 bb-reorder.c
*** bb-reorder.c	13 May 2004 21:44:20 -0000	1.74
--- bb-reorder.c	24 May 2004 07:20:41 -0000
*************** connect_traces (int n_traces, struct tra
*** 1162,1176 ****
    FREE (cold_traces);
  }
  
  /* Return true when BB can and should be copied. CODE_MAY_GROW is true
     when code size is allowed to grow by duplication.  */
  
  static bool
  copy_bb_p (basic_block bb, int code_may_grow)
  {
!   int size = 0;
    int max_size = uncond_jump_length;
-   rtx insn;
    int n_succ;
    edge e;
  
--- 1162,1193 ----
    FREE (cold_traces);
  }
  
+ /* Return the total length of instructions in basic block BB.  */
+ 
+ static int
+ bb_insn_length (basic_block bb)
+ {
+   rtx insn;
+   int size = 0;
+ 
+   for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
+        insn = NEXT_INSN (insn))
+     {
+       if (INSN_P (insn))
+ 	size += get_attr_length (insn);
+     }
+ 
+   return size;
+ }
+ 
  /* Return true when BB can and should be copied. CODE_MAY_GROW is true
     when code size is allowed to grow by duplication.  */
  
  static bool
  copy_bb_p (basic_block bb, int code_may_grow)
  {
!   int size;
    int max_size = uncond_jump_length;
    int n_succ;
    edge e;
  
*************** copy_bb_p (basic_block bb, int code_may_
*** 1193,1205 ****
    if (code_may_grow && maybe_hot_bb_p (bb))
      max_size *= 8;
  
!   for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
!        insn = NEXT_INSN (insn))
!     {
!       if (INSN_P (insn))
! 	size += get_attr_length (insn);
!     }
! 
    if (size <= max_size)
      return true;
  
--- 1210,1216 ----
    if (code_may_grow && maybe_hot_bb_p (bb))
      max_size *= 8;
  
!   size = bb_insn_length (bb);
    if (size <= max_size)
      return true;
  
*************** reorder_basic_blocks (void)
*** 1964,1969 ****
--- 1975,2046 ----
    timevar_pop (TV_REORDER_BLOCKS);
  }
  
+ /* Duplicate the blocks containing computed gotos.  */
+ 
+ void
+ duplicate_computed_gotos (void)
+ {
+   basic_block bb, new_bb;
+   int max_size;
+ 
+   if (n_basic_blocks <= 1)
+     return;
+ 
+   if (!cfun->computed_goto_common_label)
+     return;
+ 
+   if (targetm.cannot_modify_jumps_p ())
+     return;
+ 
+   timevar_push (TV_REORDER_BLOCKS);
+ 
+   cfg_layout_initialize ();
+ 
+   /* We are estimating the length of uncond jump insn only once since the code
+      for getting the insn length always returns the minimal length now.  */
+   if (uncond_jump_length == 0)
+     uncond_jump_length = get_uncond_jump_length ();
+ 
+   /* Build the reorder chain for the original order of blocks.  */ 
+   FOR_EACH_BB (bb)
+     {
+       if (bb->next_bb != EXIT_BLOCK_PTR)
+ 	bb->rbi->next = bb->next_bb;
+     }
+ 
+   /* Duplicate computed gotos.  */
+   max_size = optimize_size ? uncond_jump_length : 4 * uncond_jump_length;
+   FOR_EACH_BB (bb)
+     {
+       if (bb->rbi->visited)
+ 	continue;
+ 
+       bb->rbi->visited = 1;
+ 
+       if (/* BB has one outgoing edge which is not an edge to exit block.  */
+ 	  bb->succ && !bb->succ->succ_next && bb->succ->dest != EXIT_BLOCK_PTR
+ 	  /* Do not duplicate the successor if it is the next block,
+ 	     duplicate it in other cases.  */
+ 	  && bb->succ->dest != bb->next_bb
+ 	  /* The destination has more than one predecessor.  */
+ 	  && bb->succ->dest->pred && bb->succ->dest->pred->pred_next
+ 	  /* The last insn is a computed jump.  */
+ 	  && computed_jump_p (BB_END (bb->succ->dest))
+ 	  /* The block is small enough.  */
+ 	  && bb_insn_length (bb->succ->dest) <= max_size)
+ 	{
+ 	  new_bb = duplicate_block (bb->succ->dest, bb->succ);
+ 	  new_bb->rbi->next = bb->rbi->next;
+ 	  bb->rbi->next = new_bb;
+ 	  new_bb->rbi->visited = 1;
+ 	}
+     }
+ 
+   cfg_layout_finalize ();
+ 
+   timevar_pop (TV_REORDER_BLOCKS);
+ }
+ 
  /* This function is the main 'entrance' for the optimization that
     partitions hot and cold basic blocks into separate sections of the
     .o file (to improve performance and cache locality).  Ideally it
Index: passes.c
===================================================================
RCS file: /cvs/gcc-cvs/gcc/gcc/passes.c,v
retrieving revision 2.15
diff -c -p -r2.15 passes.c
*** passes.c	20 May 2004 11:45:26 -0000	2.15
--- passes.c	24 May 2004 06:07:24 -0000
*************** rest_of_compilation (tree decl)
*** 1807,1812 ****
--- 1807,1815 ----
    rest_of_handle_stack_regs (decl, insns);
  #endif
  
+   if (optimize > 0)
+     duplicate_computed_gotos ();
+ 
    compute_alignments ();
  
    if (flag_var_tracking)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]