GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
static sbitmap marked = NULL;
-/* Return true if INSN a normal instruction that can be deleted by the
- DCE pass. */
+/* A subroutine for which BODY is part of the instruction being tested;
+ either the top-level pattern, or an element of a PARALLEL. The
+ instruction is known not to be a bare USE or CLOBBER. */
static bool
-deletable_insn_p (rtx insn, bool fast)
+deletable_insn_p_1 (rtx body)
{
- rtx x;
-
- switch (GET_CODE (PATTERN (insn)))
+ switch (GET_CODE (body))
{
- case USE:
case PREFETCH:
case TRAP_IF:
/* The UNSPEC case was added here because the ia-64 claims that
case UNSPEC:
return false;
+ default:
+ if (volatile_insn_p (body))
+ return false;
+
+ if (flag_non_call_exceptions && may_trap_p (body))
+ return false;
+
+ return true;
+ }
+}
+
+/* Return true if INSN is a normal instruction that can be deleted by
+ the DCE pass. */
+
+static bool
+deletable_insn_p (rtx insn, bool fast)
+{
+ rtx body, x;
+ int i;
+
+ if (!NONJUMP_INSN_P (insn))
+ return false;
+
+ body = PATTERN (insn);
+ switch (GET_CODE (body))
+ {
+ case USE:
+ return false;
+
case CLOBBER:
if (fast)
{
/* A CLOBBER of a dead pseudo register serves no purpose.
That is not necessarily true for hard registers until
after reload. */
- x = XEXP (PATTERN (insn), 0);
+ x = XEXP (body, 0);
return REG_P (x) && (!HARD_REGISTER_P (x) || reload_completed);
}
- else
+ else
/* Because of the way that use-def chains are built, it is not
possible to tell if the clobber is dead because it can
never be the target of a use-def chain. */
return false;
- default:
- if (!NONJUMP_INSN_P (insn))
- return false;
-
- if (volatile_insn_p (PATTERN (insn)))
- return false;
-
- if (flag_non_call_exceptions && may_trap_p (PATTERN (insn)))
- return false;
-
+ case PARALLEL:
+ for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
+ if (!deletable_insn_p_1 (XVECEXP (body, 0, i)))
+ return false;
return true;
+
+ default:
+ return deletable_insn_p_1 (body);
}
}
instruction containing DEST. */
static void
-mark_nonreg_stores_1 (rtx dest, rtx pattern, void *data)
+mark_nonreg_stores_1 (rtx dest, const_rtx pattern, void *data)
{
if (GET_CODE (pattern) != CLOBBER && !REG_P (dest))
mark_insn ((rtx) data, true);
instruction containing DEST. */
static void
-mark_nonreg_stores_2 (rtx dest, rtx pattern, void *data)
+mark_nonreg_stores_2 (rtx dest, const_rtx pattern, void *data)
{
if (GET_CODE (pattern) != CLOBBER && !REG_P (dest))
mark_insn ((rtx) data, false);
/* UD-based DSE routines. */
-/* Mark instructions that define artifically-used registers, such as
+/* Mark instructions that define artificially-used registers, such as
the frame pointer and the stack pointer. */
static void
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func |
- TODO_df_finish |
+ TODO_df_finish | TODO_verify_rtl_sharing |
TODO_ggc_collect, /* todo_flags_finish */
'w' /* letter */
};
dce_process_block (basic_block bb, bool redo_out)
{
bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
+ bitmap au;
rtx insn;
bool block_changed;
struct df_ref **def_rec, **use_rec;
bitmap_set_bit (local_live, DF_REF_REGNO (use));
}
+ /* These regs are considered always live so if they end up dying
+ because of some def, we need to bring the back again.
+ Calling df_simulate_fixup_sets has the disadvantage of calling
+ df_has_eh_preds once per insn, so we cache the information here. */
+ if (df_has_eh_preds (bb))
+ au = df->eh_block_artificial_uses;
+ else
+ au = df->regular_block_artificial_uses;
+
FOR_BB_INSNS_REVERSE (bb, insn)
if (INSN_P (insn))
{
/* The insn is needed if there is someone who uses the output. */
for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
- if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec)))
+ if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec))
+ || bitmap_bit_p (au, DF_REF_REGNO (*def_rec)))
{
needed = true;
break;
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func |
- TODO_df_finish |
+ TODO_df_finish | TODO_verify_rtl_sharing |
TODO_ggc_collect, /* todo_flags_finish */
'w' /* letter */
};