#include "regs.h"
#include "hard-reg-set.h"
#include "flags.h"
+#include "except.h"
#include "df.h"
#include "cselib.h"
#include "dce.h"
#include "dbgcnt.h"
#include "tm_p.h"
-DEF_VEC_I(int);
-DEF_VEC_ALLOC_I(int,heap);
-
/* -------------------------------------------------------------------------
Core mark/delete routines
return false;
default:
- if (volatile_refs_p (body))
- return false;
-
- if (flag_non_call_exceptions && may_trap_p (body))
- return false;
-
- return true;
+ return !volatile_refs_p (body);
}
}
rtx body, x;
int i;
+ /* Don't delete jumps, notes and the like. */
+ if (!NONJUMP_INSN_P (insn))
+ return false;
+
+ /* Don't delete insns that can throw. */
+ if (!insn_nothrow_p (insn))
+ return false;
+
if (CALL_P (insn)
/* We cannot delete calls inside of the recursive dce because
this may cause basic blocks to be deleted and this messes up
&& !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
return find_call_stack_args (insn, false, fast, arg_stores);
- if (!NONJUMP_INSN_P (insn))
- return false;
-
body = PATTERN (insn);
switch (GET_CODE (body))
{
case USE:
+ case VAR_LOCATION:
return false;
case CLOBBER:
}
for (byte = off; byte < off + INTVAL (MEM_SIZE (mem)); byte++)
{
- gcc_assert (!bitmap_bit_p (sp_bytes, byte - min_sp_off));
- bitmap_set_bit (sp_bytes, byte - min_sp_off);
+ if (!bitmap_set_bit (sp_bytes, byte - min_sp_off))
+ gcc_unreachable ();
}
}
{
if (byte < min_sp_off
|| byte >= max_sp_off
- || !bitmap_bit_p (sp_bytes, byte - min_sp_off))
+ || !bitmap_clear_bit (sp_bytes, byte - min_sp_off))
break;
- bitmap_clear_bit (sp_bytes, byte - min_sp_off);
}
if (!deletable_insn_p (insn, fast, NULL))
rtx insn, next;
bool must_clean = false;
- FOR_EACH_BB (bb)
- FOR_BB_INSNS_SAFE (bb, insn, next)
+ FOR_EACH_BB_REVERSE (bb)
+ FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next)
if (INSN_P (insn))
{
/* Always delete no-op moves. */
else if (marked_insn_p (insn))
continue;
- /* Beware that reaching a dbg counter limit here can rarely
- result in miscompiled file. This occurs when a group of
- insns must be deleted together. Currently this only
- can happen on non-looping pure and constant calls
- on machines where ACCUMULATE_OUTGOING_ARGS is true. By
- using the dbg_cnt, it is possible to remove the call, but
- leave the argument pushes to the stack. */
+ /* Beware that reaching a dbg counter limit here can result
+ in miscompiled file. This occurs when a group of insns
+ must be deleted together, typically because the kept insn
+ depends on the output from the deleted insn. Deleting
+ this insns in reverse order (both at the bb level and
+ when looking at the blocks) minimizes this, but does not
+ eliminate it, since it is possible for the using insn to
+ be top of a block and the producer to be at the bottom of
+ the block. However, in most cases this will only result
+ in an uninitialized use of an insn that is dead anyway.
+
+ However, there is one rare case that will cause a
+ miscompile: deletion of non-looping pure and constant
+ calls on a machine where ACCUMULATE_OUTGOING_ARGS is true.
+ In this case it is possible to remove the call, but leave
+ the argument pushes to the stack. Because of the changes
+ to the stack pointer, this will almost always lead to a
+ miscompile. */
if (!dbg_cnt (dce))
continue;
FOR_ALL_BB (bb)
{
- for (use_rec = df_get_artificial_uses (bb->index);
+ for (use_rec = df_get_artificial_uses (bb->index);
*use_rec; use_rec++)
for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next)
if (! DF_REF_IS_ARTIFICIAL (defs->ref))
struct df_link *defs;
df_ref *use_rec;
+ if (DEBUG_INSN_P (insn))
+ return;
+
for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
{
df_ref use = *use_rec;
{
{
RTL_PASS,
- "dce", /* name */
- gate_ud_dce, /* gate */
- rest_of_handle_ud_dce, /* execute */
+ "ud dce", /* name */
+ gate_ud_dce, /* gate */
+ rest_of_handle_ud_dce, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
mark_insn (insn, true);
goto quickexit;
}
-
+
last = start + len;
while (start < last)
if (bitmap_bit_p (local_live, start++))
goto quickexit;
}
}
-
- quickexit:
-
+
+ quickexit:
+
/* No matter if the instruction is needed or not, we remove
any regno in the defs from the live set. */
df_byte_lr_simulate_defs (insn, local_live);
if (dump_file)
{
- fprintf (dump_file, "finished processing insn %d live out = ",
+ fprintf (dump_file, "finished processing insn %d live out = ",
INSN_UID (insn));
df_print_byte_regset (dump_file, local_live);
}
}
-
+
df_byte_lr_simulate_artificial_refs_at_top (bb, local_live);
block_changed = !bitmap_equal_p (local_live, DF_BYTE_LR_IN (bb));
needed = true;
break;
}
-
+
if (needed)
mark_insn (insn, true);
-
+
/* No matter if the instruction is needed or not, we remove
any regno in the defs from the live set. */
df_simulate_defs (insn, local_live);
if (marked_insn_p (insn))
df_simulate_uses (insn, local_live);
}
-
+
df_simulate_finalize_backwards (bb, local_live);
block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb));
}
if (byte_level)
- local_changed
+ local_changed
= byte_dce_process_block (bb, bitmap_bit_p (redo_out, index),
bb_has_eh_pred (bb) ? au_eh : au);
else
- local_changed
+ local_changed
= dce_process_block (bb, bitmap_bit_p (redo_out, index),
bb_has_eh_pred (bb) ? au_eh : au);
bitmap_set_bit (processed, index);
-
+
if (local_changed)
{
edge e;
bitmap_set_bit (redo_out, e->src->index);
}
}
-
+
if (global_changed)
{
/* Turn off the RUN_DCE flag to prevent recursive calls to
sbitmap_zero (marked);
bitmap_clear (processed);
bitmap_clear (redo_out);
-
+
/* We do not need to rescan any instructions. We only need
to redo the dataflow equations for the blocks that had a
change at the top of the block. Then we need to redo the
- iteration. */
+ iteration. */
if (byte_level)
df_analyze_problem (df_byte_lr, all_blocks, postorder, n_blocks);
else
/* If dce is able to delete something, it has to happen
immediately. Otherwise there will be problems handling the
eq_notes. */
- enum df_changeable_flags old_flags
- = df_clear_flags (DF_DEFER_INSN_RESCAN + DF_NO_INSN_RESCAN);
-
+ int old_flags =
+ df_clear_flags (DF_DEFER_INSN_RESCAN + DF_NO_INSN_RESCAN);
+
df_in_progress = true;
rest_of_handle_fast_dce ();
df_in_progress = false;
{
{
RTL_PASS,
- "dce", /* name */
+ "rtl dce", /* name */
gate_fast_dce, /* gate */
rest_of_handle_fast_dce, /* execute */
NULL, /* sub */