diff options
-rw-r--r-- | gcc/ChangeLog | 32 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/bt-load.c | 97 | ||||
-rw-r--r-- | gcc/common.opt | 6 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 8 | ||||
-rw-r--r-- | gcc/flags.h | 6 | ||||
-rw-r--r-- | gcc/opts.c | 4 | ||||
-rw-r--r-- | gcc/toplev.c | 6 |
8 files changed, 143 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e4319c734ed..1e5bfa2f723 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2004-01-27 J"orn Rennecke <joern.rennecke@superh.com> + + * Makefile.in (bt-load.o): Depend on except.h. + * bt-load.c (except.h): #include. + (compute_defs_uses_and_gen): If insn at end of BB can throw + within this function, consider registers used by it unavailable for + btr migration. + (move_btr_def): If insn at end of BB can throw, insert before rather + than after. + + * flags.h (flag_btr_bb_exclusive): Declare. + * toplev.c (flag_btr_bb_exclusive): New variable. + (f_options): Add btr-bb-exclusive. + * bt-load.c (augment_live_range): Restore old behaviour if + flag_btr_bb_exclusive is set. + * common.opt: Add entry for -fbtr-bb-exclusive. + * opts.c (common_handle_options): Same. + * doc/invoke.texi: Document -fbtr-bb-exclusive. + + * bt-load.c (btrs_live_at_end): New variable. + (compute_defs_uses_and_gen): Compute its pointed-to array. + (clear_btr_from_live_range, add_btr_to_live_range): Update it. + (augment_live_range): When augmenting with a new dominator, + use only its btrs_live_at_end set, but also add in the full set + of the old dominator. + (btr_def_live_range): Use btrs_live_at_end. + (move_btr_def): Set other_btr_uses_before_def, and move new set + to the end of the basic block, if appropriate. + (migrate_btr_defs): Allocate and free btrs_live_at_end. + + * bt-load.c (basic_block_freq): Remove outdated comment. + 2004-01-27 Alan Modra <amodra@bigpond.net.au> * config/rs6000/rs6000.h: Correct target_flags free bits comment. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 6f7291b08b0..98c07f2e453 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1760,7 +1760,7 @@ postreload.o : postreload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) caller-save.o : caller-save.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ flags.h $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) function.h \ $(RECOG_H) reload.h $(EXPR_H) toplev.h $(TM_P_H) -bt-load.o : bt-load.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ +bt-load.o : bt-load.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) except.h \ $(BASIC_BLOCK_H) $(RTL_H) hard-reg-set.h $(REGS_H) $(OBSTACK_H) $(TM_P_H) \ $(FIBHEAP_H) output.h $(TARGET_H) $(EXPR_H) flags.h $(INSN_ATTR_H) reorg.o : reorg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) conditions.h \ diff --git a/gcc/bt-load.c b/gcc/bt-load.c index 2a68cd76bdb..9b8f598d0c5 100644 --- a/gcc/bt-load.c +++ b/gcc/bt-load.c @@ -1,5 +1,5 @@ /* Perform branch target register load optimizations. - Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -36,6 +36,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "flags.h" #include "insn-attr.h" #include "function.h" +#include "except.h" #include "tm_p.h" /* Target register optimizations - these are performed after reload. */ @@ -159,6 +160,10 @@ static struct obstack migrate_btrl_obstack; live in that block. */ static HARD_REG_SET *btrs_live; +/* Array indexed by basic block number, giving the set of registers live at + the end of that block, including any uses by a final jump insn, if any. */ +static HARD_REG_SET *btrs_live_at_end; + /* Set of all target registers that we are willing to allocate. */ static HARD_REG_SET all_btrs; @@ -168,8 +173,7 @@ static int first_btr, last_btr; -/* Return an estimate of the frequency of execution of block bb. - If we have a profiling count available, we could use it here. */ +/* Return an estimate of the frequency of execution of block bb. */ static int basic_block_freq (basic_block bb) { @@ -462,6 +466,7 @@ compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array, btr_def defs_this_bb = NULL; rtx insn; rtx last; + int can_throw = 0; info.users_this_bb = NULL; info.bb_gen = bb_gen[i]; @@ -544,7 +549,7 @@ compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array, call_used_reg_set); clobbered = &call_saved; } - + for (regno = first_btr; regno <= last_btr; regno++) if (TEST_HARD_REG_BIT (*clobbered, regno)) note_btr_set (regno_reg_rtx[regno], NULL_RTX, &info); @@ -555,6 +560,35 @@ compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array, COPY_HARD_REG_SET (btrs_live[i], info.btrs_live_in_block); COPY_HARD_REG_SET (btrs_written[i], info.btrs_written_in_block); + + REG_SET_TO_HARD_REG_SET (btrs_live_at_end[i], bb->global_live_at_end); + /* If this block ends in a jump insn, add any uses or even clobbers + of branch target registers that it might have. */ + for (insn = BB_END (bb); insn != BB_HEAD (bb) && ! INSN_P (insn); ) + insn = PREV_INSN (insn); + /* ??? for the fall-through edge, it would make sense to insert the + btr set on the edge, but that would require to split the block + early on so that we can distinguish between dominance from the fall + through edge - which can use the call-clobbered registers - from + dominance by the throw edge. */ + if (can_throw_internal (insn)) + { + HARD_REG_SET tmp; + + COPY_HARD_REG_SET (tmp, call_used_reg_set); + AND_HARD_REG_SET (tmp, all_btrs); + IOR_HARD_REG_SET (btrs_live_at_end[i], tmp); + can_throw = 1; + } + if (can_throw || GET_CODE (insn) == JUMP_INSN) + { + int regno; + + for (regno = first_btr; regno <= last_btr; regno++) + if (refers_to_regno_p (regno, regno+1, insn, NULL)) + SET_HARD_REG_BIT (btrs_live_at_end[i], regno); + } + if (rtl_dump_file) dump_btrs_live(i); } @@ -797,6 +831,7 @@ clear_btr_from_live_range (btr_def def) || !block_at_edge_of_live_range_p (bb, def)) { CLEAR_HARD_REG_BIT (btrs_live[bb], def->btr); + CLEAR_HARD_REG_BIT (btrs_live_at_end[bb], def->btr); if (rtl_dump_file) dump_btrs_live (bb); } @@ -815,6 +850,7 @@ add_btr_to_live_range (btr_def def) (def->live_range, 0, bb, { SET_HARD_REG_BIT (btrs_live[bb], def->btr); + SET_HARD_REG_BIT (btrs_live_at_end[bb], def->btr); if (rtl_dump_file) dump_btrs_live (bb); }); @@ -845,11 +881,18 @@ augment_live_range (bitmap live_range, HARD_REG_SET *btrs_live_in_range, int new_block = new_bb->index; bitmap_set_bit (live_range, new_block); - IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[new_block]); + if (flag_btr_bb_exclusive) + IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[new_block]); + else + { + IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live_at_end[new_block]); + IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[head_bb->index]); + } if (rtl_dump_file) { fprintf (rtl_dump_file, - "Adding block %d to live range\n", new_block); + "Adding end of block %d and rest of %d to live range\n", + new_block, head_bb->index); fprintf (rtl_dump_file,"Now live btrs are "); dump_hard_reg_set (*btrs_live_in_range); fprintf (rtl_dump_file, "\n"); @@ -929,7 +972,11 @@ btr_def_live_range (btr_def def, HARD_REG_SET *btrs_live_in_range) def->live_range = BITMAP_XMALLOC (); bitmap_set_bit (def->live_range, def->bb->index); - COPY_HARD_REG_SET (*btrs_live_in_range, btrs_live[def->bb->index]); + if (flag_btr_bb_exclusive) + COPY_HARD_REG_SET (*btrs_live_in_range, btrs_live[def->bb->index]); + else + COPY_HARD_REG_SET (*btrs_live_in_range, + btrs_live_at_end[def->bb->index]); for (user = def->uses; user != NULL; user = user->next) augment_live_range (def->live_range, btrs_live_in_range, @@ -942,14 +989,23 @@ btr_def_live_range (btr_def def, HARD_REG_SET *btrs_live_in_range) of other PT instructions may have affected it. */ int bb; + int def_bb = def->bb->index; CLEAR_HARD_REG_SET (*btrs_live_in_range); - EXECUTE_IF_SET_IN_BITMAP - (def->live_range, 0, bb, - { - IOR_HARD_REG_SET (*btrs_live_in_range, - btrs_live[bb]); - }); + if (flag_btr_bb_exclusive) + EXECUTE_IF_SET_IN_BITMAP + (def->live_range, 0, bb, + { + IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[bb]); + }); + else + EXECUTE_IF_SET_IN_BITMAP + (def->live_range, 0, bb, + { + IOR_HARD_REG_SET (*btrs_live_in_range, + (def_bb == bb + ? btrs_live_at_end : btrs_live) [bb]); + }); } if (!def->other_btr_uses_before_def && !def->other_btr_uses_after_use) @@ -1073,7 +1129,8 @@ move_btr_def (basic_block new_def_bb, int btr, btr_def def, bitmap live_range, def->bb = new_def_bb; def->luid = 0; def->cost = basic_block_freq (new_def_bb); - def->other_btr_uses_before_def = 0; + def->other_btr_uses_before_def + = TEST_HARD_REG_BIT (btrs_live[b->index], btr) ? 1 : 0; bitmap_copy (def->live_range, live_range); combine_btr_defs (def, btrs_live_in_range); btr = def->btr; @@ -1085,6 +1142,16 @@ move_btr_def (basic_block new_def_bb, int btr, btr_def def, bitmap live_range, its basic block. */ /* ?? some assertions to check that insp is sensible? */ + if (def->other_btr_uses_before_def) + { + insp = BB_END (b); + for (insp = BB_END (b); ! INSN_P (insp); insp = PREV_INSN (insp)) + if (insp == BB_HEAD (b)) + abort (); + if (GET_CODE (insp) == JUMP_INSN || can_throw_internal (insp)) + insp = PREV_INSN (insp); + } + set = single_set (old_insn); src = SET_SRC (set); btr_mode = GET_MODE (SET_DEST (set)); @@ -1312,6 +1379,7 @@ migrate_btr_defs (enum reg_class btr_class, int allow_callee_save) } btrs_live = xcalloc (n_basic_blocks, sizeof (HARD_REG_SET)); + btrs_live_at_end = xcalloc (n_basic_blocks, sizeof (HARD_REG_SET)); build_btr_def_use_webs (all_btr_defs); @@ -1338,6 +1406,7 @@ migrate_btr_defs (enum reg_class btr_class, int allow_callee_save) } free (btrs_live); + free (btrs_live_at_end); obstack_free (&migrate_btrl_obstack, NULL); fibheap_delete (all_btr_defs); } diff --git a/gcc/common.opt b/gcc/common.opt index 302dfac6709..a384b0400ee 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1,5 +1,5 @@ ; Options for the language- and target-independent parts of the compiler. -; Copyright (C) 2003 Free Software Foundation, Inc. +; Copyright (C) 2003, 2004 Free Software Foundation, Inc. ; ; This file is part of GCC. ; @@ -243,6 +243,10 @@ fbranch-target-load-optimize2 Common Perform branch target load optimization after prologue / epilogue threading +fbtr-bb-exclusive +Common +Restrict target load migration not to re-use registers in any basic block + fcall-saved- Common Joined RejectNegative -fcall-saved-<register> Mark <register> as being preserved across functions diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 8620e6fb1ba..c21bdf370be 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -264,7 +264,8 @@ in the following sections. @gccoptlist{-falign-functions=@var{n} -falign-jumps=@var{n} @gol -falign-labels=@var{n} -falign-loops=@var{n} @gol -fbranch-probabilities -fprofile-values -fvpt -fbranch-target-load-optimize @gol --fbranch-target-load-optimize2 -fcaller-saves -fcprop-registers @gol +-fbranch-target-load-optimize2 -fbtr-bb-exclusive @gol +-fcaller-saves -fcprop-registers @gol -fcse-follow-jumps -fcse-skip-blocks -fdata-sections @gol -fdelayed-branch -fdelete-null-pointer-checks @gol -fexpensive-optimizations -ffast-math -ffloat-store @gol @@ -4651,6 +4652,11 @@ a separate optimization pass. Perform branch target register load optimization after prologue / epilogue threading. +@item -fbtr-bb-exclusive +@opindex fbtr-bb-exclusive +WHen performing branch target register load optimization, don't reuse +branch target registers in within any basic block. + @item --param @var{name}=@var{value} @opindex param In some places, GCC uses various constants to control the amount of diff --git a/gcc/flags.h b/gcc/flags.h index f172ec34a8b..370fb0a1936 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -1,6 +1,6 @@ /* Compilation switch flag definitions for GCC. Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, - 2003 + 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -689,6 +689,10 @@ extern int flag_branch_target_load_optimize; extern int flag_branch_target_load_optimize2; +/* For the bt-load pass, nonzero means don't re-use branch target registers + in any basic block. */ +extern int flag_btr_bb_exclusive; + /* Nonzero means we should do dwarf2 duplicate elimination. */ diff --git a/gcc/opts.c b/gcc/opts.c index e87accea947..2f07d6d7f02 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -901,6 +901,10 @@ common_handle_option (size_t scode, const char *arg, flag_branch_target_load_optimize2 = value; break; + case OPT_fbtr_bb_exclusive: + flag_btr_bb_exclusive = value; + break; + case OPT_fcall_used_: fix_register (arg, 0, 1); break; diff --git a/gcc/toplev.c b/gcc/toplev.c index 4d16201c177..425f94ea6af 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -711,6 +711,11 @@ int flag_branch_target_load_optimize = 0; int flag_branch_target_load_optimize2 = 0; +/* For the bt-load pass, nonzero means don't re-use branch target registers + in any basic block. */ + +int flag_btr_bb_exclusive; + /* Nonzero means to rerun cse after loop optimization. This increases compilation time about 20% and picks up a few more common expressions. */ @@ -1064,6 +1069,7 @@ static const lang_independent_options f_options[] = {"gcse-las", &flag_gcse_las, 1 }, {"branch-target-load-optimize", &flag_branch_target_load_optimize, 1 }, {"branch-target-load-optimize2", &flag_branch_target_load_optimize2, 1 }, + {"btr-bb-exclusive", &flag_btr_bb_exclusive, 1 }, {"loop-optimize", &flag_loop_optimize, 1 }, {"crossjumping", &flag_crossjumping, 1 }, {"if-conversion", &flag_if_conversion, 1 }, |