This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix PR/15242
- From: Josef Zlomek <zlomj9am at artax dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Richard Henderson <rth at redhat dot com>
- Date: Wed, 26 May 2004 14:24:57 +0200
- Subject: Fix PR/15242
Hello,
this patch duplicates computed gotos as late as possible when bb-reorder
is enabled thus it makes the code not to contain jumps to computed jumps.
This is needed because bb-reorder avoids creating a dense CFG (PR/13430)
because it would slow down other optimizations. Thus it is better to
duplicate computed gotos as late as possible.
Bootstrapped/regtested x86-64.
Josef
2004-05-26 Josef Zlomek <zlomekj@suse.cz>
* passes.c (rest_of_compilation): Call duplicate_computed_gotos
when bb-reorder is enabled.
* 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.
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 26 May 2004 05:18:26 -0000
*************** rest_of_compilation (tree decl)
*** 1807,1812 ****
--- 1807,1816 ----
rest_of_handle_stack_regs (decl, insns);
#endif
+ if (optimize > 0
+ && (flag_reorder_blocks || flag_reorder_blocks_and_partition))
+ duplicate_computed_gotos ();
+
compute_alignments ();
if (flag_var_tracking)
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