/* If-conversion support.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010,
- 2011
- Free Software Foundation, Inc.
+ Copyright (C) 2000-2013 Free Software Foundation, Inc.
This file is part of GCC.
#include "tm_p.h"
#include "cfgloop.h"
#include "target.h"
-#include "timevar.h"
#include "tree-pass.h"
#include "df.h"
#include "vec.h"
#include "pointer-set.h"
-#include "vecprim.h"
#include "dbgcnt.h"
#ifndef HAVE_conditional_move
switch (GET_RTX_CLASS (GET_CODE (y)))
{
case RTX_UNARY:
- ot = code_to_optab[GET_CODE (y)];
+ ot = code_to_optab (GET_CODE (y));
if (ot)
{
start_sequence ();
case RTX_BIN_ARITH:
case RTX_COMM_ARITH:
- ot = code_to_optab[GET_CODE (y)];
+ ot = code_to_optab (GET_CODE (y));
if (ot)
{
start_sequence ();
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 ();
return FALSE;
emit_insn_before_setloc (seq, if_info->jump,
- INSN_LOCATOR (if_info->insn_a));
+ INSN_LOCATION (if_info->insn_a));
}
return TRUE;
}
return FALSE;
emit_insn_before_setloc (seq, if_info->jump,
- INSN_LOCATOR (if_info->insn_a));
+ INSN_LOCATION (if_info->insn_a));
return TRUE;
}
else
return FALSE;
emit_insn_before_setloc (seq, if_info->jump,
- INSN_LOCATOR (if_info->insn_a));
+ INSN_LOCATION (if_info->insn_a));
return TRUE;
}
return FALSE;
emit_insn_before_setloc (seq, if_info->jump,
- INSN_LOCATOR (if_info->insn_a));
+ INSN_LOCATION (if_info->insn_a));
return TRUE;
}
end_sequence ();
return FALSE;
emit_insn_before_setloc (seq, if_info->jump,
- INSN_LOCATOR (if_info->insn_a));
+ INSN_LOCATION (if_info->insn_a));
return TRUE;
}
end_sequence ();
return FALSE;
emit_insn_before_setloc (seq, if_info->jump,
- INSN_LOCATOR (if_info->insn_a));
+ INSN_LOCATION (if_info->insn_a));
return TRUE;
}
return FALSE;
emit_insn_before_setloc (seq, if_info->jump,
- INSN_LOCATOR (if_info->insn_a));
+ INSN_LOCATION (if_info->insn_a));
return TRUE;
}
else
&& MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b)
&& if_info->branch_cost >= 5)
{
- enum machine_mode address_mode
- = targetm.addr_space.address_mode (MEM_ADDR_SPACE (a));
+ enum machine_mode address_mode = get_address_mode (a);
a = XEXP (a, 0);
b = XEXP (b, 0);
if (!tmp)
return FALSE;
- emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR (if_info->insn_a));
+ emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATION (if_info->insn_a));
return TRUE;
end_seq_and_fail:
if (!seq)
return FALSE;
- emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
+ emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
if_info->cond = cond;
if_info->cond_earliest = earliest;
if (!seq)
return FALSE;
- emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
+ emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
if_info->cond = cond;
if_info->cond_earliest = earliest;
if (!seq)
return FALSE;
- emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
+ emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
return TRUE;
}
return FALSE;
emit_insn_before_setloc (seq, if_info->jump,
- INSN_LOCATOR (if_info->insn_a));
+ INSN_LOCATION (if_info->insn_a));
}
return TRUE;
}
|| (CALL_P (insn) && (!RTL_CONST_CALL_P (insn)))))
return false;
- if (memory_modified_in_insn_p (mem, insn))
+ if (memory_must_be_modified_in_insn_p (mem, insn))
return true;
if (modified_in_p (XEXP (mem, 0), insn))
return false;
|| ! 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. */
unshare_all_rtl_in_chain (seq);
end_sequence ();
- emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATOR (insn_a));
+ emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATION (insn_a));
}
/* The original THEN and ELSE blocks may now be removed. The test block
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))
loc_insn = first_active_insn (else_bb);
gcc_assert (loc_insn);
}
- emit_insn_before_setloc (seq, jump, INSN_LOCATOR (loc_insn));
+ emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));
if (else_bb)
{
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;
}
ce_info.else_bb = else_edge->dest;
ce_info.pass = pass;
-#ifdef IFCVT_INIT_EXTRA_FIELDS
- IFCVT_INIT_EXTRA_FIELDS (&ce_info);
+#ifdef IFCVT_MACHDEP_INIT
+ IFCVT_MACHDEP_INIT (&ce_info);
#endif
if (!reload_completed
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)
{
rtx last_insn = BB_END (then_bb);
return FALSE;
/* Emit the new insns before cond_earliest. */
- emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap));
+ emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATION (trap));
/* Delete the trap block if possible. */
remove_edge (trap_bb == then_bb ? then_edge : else_edge);
/* We can avoid creating a new basic block if then_bb is immediately
followed by else_bb, i.e. deleting then_bb allows test_bb to fall
- thru to else_bb. */
+ through to else_bb. */
if (then_bb->next_bb == else_bb
&& then_bb->prev_bb == test_bb
edge else_succ;
int then_prob, else_prob;
+ /* We do not want to speculate (empty) loop latches. */
+ if (current_loops
+ && else_bb->loop_father->latch == else_bb)
+ return FALSE;
+
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
and cold sections.
#ifdef IFCVT_MULTIPLE_DUMPS
if (dump_file && cond_exec_changed_p)
- {
- if (dump_flags & TDF_SLIM)
- print_rtl_slim_with_bb (dump_file, get_insns (), dump_flags);
- else
- print_rtl_with_bb (dump_file, get_insns ());
- }
+ print_rtl_with_bb (dump_file, get_insns (), dump_flags);
#endif
}
while (cond_exec_changed_p);
if (flag_if_conversion)
{
if (dump_file)
- dump_flow_info (dump_file, dump_flags);
+ {
+ dump_reg_info (dump_file);
+ dump_flow_info (dump_file, dump_flags);
+ }
cleanup_cfg (CLEANUP_EXPENSIVE);
if_convert ();
}
{
RTL_PASS,
"ce1", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
gate_handle_if_conversion, /* gate */
rest_of_handle_if_conversion, /* execute */
NULL, /* sub */
{
RTL_PASS,
"ce2", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
gate_handle_if_after_combine, /* gate */
rest_of_handle_if_after_combine, /* execute */
NULL, /* sub */
{
RTL_PASS,
"ce3", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
gate_handle_if_after_reload, /* gate */
rest_of_handle_if_after_reload, /* execute */
NULL, /* sub */