+
/* Perform branch target register load optimizations.
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "rtl.h"
#include "hard-reg-set.h"
#include "regs.h"
-#include "fibheap.h"
-#include "output.h"
#include "target.h"
-#include "expr.h"
+#include "symtab.h"
+#include "function.h"
#include "flags.h"
+#include "alias.h"
+#include "tree.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
+#include "expr.h"
#include "insn-attr.h"
-#include "function.h"
#include "except.h"
#include "tm_p.h"
#include "diagnostic-core.h"
#include "tree-pass.h"
#include "recog.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "cfgcleanup.h"
+#include "predict.h"
+#include "basic-block.h"
#include "df.h"
+#include "cfgloop.h"
+#include "rtl-iter.h"
+#include "fibonacci_heap.h"
/* Target register optimizations - these are performed after reload. */
struct btr_user_s *next;
basic_block bb;
int luid;
- rtx insn;
+ rtx_insn *insn;
/* If INSN has a single use of a single branch register, then
USE points to it within INSN. If there is more than
one branch register use, or the use is in some way ambiguous,
struct btr_def_s *next_this_group;
basic_block bb;
int luid;
- rtx insn;
+ rtx_insn *insn;
int btr;
int cost;
/* For a branch register setting insn that has a constant
bitmap live_range;
} *btr_def;
+typedef fibonacci_heap <long, btr_def_s> btr_heap_t;
+typedef fibonacci_node <long, btr_def_s> btr_heap_node_t;
+
static int issue_rate;
static int basic_block_freq (const_basic_block);
-static int insn_sets_btr_p (const_rtx, int, int *);
-static rtx *find_btr_use (rtx);
-static int btr_referenced_p (rtx, rtx *);
-static int find_btr_reference (rtx *, void *);
+static int insn_sets_btr_p (const rtx_insn *, int, int *);
static void find_btr_def_group (btr_def_group *, btr_def);
-static btr_def add_btr_def (fibheap_t, basic_block, int, rtx,
+static btr_def add_btr_def (btr_heap_t *, basic_block, int, rtx_insn *,
unsigned int, int, btr_def_group *);
-static btr_user new_btr_user (basic_block, int, rtx);
+static btr_user new_btr_user (basic_block, int, rtx_insn *);
static void dump_hard_reg_set (HARD_REG_SET);
static void dump_btrs_live (int);
static void note_other_use_this_block (unsigned int, btr_user);
-static void compute_defs_uses_and_gen (fibheap_t, btr_def *,btr_user *,
+static void compute_defs_uses_and_gen (btr_heap_t *, btr_def *,btr_user *,
sbitmap *, sbitmap *, HARD_REG_SET *);
static void compute_kill (sbitmap *, sbitmap *, HARD_REG_SET *);
static void compute_out (sbitmap *bb_out, sbitmap *, sbitmap *, int);
static void link_btr_uses (btr_def *, btr_user *, sbitmap *, sbitmap *, int);
-static void build_btr_def_use_webs (fibheap_t);
+static void build_btr_def_use_webs (btr_heap_t *);
static int block_at_edge_of_live_range_p (int, btr_def);
static void clear_btr_from_live_range (btr_def def);
static void add_btr_to_live_range (btr_def, int);
static void move_btr_def (basic_block, int, btr_def, bitmap, HARD_REG_SET *);
static int migrate_btr_def (btr_def, int);
static void migrate_btr_defs (enum reg_class, int);
-static int can_move_up (const_basic_block, const_rtx, int);
+static int can_move_up (const_basic_block, const rtx_insn *, int);
static void note_btr_set (rtx, const_rtx, void *);
\f
/* The following code performs code motion of target load instructions
return bb->frequency;
}
-static rtx *btr_reference_found;
-
-/* A subroutine of btr_referenced_p, called through for_each_rtx.
- PREG is a pointer to an rtx that is to be excluded from the
- traversal. If we find a reference to a target register anywhere
- else, return 1, and put a pointer to it into btr_reference_found. */
-static int
-find_btr_reference (rtx *px, void *preg)
+/* If X references (sets or reads) any branch target register, return one
+ such register. If EXCLUDEP is set, disregard any references within
+ that location. */
+static rtx *
+find_btr_use (rtx x, rtx *excludep = 0)
{
- rtx x;
-
- if (px == preg)
- return -1;
- x = *px;
- if (!REG_P (x))
- return 0;
- if (overlaps_hard_reg_set_p (all_btrs, GET_MODE (x), REGNO (x)))
+ subrtx_ptr_iterator::array_type array;
+ FOR_EACH_SUBRTX_PTR (iter, array, &x, NONCONST)
{
- btr_reference_found = px;
- return 1;
+ rtx *loc = *iter;
+ if (loc == excludep)
+ iter.skip_subrtxes ();
+ else
+ {
+ const_rtx x = *loc;
+ if (REG_P (x)
+ && overlaps_hard_reg_set_p (all_btrs, GET_MODE (x), REGNO (x)))
+ return loc;
+ }
}
- return -1;
-}
-
-/* Return nonzero if X references (sets or reads) any branch target register.
- If EXCLUDEP is set, disregard any references within the rtx pointed to
- by it. If returning nonzero, also set btr_reference_found as above. */
-static int
-btr_referenced_p (rtx x, rtx *excludep)
-{
- return for_each_rtx (&x, find_btr_reference, excludep);
+ return 0;
}
/* Return true if insn is an instruction that sets a target register.
If such a set is found and REGNO is nonzero, assign the register number
of the destination register to *REGNO. */
static int
-insn_sets_btr_p (const_rtx insn, int check_const, int *regno)
+insn_sets_btr_p (const rtx_insn *insn, int check_const, int *regno)
{
rtx set;
if (REG_P (dest)
&& TEST_HARD_REG_BIT (all_btrs, REGNO (dest)))
{
- gcc_assert (!btr_referenced_p (src, NULL));
+ gcc_assert (!find_btr_use (src));
if (!check_const || CONSTANT_P (src))
{
return 0;
}
-/* Find and return a use of a target register within an instruction INSN. */
-static rtx *
-find_btr_use (rtx insn)
-{
- return btr_referenced_p (insn, NULL) ? btr_reference_found : NULL;
-}
-
/* Find the group that the target register definition DEF belongs
to in the list starting with *ALL_BTR_DEF_GROUPS. If no such
group exists, create one. Add def to the group. */
block BB, instruction INSN, and insert it into ALL_BTR_DEFS. Return
the new definition. */
static btr_def
-add_btr_def (fibheap_t all_btr_defs, basic_block bb, int insn_luid, rtx insn,
+add_btr_def (btr_heap_t *all_btr_defs, basic_block bb, int insn_luid,
+ rtx_insn *insn,
unsigned int dest_reg, int other_btr_uses_before_def,
btr_def_group *all_btr_def_groups)
{
this_def->live_range = NULL;
find_btr_def_group (all_btr_def_groups, this_def);
- fibheap_insert (all_btr_defs, -this_def->cost, this_def);
+ all_btr_defs->insert (-this_def->cost, this_def);
if (dump_file)
fprintf (dump_file,
/* Create a new target register user structure, for a use in block BB,
instruction INSN. Return the new user. */
static btr_user
-new_btr_user (basic_block bb, int insn_luid, rtx insn)
+new_btr_user (basic_block bb, int insn_luid, rtx_insn *insn)
{
/* This instruction reads target registers. We need
to decide whether we can replace all target register
/* We want to ensure that USE is the only use of a target
register in INSN, so that we know that to rewrite INSN to use
a different target register, all we have to do is replace USE. */
- unambiguous_single_use = !btr_referenced_p (PATTERN (insn), usep);
+ unambiguous_single_use = !find_btr_use (PATTERN (insn), usep);
if (!unambiguous_single_use)
usep = NULL;
}
if (!REG_P (dest))
return;
regno = REGNO (dest);
- end_regno = END_HARD_REGNO (dest);
+ end_regno = END_REGNO (dest);
for (; regno < end_regno; regno++)
if (TEST_HARD_REG_BIT (all_btrs, regno))
{
note_other_use_this_block (regno, info->users_this_bb);
SET_HARD_REG_BIT (info->btrs_written_in_block, regno);
SET_HARD_REG_BIT (info->btrs_live_in_block, regno);
- sbitmap_difference (info->bb_gen, info->bb_gen,
+ bitmap_and_compl (info->bb_gen, info->bb_gen,
info->btr_defset[regno - first_btr]);
}
}
static void
-compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array,
+compute_defs_uses_and_gen (btr_heap_t *all_btr_defs, btr_def *def_array,
btr_user *use_array, sbitmap *btr_defset,
sbitmap *bb_gen, HARD_REG_SET *btrs_written)
{
btr_def_group all_btr_def_groups = NULL;
defs_uses_info info;
- sbitmap_vector_zero (bb_gen, last_basic_block);
- for (i = NUM_FIXED_BLOCKS; i < last_basic_block; i++)
+ bitmap_vector_clear (bb_gen, last_basic_block_for_fn (cfun));
+ for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
{
- basic_block bb = BASIC_BLOCK (i);
+ basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
int reg;
btr_def defs_this_bb = NULL;
- rtx insn;
- rtx last;
+ rtx_insn *insn;
+ rtx_insn *last;
int can_throw = 0;
info.users_this_bb = NULL;
def_array[insn_uid] = def;
SET_HARD_REG_BIT (info.btrs_written_in_block, regno);
SET_HARD_REG_BIT (info.btrs_live_in_block, regno);
- sbitmap_difference (bb_gen[i], bb_gen[i],
+ bitmap_and_compl (bb_gen[i], bb_gen[i],
btr_defset[regno - first_btr]);
- SET_BIT (bb_gen[i], insn_uid);
+ bitmap_set_bit (bb_gen[i], insn_uid);
def->next_this_bb = defs_this_bb;
defs_this_bb = def;
- SET_BIT (btr_defset[regno - first_btr], insn_uid);
+ bitmap_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. */
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);
+ bitmap_clear (info.bb_gen);
}
else
{
- if (btr_referenced_p (PATTERN (insn), NULL))
+ if (find_btr_use (PATTERN (insn)))
{
btr_user user = new_btr_user (bb, insn_luid, insn);
int reg;
for (reg = first_btr; reg <= last_btr; reg++)
if (TEST_HARD_REG_BIT (all_btrs, reg)
- && refers_to_regno_p (reg, reg + 1, user->insn,
- NULL))
+ && refers_to_regno_p (reg, user->insn))
{
note_other_use_this_block (reg,
info.users_this_bb);
/* Check for sibcall. */
if (GET_CODE (pat) == PARALLEL)
for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (pat, 0, i)) == RETURN)
+ if (ANY_RETURN_P (XVECEXP (pat, 0, i)))
{
COMPL_HARD_REG_SET (call_saved,
call_used_reg_set);
int regno;
for (regno = first_btr; regno <= last_btr; regno++)
- if (refers_to_regno_p (regno, regno+1, insn, NULL))
+ if (refers_to_regno_p (regno, insn))
SET_HARD_REG_BIT (btrs_live_at_end[i], regno);
}
if (dump_file)
- dump_btrs_live(i);
+ dump_btrs_live (i);
}
}
/* For each basic block, form the set BB_KILL - the set
of definitions that the block kills. */
- sbitmap_vector_zero (bb_kill, last_basic_block);
- for (i = NUM_FIXED_BLOCKS; i < last_basic_block; i++)
+ bitmap_vector_clear (bb_kill, last_basic_block_for_fn (cfun));
+ for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
{
for (regno = first_btr; regno <= last_btr; regno++)
if (TEST_HARD_REG_BIT (all_btrs, regno)
&& TEST_HARD_REG_BIT (btrs_written[i], regno))
- sbitmap_a_or_b (bb_kill[i], bb_kill[i],
+ bitmap_ior (bb_kill[i], bb_kill[i],
btr_defset[regno - first_btr]);
}
}
int changed;
sbitmap bb_in = sbitmap_alloc (max_uid);
- for (i = NUM_FIXED_BLOCKS; i < last_basic_block; i++)
- sbitmap_copy (bb_out[i], bb_gen[i]);
+ for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
+ bitmap_copy (bb_out[i], bb_gen[i]);
changed = 1;
while (changed)
{
changed = 0;
- for (i = NUM_FIXED_BLOCKS; i < last_basic_block; i++)
+ for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
{
- sbitmap_union_of_preds (bb_in, bb_out, i);
- changed |= sbitmap_union_of_diff_cg (bb_out[i], bb_gen[i],
+ bitmap_union_of_preds (bb_in, bb_out, BASIC_BLOCK_FOR_FN (cfun, i));
+ changed |= bitmap_ior_and_compl (bb_out[i], bb_gen[i],
bb_in, bb_kill[i]);
}
}
/* Link uses to the uses lists of all of their reaching defs.
Count up the number of reaching defs of each use. */
- for (i = NUM_FIXED_BLOCKS; i < last_basic_block; i++)
+ for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
{
- basic_block bb = BASIC_BLOCK (i);
- rtx insn;
- rtx last;
+ basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
+ rtx_insn *insn;
+ rtx_insn *last;
- sbitmap_union_of_preds (reaching_defs, bb_out, i);
+ bitmap_union_of_preds (reaching_defs, bb_out, BASIC_BLOCK_FOR_FN (cfun, i));
for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb));
insn != last;
insn = NEXT_INSN (insn))
{
/* Remove all reaching defs of regno except
for this one. */
- sbitmap_difference (reaching_defs, reaching_defs,
+ bitmap_and_compl (reaching_defs, reaching_defs,
btr_defset[def->btr - first_btr]);
- SET_BIT(reaching_defs, insn_uid);
+ bitmap_set_bit (reaching_defs, insn_uid);
}
if (user != NULL)
{
/* Find all the reaching defs for this use. */
- sbitmap reaching_defs_of_reg = sbitmap_alloc(max_uid);
+ sbitmap reaching_defs_of_reg = sbitmap_alloc (max_uid);
unsigned int uid = 0;
sbitmap_iterator sbi;
if (user->use)
- sbitmap_a_and_b (
+ bitmap_and (
reaching_defs_of_reg,
reaching_defs,
btr_defset[REGNO (user->use) - first_btr]);
{
int reg;
- sbitmap_zero (reaching_defs_of_reg);
+ bitmap_clear (reaching_defs_of_reg);
for (reg = first_btr; reg <= last_btr; reg++)
if (TEST_HARD_REG_BIT (all_btrs, reg)
- && refers_to_regno_p (reg, reg + 1, user->insn,
- NULL))
- sbitmap_a_or_b_and_c (reaching_defs_of_reg,
+ && refers_to_regno_p (reg, user->insn))
+ bitmap_or_and (reaching_defs_of_reg,
reaching_defs_of_reg,
reaching_defs,
btr_defset[reg - first_btr]);
}
- EXECUTE_IF_SET_IN_SBITMAP (reaching_defs_of_reg, 0, uid, sbi)
+ EXECUTE_IF_SET_IN_BITMAP (reaching_defs_of_reg, 0, uid, sbi)
{
btr_def def = def_array[uid];
for (regno = first_btr; regno <= last_btr; regno++)
if (TEST_HARD_REG_BIT (all_btrs, regno)
&& TEST_HARD_REG_BIT (call_used_reg_set, regno))
- sbitmap_difference (reaching_defs, reaching_defs,
+ bitmap_and_compl (reaching_defs, reaching_defs,
btr_defset[regno - first_btr]);
}
}
}
static void
-build_btr_def_use_webs (fibheap_t all_btr_defs)
+build_btr_def_use_webs (btr_heap_t *all_btr_defs)
{
const int max_uid = get_max_uid ();
btr_def *def_array = XCNEWVEC (btr_def, max_uid);
btr_user *use_array = XCNEWVEC (btr_user, max_uid);
sbitmap *btr_defset = sbitmap_vector_alloc (
(last_btr - first_btr) + 1, max_uid);
- sbitmap *bb_gen = sbitmap_vector_alloc (last_basic_block, max_uid);
- HARD_REG_SET *btrs_written = XCNEWVEC (HARD_REG_SET, last_basic_block);
+ sbitmap *bb_gen = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
+ max_uid);
+ HARD_REG_SET *btrs_written = XCNEWVEC (HARD_REG_SET,
+ last_basic_block_for_fn (cfun));
sbitmap *bb_kill;
sbitmap *bb_out;
- sbitmap_vector_zero (btr_defset, (last_btr - first_btr) + 1);
+ bitmap_vector_clear (btr_defset, (last_btr - first_btr) + 1);
compute_defs_uses_and_gen (all_btr_defs, def_array, use_array, btr_defset,
bb_gen, btrs_written);
- bb_kill = sbitmap_vector_alloc (last_basic_block, max_uid);
+ bb_kill = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), max_uid);
compute_kill (bb_kill, btr_defset, btrs_written);
free (btrs_written);
- bb_out = sbitmap_vector_alloc (last_basic_block, max_uid);
+ bb_out = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), max_uid);
compute_out (bb_out, bb_gen, bb_kill, max_uid);
sbitmap_vector_free (bb_gen);
static int
block_at_edge_of_live_range_p (int bb, btr_def def)
{
- if (def->other_btr_uses_before_def && BASIC_BLOCK (bb) == def->bb)
+ if (def->other_btr_uses_before_def
+ && BASIC_BLOCK_FOR_FN (cfun, bb) == def->bb)
return 1;
else if (def->other_btr_uses_after_use)
{
btr_user user;
for (user = def->uses; user != NULL; user = user->next)
- if (BASIC_BLOCK (bb) == user->bb)
+ if (BASIC_BLOCK_FOR_FN (cfun, bb) == user->bb)
return 1;
}
return 0;
{
basic_block *worklist, *tos;
- tos = worklist = XNEWVEC (basic_block, n_basic_blocks + 1);
+ tos = worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun) + 1);
if (dominated_by_p (CDI_DOMINATORS, new_bb, head_bb))
{
Replace all uses of the old target register definition by
uses of the new definition. Delete the old definition. */
basic_block b = new_def_bb;
- rtx insp = BB_HEAD (b);
- rtx old_insn = def->insn;
+ rtx_insn *insp = BB_HEAD (b);
+ rtx_insn *old_insn = def->insn;
rtx src;
rtx btr_rtx;
- rtx new_insn;
- enum machine_mode btr_mode;
+ rtx_insn *new_insn;
+ machine_mode btr_mode;
btr_user user;
rtx set;
/* We anticipate intra-block scheduling to be done. See if INSN could move
up within BB by N_INSNS. */
static int
-can_move_up (const_basic_block bb, const_rtx insn, int n_insns)
+can_move_up (const_basic_block bb, const rtx_insn *insn, int n_insns)
{
while (insn != BB_HEAD (bb) && n_insns > 0)
{
def_basic_block_freq = basic_block_freq (def->bb);
for (attempt = get_immediate_dominator (CDI_DOMINATORS, def->bb);
- !give_up && attempt && attempt != ENTRY_BLOCK_PTR && def->cost >= min_cost;
+ !give_up && attempt && attempt != ENTRY_BLOCK_PTR_FOR_FN (cfun)
+ && def->cost >= min_cost;
attempt = get_immediate_dominator (CDI_DOMINATORS, attempt))
{
/* Try to move the instruction that sets the target register into
if (btr != -1)
{
move_btr_def (attempt, btr, def, live_range, &btrs_live_in_range);
- bitmap_copy(live_range, def->live_range);
+ bitmap_copy (live_range, def->live_range);
btr_used_near_def = 0;
def_moved = 1;
def_basic_block_freq = basic_block_freq (def->bb);
static void
migrate_btr_defs (enum reg_class btr_class, int allow_callee_save)
{
- fibheap_t all_btr_defs = fibheap_new ();
+ btr_heap_t all_btr_defs (LONG_MIN);
int reg;
gcc_obstack_init (&migrate_btrl_obstack);
{
int i;
- for (i = NUM_FIXED_BLOCKS; i < last_basic_block; i++)
+ for (i = NUM_FIXED_BLOCKS; i < last_basic_block_for_fn (cfun); i++)
{
- basic_block bb = BASIC_BLOCK (i);
- fprintf(dump_file,
- "Basic block %d: count = " HOST_WIDEST_INT_PRINT_DEC
- " loop-depth = %d idom = %d\n",
- i, (HOST_WIDEST_INT) bb->count, bb->loop_depth,
- get_immediate_dominator (CDI_DOMINATORS, bb)->index);
+ basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
+ fprintf (dump_file,
+ "Basic block %d: count = %" PRId64
+ " loop-depth = %d idom = %d\n",
+ i, (int64_t) bb->count, bb_loop_depth (bb),
+ get_immediate_dominator (CDI_DOMINATORS, bb)->index);
}
}
first_btr = reg;
}
- btrs_live = XCNEWVEC (HARD_REG_SET, last_basic_block);
- btrs_live_at_end = XCNEWVEC (HARD_REG_SET, last_basic_block);
+ btrs_live = XCNEWVEC (HARD_REG_SET, last_basic_block_for_fn (cfun));
+ btrs_live_at_end = XCNEWVEC (HARD_REG_SET, last_basic_block_for_fn (cfun));
- build_btr_def_use_webs (all_btr_defs);
+ build_btr_def_use_webs (&all_btr_defs);
- while (!fibheap_empty (all_btr_defs))
+ while (!all_btr_defs.empty ())
{
- btr_def def = (btr_def) fibheap_extract_min (all_btr_defs);
- int min_cost = -fibheap_min_key (all_btr_defs);
+ int min_cost = -all_btr_defs.min_key ();
+ btr_def def = all_btr_defs.extract_min ();
if (migrate_btr_def (def, min_cost))
{
- fibheap_insert (all_btr_defs, -def->cost, (void *) def);
+ all_btr_defs.insert (-def->cost, def);
if (dump_file)
{
fprintf (dump_file,
free (btrs_live);
free (btrs_live_at_end);
obstack_free (&migrate_btrl_obstack, NULL);
- fibheap_delete (all_btr_defs);
}
static void
}
}
\f
-static bool
-gate_handle_branch_target_load_optimize1 (void)
+namespace {
+
+const pass_data pass_data_branch_target_load_optimize1 =
{
- return flag_branch_target_load_optimize;
-}
+ RTL_PASS, /* type */
+ "btl1", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+class pass_branch_target_load_optimize1 : public rtl_opt_pass
+{
+public:
+ pass_branch_target_load_optimize1 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_branch_target_load_optimize1, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *) { return flag_branch_target_load_optimize; }
+ virtual unsigned int execute (function *)
+ {
+ branch_target_load_optimize (epilogue_completed);
+ return 0;
+ }
+
+}; // class pass_branch_target_load_optimize1
-static unsigned int
-rest_of_handle_branch_target_load_optimize1 (void)
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_branch_target_load_optimize1 (gcc::context *ctxt)
{
- branch_target_load_optimize (epilogue_completed);
- return 0;
+ return new pass_branch_target_load_optimize1 (ctxt);
}
-struct rtl_opt_pass pass_branch_target_load_optimize1 =
+
+namespace {
+
+const pass_data pass_data_branch_target_load_optimize2 =
{
- {
- RTL_PASS,
- "btl1", /* name */
- gate_handle_branch_target_load_optimize1, /* gate */
- rest_of_handle_branch_target_load_optimize1, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_NONE, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_dump_func |
- TODO_verify_rtl_sharing |
- TODO_ggc_collect, /* todo_flags_finish */
- }
+ RTL_PASS, /* type */
+ "btl2", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
};
-static bool
-gate_handle_branch_target_load_optimize2 (void)
+class pass_branch_target_load_optimize2 : public rtl_opt_pass
{
- return (optimize > 0 && flag_branch_target_load_optimize2);
-}
+public:
+ pass_branch_target_load_optimize2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_branch_target_load_optimize2, ctxt)
+ {}
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+ {
+ return (optimize > 0 && flag_branch_target_load_optimize2);
+ }
-static unsigned int
-rest_of_handle_branch_target_load_optimize2 (void)
+ virtual unsigned int execute (function *);
+
+}; // class pass_branch_target_load_optimize2
+
+unsigned int
+pass_branch_target_load_optimize2::execute (function *)
{
static int warned = 0;
&& !warned)
{
warning (0, "branch target register load optimization is not intended "
- "to be run twice");
+ "to be run twice");
warned = 1;
}
return 0;
}
-struct rtl_opt_pass pass_branch_target_load_optimize2 =
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_branch_target_load_optimize2 (gcc::context *ctxt)
{
- {
- RTL_PASS,
- "btl2", /* name */
- gate_handle_branch_target_load_optimize2, /* gate */
- rest_of_handle_branch_target_load_optimize2, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_NONE, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_dump_func |
- TODO_ggc_collect, /* todo_flags_finish */
- }
-};
+ return new pass_branch_target_load_optimize2 (ctxt);
+}