/* Perform branch target register load optimizations.
- Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
#include "function.h"
#include "except.h"
#include "tm_p.h"
+#include "toplev.h"
+#include "tree-pass.h"
/* Target register optimizations - these are performed after reload. */
CLEAR_HARD_REG_SET (info.btrs_written_in_block);
for (reg = first_btr; reg <= last_btr; reg++)
if (TEST_HARD_REG_BIT (all_btrs, reg)
- && REGNO_REG_SET_P (bb->global_live_at_start, reg))
+ && REGNO_REG_SET_P (bb->il.rtl->global_live_at_start, reg))
SET_HARD_REG_BIT (info.btrs_live_in_block, reg);
for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb));
SET_BIT (btr_defset[regno - first_btr], insn_uid);
note_other_use_this_block (regno, info.users_this_bb);
}
+ /* Check for the blockage emitted by expand_nl_goto_receiver. */
+ else if (current_function_has_nonlocal_label
+ && GET_CODE (PATTERN (insn)) == ASM_INPUT)
+ {
+ btr_user user;
+
+ /* Do the equivalent of calling note_other_use_this_block
+ for every target register. */
+ for (user = info.users_this_bb; user != NULL;
+ user = user->next)
+ if (user->use)
+ user->other_use_this_block = 1;
+ IOR_HARD_REG_SET (info.btrs_written_in_block, all_btrs);
+ IOR_HARD_REG_SET (info.btrs_live_in_block, all_btrs);
+ sbitmap_zero (info.bb_gen);
+ }
else
{
if (btr_referenced_p (PATTERN (insn), NULL))
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);
+ REG_SET_TO_HARD_REG_SET (btrs_live_at_end[i], bb->il.rtl->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); )
{
/* Find all the reaching defs for this use. */
sbitmap reaching_defs_of_reg = sbitmap_alloc(max_uid);
- int uid;
+ unsigned int uid = 0;
+ sbitmap_iterator sbi;
if (user->use)
sbitmap_a_and_b (
reaching_defs,
btr_defset[reg - first_btr]);
}
- EXECUTE_IF_SET_IN_SBITMAP (reaching_defs_of_reg, 0, uid,
+ EXECUTE_IF_SET_IN_SBITMAP (reaching_defs_of_reg, 0, uid, sbi)
{
btr_def def = def_array[uid];
def->other_btr_uses_after_use = 1;
user->next = def->uses;
def->uses = user;
- });
+ }
sbitmap_free (reaching_defs_of_reg);
}
def->bb, user->bb,
(flag_btr_bb_exclusive
|| user->insn != BB_END (def->bb)
- || GET_CODE (user->insn) != JUMP_INSN));
+ || !JUMP_P (user->insn)));
}
else
{
def->bb, user->bb,
(flag_btr_bb_exclusive
|| user->insn != BB_END (def->bb)
- || GET_CODE (user->insn) != JUMP_INSN));
+ || !JUMP_P (user->insn)));
btr = choose_btr (combined_btrs_live);
if (btr != -1)
PROP_DEATH_NOTES | PROP_REG_INFO);
}
}
+\f
+static bool
+gate_handle_branch_target_load_optimize (void)
+{
+ return (optimize > 0 && flag_branch_target_load_optimize2);
+}
+
+
+static void
+rest_of_handle_branch_target_load_optimize (void)
+{
+ static int warned = 0;
+
+ /* Leave this a warning for now so that it is possible to experiment
+ with running this pass twice. In 3.6, we should either make this
+ an error, or use separate dump files. */
+ if (flag_branch_target_load_optimize
+ && flag_branch_target_load_optimize2
+ && !warned)
+ {
+ warning (0, "branch target register load optimization is not intended "
+ "to be run twice");
+
+ warned = 1;
+ }
+
+ branch_target_load_optimize (epilogue_completed);
+}
+
+struct tree_opt_pass pass_branch_target_load_optimize =
+{
+ "btl", /* name */
+ gate_handle_branch_target_load_optimize, /* gate */
+ rest_of_handle_branch_target_load_optimize, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func |
+ TODO_ggc_collect, /* todo_flags_finish */
+ 'd' /* letter */
+};
+