/* If-conversion support.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010,
- 2011
- Free Software Foundation, Inc.
+ Copyright (C) 2000-2014 Free Software Foundation, Inc.
This file is part of GCC.
#include "df.h"
#include "vec.h"
#include "pointer-set.h"
-#include "vecprim.h"
#include "dbgcnt.h"
#ifndef HAVE_conditional_move
#define NULL_BLOCK ((basic_block) NULL)
+/* True if after combine pass. */
+static bool ifcvt_after_combine;
+
/* # of IF-THEN or IF-THEN-ELSE blocks we looked at */
static int num_possible_if_blocks;
static rtx find_active_insn_before (basic_block, rtx);
static rtx find_active_insn_after (basic_block, rtx);
static basic_block block_fallthru (basic_block);
-static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int);
+static int cond_exec_process_insns (ce_if_block *, rtx, rtx, rtx, int, int);
static rtx cond_exec_get_condition (rtx);
static rtx noce_get_condition (rtx, rtx *, bool);
static int noce_operand_ok (const_rtx);
-static void merge_if_block (ce_if_block_t *);
+static void merge_if_block (ce_if_block *);
static int find_cond_trap (basic_block, edge, edge);
static basic_block find_if_header (basic_block, int);
static int block_jumps_and_fallthru_p (basic_block, basic_block);
static int noce_find_if_block (basic_block, edge, edge, int);
-static int cond_exec_find_if_block (ce_if_block_t *);
+static int cond_exec_find_if_block (ce_if_block *);
static int find_if_case_1 (basic_block, edge, edge);
static int find_if_case_2 (basic_block, edge, edge);
static int dead_or_predicable (basic_block, basic_block, basic_block,
while (1)
{
- if (CALL_P (insn) || NONJUMP_INSN_P (insn))
+ if (active_insn_p (insn) && !JUMP_P (insn))
count++;
if (insn == BB_END (bb))
rtx insn = BB_HEAD (bb);
bool speed = optimize_bb_for_speed_p (bb);
+ /* Set scale to REG_BR_PROB_BASE to void the identical scaling
+ applied to insn_rtx_cost when optimizing for size. Only do
+ this after combine because if-conversion might interfere with
+ passes before combine.
+
+ Use optimize_function_for_speed_p instead of the pre-defined
+ variable speed to make sure it is set to same value for all
+ basic blocks in one if-conversion transformation. */
+ if (!optimize_function_for_speed_p (cfun) && ifcvt_after_combine)
+ scale = REG_BR_PROB_BASE;
/* Our branch probability/scaling factors are just estimates and don't
account for cases where we can get speculation for free and other
secondary benefits. So we fudge the scale factor to make speculating
- appear a little more profitable. */
- scale += REG_BR_PROB_BASE / 8;
+ appear a little more profitable when optimizing for performance. */
+ else
+ scale += REG_BR_PROB_BASE / 8;
+
+
max_cost *= scale;
while (1)
insns were processed. */
static int
-cond_exec_process_insns (ce_if_block_t *ce_info ATTRIBUTE_UNUSED,
+cond_exec_process_insns (ce_if_block *ce_info ATTRIBUTE_UNUSED,
/* if block information */rtx start,
/* first insn to look at */rtx end,
/* last insn to look at */rtx test,
- /* conditional execution test */rtx prob_val,
+ /* conditional execution test */int prob_val,
/* probability of branch taken. */int mod_ok)
{
int must_be_last = FALSE;
if (NOTE_P (insn) || DEBUG_INSN_P (insn))
goto insn_done;
- gcc_assert(NONJUMP_INSN_P (insn) || CALL_P (insn));
+ gcc_assert (NONJUMP_INSN_P (insn) || CALL_P (insn));
+
+ /* dwarf2out can't cope with conditional unwind info. */
+ if (RTX_FRAME_RELATED_P (insn))
+ return FALSE;
/* Remove USE insns that get in the way. */
if (reload_completed && GET_CODE (PATTERN (insn)) == USE)
validate_change (insn, &PATTERN (insn), pattern, 1);
- if (CALL_P (insn) && prob_val)
+ if (CALL_P (insn) && prob_val >= 0)
validate_change (insn, ®_NOTES (insn),
- alloc_EXPR_LIST (REG_BR_PROB, prob_val,
- REG_NOTES (insn)), 1);
+ gen_rtx_INT_LIST ((enum machine_mode) REG_BR_PROB,
+ prob_val, REG_NOTES (insn)), 1);
insn_done:
if (insn == end)
converting the block. */
static int
-cond_exec_process_if_block (ce_if_block_t * ce_info,
+cond_exec_process_if_block (ce_if_block * ce_info,
/* if block information */int do_multiple_p)
{
basic_block test_bb = ce_info->test_bb; /* last test block */
int then_mod_ok; /* whether conditional mods are ok in THEN */
rtx true_expr; /* test for else block insns */
rtx false_expr; /* test for then block insns */
- rtx true_prob_val; /* probability of else block */
- rtx false_prob_val; /* probability of then block */
+ int true_prob_val; /* probability of else block */
+ int false_prob_val; /* probability of then block */
rtx then_last_head = NULL_RTX; /* Last match at the head of THEN */
rtx else_last_head = NULL_RTX; /* Last match at the head of ELSE */
rtx then_first_tail = NULL_RTX; /* First match at the tail of THEN */
rtx else_first_tail = NULL_RTX; /* First match at the tail of ELSE */
int then_n_insns, else_n_insns, n_insns;
enum rtx_code false_code;
+ rtx note;
/* If test is comprised of && or || elements, and we've failed at handling
all of them together, just use the last test if it is the special case of
n_insns -= 2 * n_matching;
}
- if (then_start && else_start)
+ if (then_start
+ && else_start
+ && then_n_insns > n_matching
+ && else_n_insns > n_matching)
{
int longest_match = MIN (then_n_insns - n_matching,
else_n_insns - n_matching);
goto fail;
#endif
- true_prob_val = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
- if (true_prob_val)
+ note = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
+ if (note)
{
- true_prob_val = XEXP (true_prob_val, 0);
- false_prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (true_prob_val));
+ true_prob_val = XINT (note, 0);
+ false_prob_val = REG_BR_PROB_BASE - true_prob_val;
}
else
- false_prob_val = NULL_RTX;
+ {
+ true_prob_val = -1;
+ false_prob_val = -1;
+ }
/* If we have && or || tests, do them here. These tests are in the adjacent
blocks after the first block containing the test. */
set_used_flags (if_info->x);
set_used_flags (if_info->cond);
+ set_used_flags (if_info->a);
+ set_used_flags (if_info->b);
unshare_all_rtl_in_chain (seq);
end_sequence ();
ifalse = INTVAL (if_info->a);
itrue = INTVAL (if_info->b);
+ diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
/* Make sure we can represent the difference between the two values. */
- if ((itrue - ifalse > 0)
+ if ((diff > 0)
!= ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
return FALSE;
- diff = trunc_int_for_mode (itrue - ifalse, mode);
+ diff = trunc_int_for_mode (diff, mode);
can_reverse = (reversed_comparison_code (if_info->cond, if_info->jump)
!= UNKNOWN);
if (reversep)
{
tmp = itrue; itrue = ifalse; ifalse = tmp;
- diff = trunc_int_for_mode (-diff, mode);
+ diff = trunc_int_for_mode (-(unsigned HOST_WIDE_INT) diff, mode);
}
start_sequence ();
target = expand_simple_binop (mode,
(diff == STORE_FLAG_VALUE
? PLUS : MINUS),
- GEN_INT (ifalse), target, if_info->x, 0,
- OPTAB_WIDEN);
+ gen_int_mode (ifalse, mode), target,
+ if_info->x, 0, OPTAB_WIDEN);
}
/* if (test) x = 8; else x = 0;
else if (itrue == -1)
{
target = expand_simple_binop (mode, IOR,
- target, GEN_INT (ifalse), if_info->x, 0,
- OPTAB_WIDEN);
+ target, gen_int_mode (ifalse, mode),
+ if_info->x, 0, OPTAB_WIDEN);
}
/* if (test) x = a; else x = b;
else
{
target = expand_simple_binop (mode, AND,
- target, GEN_INT (diff), if_info->x, 0,
- OPTAB_WIDEN);
+ target, gen_int_mode (diff, mode),
+ if_info->x, 0, OPTAB_WIDEN);
if (target)
target = expand_simple_binop (mode, PLUS,
- target, GEN_INT (ifalse),
+ target, gen_int_mode (ifalse, mode),
if_info->x, 0, OPTAB_WIDEN);
}
|| ! noce_operand_ok (SET_SRC (set_b))
|| reg_overlap_mentioned_p (x, SET_SRC (set_b))
|| modified_between_p (SET_SRC (set_b), insn_b, jump)
+ /* Avoid extending the lifetime of hard registers on small
+ register class machines. */
+ || (REG_P (SET_SRC (set_b))
+ && HARD_REGISTER_P (SET_SRC (set_b))
+ && targetm.small_register_classes_for_mode_p
+ (GET_MODE (SET_SRC (set_b))))
/* Likewise with X. In particular this can happen when
noce_get_condition looks farther back in the instruction
stream than one might expect. */
static int
check_cond_move_block (basic_block bb,
struct pointer_map_t *vals,
- VEC (rtx, heap) **regs,
+ vec<rtx> *regs,
rtx cond)
{
rtx insn;
slot = pointer_map_insert (vals, (void *) dest);
*slot = (void *) src;
- VEC_safe_push (rtx, heap, *regs, dest);
+ regs->safe_push (dest);
}
return TRUE;
int c;
struct pointer_map_t *then_vals;
struct pointer_map_t *else_vals;
- VEC (rtx, heap) *then_regs = NULL;
- VEC (rtx, heap) *else_regs = NULL;
+ vec<rtx> then_regs = vNULL;
+ vec<rtx> else_regs = vNULL;
unsigned int i;
int success_p = FALSE;
source register does not change after the assignment. Also count
the number of registers set in only one of the blocks. */
c = 0;
- FOR_EACH_VEC_ELT (rtx, then_regs, i, reg)
+ FOR_EACH_VEC_ELT (then_regs, i, reg)
{
void **then_slot = pointer_map_contains (then_vals, reg);
void **else_slot = pointer_map_contains (else_vals, reg);
}
/* Finish off c for MAX_CONDITIONAL_EXECUTE. */
- FOR_EACH_VEC_ELT (rtx, else_regs, i, reg)
+ FOR_EACH_VEC_ELT (else_regs, i, reg)
{
gcc_checking_assert (pointer_map_contains (else_vals, reg));
if (!pointer_map_contains (then_vals, reg))
done:
pointer_map_destroy (then_vals);
pointer_map_destroy (else_vals);
- VEC_free (rtx, heap, then_regs);
- VEC_free (rtx, heap, else_regs);
+ then_regs.release ();
+ else_regs.release ();
return success_p;
}
if (then_bb)
{
+ /* If THEN_BB has no successors, then there's a BARRIER after it.
+ If COMBO_BB has more than one successor (THEN_BB), then that BARRIER
+ is no longer needed, and in fact it is incorrect to leave it in
+ the insn stream. */
+ if (EDGE_COUNT (then_bb->succs) == 0
+ && EDGE_COUNT (combo_bb->succs) > 1)
+ {
+ rtx end = NEXT_INSN (BB_END (then_bb));
+ while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end))
+ end = NEXT_INSN (end);
+
+ if (end && BARRIER_P (end))
+ delete_insn (end);
+ }
merge_blocks (combo_bb, then_bb);
num_true_changes++;
}
get their addresses taken. */
if (else_bb)
{
+ /* If ELSE_BB has no successors, then there's a BARRIER after it.
+ If COMBO_BB has more than one successor (ELSE_BB), then that BARRIER
+ is no longer needed, and in fact it is incorrect to leave it in
+ the insn stream. */
+ if (EDGE_COUNT (else_bb->succs) == 0
+ && EDGE_COUNT (combo_bb->succs) > 1)
+ {
+ rtx end = NEXT_INSN (BB_END (else_bb));
+ while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end))
+ end = NEXT_INSN (end);
+
+ if (end && BARRIER_P (end))
+ delete_insn (end);
+ }
merge_blocks (combo_bb, else_bb);
num_true_changes++;
}
/* There should still be something at the end of the THEN or ELSE
blocks taking us to our final destination. */
gcc_assert (JUMP_P (last)
- || (EDGE_SUCC (combo_bb, 0)->dest == EXIT_BLOCK_PTR
+ || (EDGE_SUCC (combo_bb, 0)->dest
+ == EXIT_BLOCK_PTR_FOR_FN (cfun)
&& CALL_P (last)
&& SIBLING_CALL_P (last))
|| ((EDGE_SUCC (combo_bb, 0)->flags & EDGE_EH)
may be zero incoming edges if the THEN block didn't actually join
back up (as with a call to a non-return function). */
else if (EDGE_COUNT (join_bb->preds) < 2
- && join_bb != EXIT_BLOCK_PTR)
+ && join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
{
/* We can merge the JOIN cleanly and update the dataflow try
again on this pass.*/
&& single_succ (combo_bb) == join_bb);
/* Remove the jump and cruft from the end of the COMBO block. */
- if (join_bb != EXIT_BLOCK_PTR)
+ if (join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
tidy_fallthru_edge (single_succ_edge (combo_bb));
}
static basic_block
find_if_header (basic_block test_bb, int pass)
{
- ce_if_block_t ce_info;
+ ce_if_block ce_info;
edge then_edge;
edge else_edge;
code processing. ??? we should fix this in the future. */
if (EDGE_COUNT (then_bb->succs) == 0)
{
- if (single_pred_p (else_bb))
+ if (single_pred_p (else_bb) && else_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
{
rtx last_insn = BB_END (then_bb);
next = then_bb;
if (else_bb && (next = next->next_bb) != else_bb)
return FALSE;
- if ((next = next->next_bb) != join_bb && join_bb != EXIT_BLOCK_PTR)
+ if ((next = next->next_bb) != join_bb
+ && join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
{
if (else_bb)
join_bb = NULL;
/* Wire together the blocks again. */
if (current_ir_type () == IR_RTL_CFGLAYOUT)
single_succ_edge (test_bb)->flags |= EDGE_FALLTHRU;
- else
+ else if (trap_bb == then_bb)
{
rtx lab, newjump;
rtx trap;
/* We're not the exit block. */
- if (bb == EXIT_BLOCK_PTR)
+ if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
return NULL_RTX;
/* The block must have no successors. */
predictable_edge_p (then_edge)))))
return FALSE;
- if (else_bb == EXIT_BLOCK_PTR)
+ if (else_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
{
rtx jump = BB_END (else_edge->src);
gcc_assert (JUMP_P (jump));
if (then_bb->next_bb == else_bb
&& then_bb->prev_bb == test_bb
- && else_bb != EXIT_BLOCK_PTR)
+ && else_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
{
redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb);
new_bb = 0;
}
- else if (else_bb == EXIT_BLOCK_PTR)
+ else if (else_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
new_bb = force_nonfallthru_and_redirect (FALLTHRU_EDGE (test_bb),
else_bb, else_target);
else
if (new_bb)
{
df_bb_replace (then_bb_index, new_bb);
- /* Since the fallthru edge was redirected from test_bb to new_bb,
- we need to ensure that new_bb is in the same partition as
- test bb (you can not fall through across section boundaries). */
- BB_COPY_PARTITION (new_bb, test_bb);
+ /* This should have been done above via force_nonfallthru_and_redirect
+ (possibly called from redirect_edge_and_branch_force). */
+ gcc_checking_assert (BB_PARTITION (new_bb) == BB_PARTITION (test_bb));
}
num_true_changes++;
end = PREV_INSN (end);
}
+ /* Don't move frame-related insn across the conditional branch. This
+ can lead to one of the paths of the branch having wrong unwind info. */
+ if (epilogue_completed)
+ {
+ rtx insn = head;
+ while (1)
+ {
+ if (INSN_P (insn) && RTX_FRAME_RELATED_P (insn))
+ return FALSE;
+ if (insn == end)
+ break;
+ insn = NEXT_INSN (insn);
+ }
+ }
+
/* Disable handling dead code by conditional execution if the machine needs
to do anything funny with the tests, etc. */
#ifndef IFCVT_MODIFY_TESTS
All that's left is making sure the insns involved can actually
be predicated. */
- rtx cond, prob_val;
+ rtx cond;
cond = cond_exec_get_condition (jump);
if (! cond)
return FALSE;
- prob_val = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
- if (prob_val)
- prob_val = XEXP (prob_val, 0);
+ rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
+ int prob_val = (note ? XINT (note, 0) : -1);
if (reversep)
{
return FALSE;
cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
XEXP (cond, 1));
- if (prob_val)
- prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (prob_val));
+ if (prob_val >= 0)
+ prob_val = REG_BR_PROB_BASE - prob_val;
}
if (cond_exec_process_insns (NULL, head, end, cond, prob_val, 0)
saved in caller-saved regs. A caller-saved reg requires the
prologue, killing a shrink-wrap opportunity. */
if ((flag_shrink_wrap && HAVE_simple_return && !epilogue_completed)
- && ENTRY_BLOCK_PTR->next_bb == test_bb
+ && ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb == test_bb
&& single_succ_p (new_dest)
- && single_succ (new_dest) == EXIT_BLOCK_PTR
+ && single_succ (new_dest) == EXIT_BLOCK_PTR_FOR_FN (cfun)
&& bitmap_intersect_p (df_get_live_in (new_dest), merge_set))
{
regset return_regs;
&& targetm.calls.function_value_regno_p (i))
bitmap_set_bit (return_regs, INCOMING_REGNO (i));
- bitmap_and_into (return_regs, df_get_live_out (ENTRY_BLOCK_PTR));
- bitmap_and_into (return_regs, df_get_live_in (EXIT_BLOCK_PTR));
+ bitmap_and_into (return_regs,
+ df_get_live_out (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
+ bitmap_and_into (return_regs,
+ df_get_live_in (EXIT_BLOCK_PTR_FOR_FN (cfun)));
if (!bitmap_empty_p (return_regs))
{
FOR_BB_INSNS_REVERSE (new_dest, insn)
{
if (JUMP_P (BB_END (dest_edge->src)))
new_dest_label = JUMP_LABEL (BB_END (dest_edge->src));
- else if (new_dest == EXIT_BLOCK_PTR)
+ else if (new_dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
new_dest_label = ret_rtx;
else
new_dest_label = block_label (new_dest);
return FALSE;
}
\f
-/* Main entry point for all if-conversion. */
+/* Main entry point for all if-conversion. AFTER_COMBINE is true if
+ we are after combine pass. */
static void
-if_convert (void)
+if_convert (bool after_combine)
{
basic_block bb;
int pass;
df_live_set_all_dirty ();
}
+ /* Record whether we are after combine pass. */
+ ifcvt_after_combine = after_combine;
num_possible_if_blocks = 0;
num_updated_if_blocks = 0;
num_true_changes = 0;
fprintf (dump_file, "\n\n========== Pass %d ==========\n", pass);
#endif
- FOR_EACH_BB (bb)
+ FOR_EACH_BB_FN (bb, cfun)
{
basic_block new_bb;
while (!df_get_bb_dirty (bb)
dump_flow_info (dump_file, dump_flags);
}
cleanup_cfg (CLEANUP_EXPENSIVE);
- if_convert ();
+ if_convert (false);
}
cleanup_cfg (0);
return 0;
}
-struct rtl_opt_pass pass_rtl_ifcvt =
+namespace {
+
+const pass_data pass_data_rtl_ifcvt =
{
- {
- RTL_PASS,
- "ce1", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- gate_handle_if_conversion, /* gate */
- rest_of_handle_if_conversion, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_IFCVT, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_df_finish | TODO_verify_rtl_sharing |
- 0 /* todo_flags_finish */
- }
+ RTL_PASS, /* type */
+ "ce1", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_IFCVT, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ ( TODO_df_finish | TODO_verify_rtl_sharing | 0 ), /* todo_flags_finish */
};
+class pass_rtl_ifcvt : public rtl_opt_pass
+{
+public:
+ pass_rtl_ifcvt (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_ifcvt, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_handle_if_conversion (); }
+ unsigned int execute () { return rest_of_handle_if_conversion (); }
+
+}; // class pass_rtl_ifcvt
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_rtl_ifcvt (gcc::context *ctxt)
+{
+ return new pass_rtl_ifcvt (ctxt);
+}
+
static bool
gate_handle_if_after_combine (void)
{
static unsigned int
rest_of_handle_if_after_combine (void)
{
- if_convert ();
+ if_convert (true);
return 0;
}
-struct rtl_opt_pass pass_if_after_combine =
+namespace {
+
+const pass_data pass_data_if_after_combine =
{
- {
- RTL_PASS,
- "ce2", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- gate_handle_if_after_combine, /* gate */
- rest_of_handle_if_after_combine, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_IFCVT, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_df_finish | TODO_verify_rtl_sharing |
- TODO_ggc_collect /* todo_flags_finish */
- }
+ RTL_PASS, /* type */
+ "ce2", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_IFCVT, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ ( TODO_df_finish | TODO_verify_rtl_sharing ), /* todo_flags_finish */
};
+class pass_if_after_combine : public rtl_opt_pass
+{
+public:
+ pass_if_after_combine (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_if_after_combine, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_handle_if_after_combine (); }
+ unsigned int execute () { return rest_of_handle_if_after_combine (); }
+
+}; // class pass_if_after_combine
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_if_after_combine (gcc::context *ctxt)
+{
+ return new pass_if_after_combine (ctxt);
+}
+
static bool
gate_handle_if_after_reload (void)
static unsigned int
rest_of_handle_if_after_reload (void)
{
- if_convert ();
+ if_convert (true);
return 0;
}
-struct rtl_opt_pass pass_if_after_reload =
+namespace {
+
+const pass_data pass_data_if_after_reload =
{
- {
- RTL_PASS,
- "ce3", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- gate_handle_if_after_reload, /* gate */
- rest_of_handle_if_after_reload, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_IFCVT2, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_df_finish | TODO_verify_rtl_sharing |
- TODO_ggc_collect /* todo_flags_finish */
- }
+ RTL_PASS, /* type */
+ "ce3", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_IFCVT2, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ ( TODO_df_finish | TODO_verify_rtl_sharing ), /* todo_flags_finish */
};
+
+class pass_if_after_reload : public rtl_opt_pass
+{
+public:
+ pass_if_after_reload (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_if_after_reload, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_handle_if_after_reload (); }
+ unsigned int execute () { return rest_of_handle_if_after_reload (); }
+
+}; // class pass_if_after_reload
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_if_after_reload (gcc::context *ctxt)
+{
+ return new pass_if_after_reload (ctxt);
+}