summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog32
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/bt-load.c97
-rw-r--r--gcc/common.opt6
-rw-r--r--gcc/doc/invoke.texi8
-rw-r--r--gcc/flags.h6
-rw-r--r--gcc/opts.c4
-rw-r--r--gcc/toplev.c6
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 },