/* Common subexpression elimination for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
#include "toplev.h"
#include "output.h"
#include "ggc.h"
+#include "timevar.h"
/* The basic idea of common subexpression elimination is to go
through the code, keeping a record of expressions that would
/* Return an estimate of the cost of the registers used in an rtx.
This is mostly the number of different REG expressions in the rtx;
- however for some excecptions like fixed registers we use a cost of
+ however for some exceptions like fixed registers we use a cost of
0. If any other hard register reference occurs, return MAX_COST. */
static int
rtx x;
enum rtx_code outer_code ATTRIBUTE_UNUSED;
{
- register int i, j;
- register enum rtx_code code;
- register const char *fmt;
- register int total;
+ int i, j;
+ enum rtx_code code;
+ const char *fmt;
+ int total;
if (x == 0)
return 0;
}
\f
/* Return cost of address expression X.
- Expect that X is propertly formed address reference. */
+ Expect that X is properly formed address reference. */
int
address_cost (x, mode)
static void
new_basic_block ()
{
- register int i;
+ int i;
next_qty = max_reg;
unsigned int reg;
enum machine_mode mode;
{
- register int q;
- register struct qty_table_elem *ent;
- register struct reg_eqv_elem *eqv;
+ int q;
+ struct qty_table_elem *ent;
+ struct reg_eqv_elem *eqv;
if (next_qty >= max_qty)
abort ();
delete_reg_equiv (reg)
unsigned int reg;
{
- register struct qty_table_elem *ent;
- register int q = REG_QTY (reg);
- register int p, n;
+ struct qty_table_elem *ent;
+ int q = REG_QTY (reg);
+ int p, n;
/* If invalid, do nothing. */
if (q == (int) reg)
mention_regs (x)
rtx x;
{
- register enum rtx_code code;
- register int i, j;
- register const char *fmt;
- register int changed = 0;
+ enum rtx_code code;
+ int i, j;
+ const char *fmt;
+ int changed = 0;
if (x == 0)
return 0;
static void
remove_from_table (elt, hash)
- register struct table_elt *elt;
+ struct table_elt *elt;
unsigned hash;
{
if (elt == 0)
/* Remove the table element from its equivalence class. */
{
- register struct table_elt *prev = elt->prev_same_value;
- register struct table_elt *next = elt->next_same_value;
+ struct table_elt *prev = elt->prev_same_value;
+ struct table_elt *next = elt->next_same_value;
if (next)
next->prev_same_value = prev;
prev->next_same_value = next;
else
{
- register struct table_elt *newfirst = next;
+ struct table_elt *newfirst = next;
while (next)
{
next->first_same_value = newfirst;
/* Remove the table element from its hash bucket. */
{
- register struct table_elt *prev = elt->prev_same_hash;
- register struct table_elt *next = elt->next_same_hash;
+ struct table_elt *prev = elt->prev_same_hash;
+ struct table_elt *next = elt->next_same_hash;
if (next)
next->prev_same_hash = prev;
if (elt->related_value != 0 && elt->related_value != elt)
{
- register struct table_elt *p = elt->related_value;
+ struct table_elt *p = elt->related_value;
while (p->related_value != elt)
p = p->related_value;
unsigned hash;
enum machine_mode mode;
{
- register struct table_elt *p;
+ struct table_elt *p;
for (p = table[hash]; p; p = p->next_same_hash)
if (mode == p->mode && ((x == p->exp && GET_CODE (x) == REG)
unsigned hash;
enum machine_mode mode;
{
- register struct table_elt *p;
+ struct table_elt *p;
if (GET_CODE (x) == REG)
{
rtx x;
enum rtx_code code;
{
- register struct table_elt *p
+ struct table_elt *p
= lookup (x, safe_hash (x, VOIDmode) & HASH_MASK, GET_MODE (x));
/* If we are looking for a CONST_INT, the mode doesn't really matter, as
static struct table_elt *
insert (x, classp, hash, mode)
- register rtx x;
- register struct table_elt *classp;
+ rtx x;
+ struct table_elt *classp;
unsigned hash;
enum machine_mode mode;
{
- register struct table_elt *elt;
+ struct table_elt *elt;
/* If X is a register and we haven't made a quantity for it,
something is wrong. */
if (CHEAPER (elt, classp))
/* Insert at the head of the class */
{
- register struct table_elt *p;
+ struct table_elt *p;
elt->next_same_value = classp;
classp->prev_same_value = elt;
elt->first_same_value = elt;
{
/* Insert not at head of the class. */
/* Put it after the last element cheaper than X. */
- register struct table_elt *p, *next;
+ struct table_elt *p, *next;
for (p = classp; (next = p->next_same_value) && CHEAPER (next, elt);
p = next);
&& ! qty_table[REG_QTY (REGNO (x))].const_rtx
&& ! elt->is_const)
{
- register struct table_elt *p;
+ struct table_elt *p;
for (p = classp; p != 0; p = p->next_same_value)
{
rtx x;
enum machine_mode full_mode;
{
- register int i;
- register struct table_elt *p;
+ int i;
+ struct table_elt *p;
switch (GET_CODE (x))
{
unsigned int endregno
= regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
unsigned int tregno, tendregno, rn;
- register struct table_elt *p, *next;
+ struct table_elt *p, *next;
CLEAR_HARD_REG_BIT (hard_regs_in_table, regno);
for (i = 0; i < HASH_SIZE; i++)
{
- register struct table_elt *next;
+ struct table_elt *next;
for (p = table[i]; p; p = next)
{
{
next = p->next_same_hash;
if (GET_CODE (p->exp) != REG
- && refers_to_regno_p (regno, regno + 1, p->exp, (rtx*)0))
+ && refers_to_regno_p (regno, regno + 1, p->exp, (rtx*) 0))
remove_from_table (p, i);
}
}
|| (((SUBREG_BYTE (exp)
+ (GET_MODE_SIZE (GET_MODE (exp)) - 1)) >= offset)
&& SUBREG_BYTE (exp) <= end))
- && refers_to_regno_p (regno, regno + 1, p->exp, (rtx*)0))
+ && refers_to_regno_p (regno, regno + 1, p->exp, (rtx*) 0))
remove_from_table (p, i);
}
}
rtx x;
struct table_elt *elt;
{
- register struct table_elt *relt = 0;
- register struct table_elt *p, *q;
+ struct table_elt *relt = 0;
+ struct table_elt *p, *q;
HOST_WIDE_INT offset;
/* First, is there anything related known?
rtx x;
enum machine_mode mode;
{
- register int i, j;
- register unsigned hash = 0;
- register enum rtx_code code;
- register const char *fmt;
+ int i, j;
+ unsigned hash = 0;
+ enum rtx_code code;
+ const char *fmt;
/* repeat is used to turn tail-recursion into iteration. */
repeat:
|| CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (regno))
|| (SMALL_REGISTER_CLASSES
&& ! fixed_regs[regno]
- && regno != FRAME_POINTER_REGNUM
- && regno != HARD_FRAME_POINTER_REGNUM
- && regno != ARG_POINTER_REGNUM
- && regno != STACK_POINTER_REGNUM
+ && x != frame_pointer_rtx
+ && x != hard_frame_pointer_rtx
+ && x != arg_pointer_rtx
+ && x != stack_pointer_rtx
&& GET_MODE_CLASS (GET_MODE (x)) != MODE_CC)))
{
do_not_record = 1;
+ (unsigned) CONST_DOUBLE_HIGH (x));
return hash;
+ case CONST_VECTOR:
+ {
+ int units;
+ rtx elt;
+
+ units = CONST_VECTOR_NUNITS (x);
+
+ for (i = 0; i < units; ++i)
+ {
+ elt = CONST_VECTOR_ELT (x, i);
+ hash += canon_hash (elt, GET_MODE (elt));
+ }
+
+ return hash;
+ }
+
/* Assume there is only one rtx object for any given label. */
case LABEL_REF:
hash += ((unsigned) LABEL_REF << 7) + (unsigned long) XEXP (x, 0);
hash += canon_hash_string (XSTR (x, i));
else if (fmt[i] == 'i')
{
- register unsigned tem = XINT (x, i);
+ unsigned tem = XINT (x, i);
hash += tem;
}
else if (fmt[i] == '0' || fmt[i] == 't')
int validate;
int equal_values;
{
- register int i, j;
- register enum rtx_code code;
- register const char *fmt;
+ int i, j;
+ enum rtx_code code;
+ const char *fmt;
/* Note: it is incorrect to assume an expression is equivalent to itself
if VALIDATE is nonzero. */
static int
cse_rtx_varies_p (x, from_alias)
- register rtx x;
+ rtx x;
int from_alias;
{
/* We need not check for X and the equivalence class being of the same
rtx x;
rtx insn;
{
- register int i;
- register enum rtx_code code;
- register const char *fmt;
+ int i;
+ enum rtx_code code;
+ const char *fmt;
if (x == 0)
return x;
case CONST:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_VECTOR:
case SYMBOL_REF:
case LABEL_REF:
case ADDR_VEC:
case REG:
{
- register int first;
- register int q;
- register struct qty_table_elem *ent;
+ int first;
+ int q;
+ struct qty_table_elem *ent;
/* Never replace a hard reg, because hard regs can appear
in more than one machine mode, and we must preserve the mode
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
- register int j;
+ int j;
if (fmt[i] == 'e')
{
rtx x;
rtx insn;
{
- register enum rtx_code code;
- register enum machine_mode mode;
- register const char *fmt;
- register int i;
+ enum rtx_code code;
+ enum machine_mode mode;
+ const char *fmt;
+ int i;
rtx new = 0;
int copied = 0;
int must_swap = 0;
case CONST:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_VECTOR:
case SYMBOL_REF:
case LABEL_REF:
case REG:
case SYMBOL_REF:
case LABEL_REF:
case CONST_DOUBLE:
+ case CONST_VECTOR:
const_arg = arg;
break;
|| (GET_CODE (const_arg0) == CONST_INT
&& GET_CODE (const_arg1) != CONST_INT))))
{
- register rtx tem = XEXP (x, 0);
+ rtx tem = XEXP (x, 0);
if (insn == 0 && ! copied)
{
& HASH_MASK), mode_arg0))
&& p0->first_same_value == p1->first_same_value))
{
- /* Sadly two equal NaNs are not equivalent. */
- if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || ! FLOAT_MODE_P (mode_arg0)
- || flag_unsafe_math_optimizations)
- return ((code == EQ || code == LE || code == GE
- || code == LEU || code == GEU || code == UNEQ
- || code == UNLE || code == UNGE || code == ORDERED)
- ? true_rtx : false_rtx);
- /* Take care for the FP compares we can resolve. */
- if (code == UNEQ || code == UNLE || code == UNGE)
- return true_rtx;
- if (code == LTGT || code == LT || code == GT)
- return false_rtx;
+ /* Sadly two equal NaNs are not equivalent. */
+ if (!HONOR_NANS (mode_arg0))
+ return ((code == EQ || code == LE || code == GE
+ || code == LEU || code == GEU || code == UNEQ
+ || code == UNLE || code == UNGE
+ || code == ORDERED)
+ ? true_rtx : false_rtx);
+ /* Take care for the FP compares we can resolve. */
+ if (code == UNEQ || code == UNLE || code == UNGE)
+ return true_rtx;
+ if (code == LTGT || code == LT || code == GT)
+ return false_rtx;
}
/* If FOLDED_ARG0 is a register, see if the comparison we are
CONST_INT, see if we can find a register equivalent to the
positive constant. Make a MINUS if so. Don't do this for
a non-negative constant since we might then alternate between
- chosing positive and negative constants. Having the positive
+ choosing positive and negative constants. Having the positive
constant previously-used is the more common case. Be sure
the resulting constant is non-negative; if const_arg1 were
the smallest negative number this would overflow: depending
rtx
gen_lowpart_if_possible (mode, x)
enum machine_mode mode;
- register rtx x;
+ rtx x;
{
rtx result = gen_lowpart_common (mode, x);
else if (GET_CODE (x) == MEM)
{
/* This is the only other case we handle. */
- register int offset = 0;
+ int offset = 0;
rtx new;
if (WORDS_BIG_ENDIAN)
rtx insn;
rtx libcall_insn;
{
- register rtx x = PATTERN (insn);
- register int i;
+ rtx x = PATTERN (insn);
+ int i;
rtx tem;
- register int n_sets = 0;
+ int n_sets = 0;
#ifdef HAVE_cc0
/* Records what this insn does to set CC0. */
}
else if (GET_CODE (x) == PARALLEL)
{
- register int lim = XVECLEN (x, 0);
+ int lim = XVECLEN (x, 0);
sets = (struct set *) alloca (lim * sizeof (struct set));
anything in that case. */
for (i = 0; i < lim; i++)
{
- register rtx y = XVECEXP (x, 0, i);
+ rtx y = XVECEXP (x, 0, i);
if (GET_CODE (y) == CLOBBER)
{
rtx clobbered = XEXP (y, 0);
for (i = 0; i < lim; i++)
{
- register rtx y = XVECEXP (x, 0, i);
+ rtx y = XVECEXP (x, 0, i);
if (GET_CODE (y) == SET)
{
/* As above, we ignore unconditional jumps and call-insns and
for (i = 0; i < n_sets; i++)
{
- register rtx src, dest;
- register rtx src_folded;
- register struct table_elt *elt = 0, *p;
+ rtx src, dest;
+ rtx src_folded;
+ struct table_elt *elt = 0, *p;
enum machine_mode mode;
rtx src_eqv_here;
rtx src_const = 0;
&& GET_CODE (XEXP (XEXP (src_const, 0), 0)) == LABEL_REF
&& GET_CODE (XEXP (XEXP (src_const, 0), 1)) == LABEL_REF))
{
- tem = find_reg_note (insn, REG_EQUAL, NULL_RTX);
-
/* Make sure that the rtx is not shared with any other insn. */
src_const = copy_rtx (src_const);
/* Record the actual constant value in a REG_EQUAL note, making
a new one if one does not already exist. */
- if (tem)
- XEXP (tem, 0) = src_const;
- else
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL,
- src_const, REG_NOTES (insn));
+ set_unique_reg_note (insn, REG_EQUAL, src_const);
/* If storing a constant value in a register that
previously held the constant value 0,
be a conditional or computed branch. */
else if (dest == pc_rtx && GET_CODE (src) == LABEL_REF)
{
+ /* Now emit a BARRIER after the unconditional jump. */
+ if (NEXT_INSN (insn) == 0
+ || GET_CODE (NEXT_INSN (insn)) != BARRIER)
+ emit_barrier_after (insn);
+
/* We reemit the jump in as many cases as possible just in
case the form of an unconditional jump is significantly
different than a computed jump or conditional jump.
and hope for the best. */
if (n_sets == 1)
{
- rtx new = emit_jump_insn_before (gen_jump (XEXP (src, 0)), insn);
+ rtx new = emit_jump_insn_after (gen_jump (XEXP (src, 0)), insn);
+
JUMP_LABEL (new) = XEXP (src, 0);
LABEL_NUSES (XEXP (src, 0))++;
+ delete_insn (insn);
insn = new;
+
+ /* Now emit a BARRIER after the unconditional jump. */
+ if (NEXT_INSN (insn) == 0
+ || GET_CODE (NEXT_INSN (insn)) != BARRIER)
+ emit_barrier_after (insn);
}
else
INSN_CODE (insn) = -1;
- never_reached_warning (insn);
+ never_reached_warning (insn, NULL);
- /* Now emit a BARRIER after the unconditional jump. Do not bother
- deleting any unreachable code, let jump/flow do that. */
- if (NEXT_INSN (insn) != 0
- && GET_CODE (NEXT_INSN (insn)) != BARRIER)
- emit_barrier_after (insn);
+ /* Do not bother deleting any unreachable code,
+ let jump/flow do that. */
cse_jumps_altered = 1;
sets[i].rtl = 0;
if (src_eqv && src_eqv_elt == 0 && sets[0].rtl != 0 && ! src_eqv_volatile
&& ! rtx_equal_p (src_eqv, SET_DEST (sets[0].rtl)))
{
- register struct table_elt *elt;
- register struct table_elt *classp = sets[0].src_elt;
+ struct table_elt *elt;
+ struct table_elt *classp = sets[0].src_elt;
rtx dest = SET_DEST (sets[0].rtl);
enum machine_mode eqvmode = GET_MODE (dest);
{
/* Insert source and constant equivalent into hash table, if not
already present. */
- register struct table_elt *classp = src_eqv_elt;
- register rtx src = sets[i].src;
- register rtx dest = SET_DEST (sets[i].rtl);
+ struct table_elt *classp = src_eqv_elt;
+ rtx src = sets[i].src;
+ rtx dest = SET_DEST (sets[i].rtl);
enum machine_mode mode
= GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src);
/* Don't put a hard register source into the table if this is
the last insn of a libcall. In this case, we only need
to put src_eqv_elt in src_elt. */
- if (GET_CODE (src) != REG
- || REGNO (src) >= FIRST_PSEUDO_REGISTER
- || ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
+ if (! find_reg_note (insn, REG_RETVAL, NULL_RTX))
{
- register struct table_elt *elt;
+ struct table_elt *elt;
/* Note that these insert_regs calls cannot remove
any of the src_elt's, because they would have failed to
{
/* We can't use the inner dest, because the mode associated with
a ZERO_EXTRACT is significant. */
- register rtx dest = SET_DEST (sets[i].rtl);
+ rtx dest = SET_DEST (sets[i].rtl);
/* Needed for registers to remove the register from its
previous quantity's chain.
/* If elt was removed, find current head of same class,
or 0 if nothing remains of that class. */
{
- register struct table_elt *elt = sets[i].src_elt;
+ struct table_elt *elt = sets[i].src_elt;
while (elt && elt->prev_same_value)
elt = elt->prev_same_value;
for (i = 0; i < n_sets; i++)
if (sets[i].rtl)
{
- register rtx dest = SET_DEST (sets[i].rtl);
+ rtx dest = SET_DEST (sets[i].rtl);
rtx inner_dest = sets[i].inner_dest;
- register struct table_elt *elt;
+ struct table_elt *elt;
/* Don't record value if we are not supposed to risk allocating
floating-point values in registers that might be wider than
static void
invalidate_memory ()
{
- register int i;
- register struct table_elt *p, *next;
+ int i;
+ struct table_elt *p, *next;
for (i = 0; i < HASH_SIZE; i++)
for (p = table[i]; p; p = next)
static int
addr_affects_sp_p (addr)
- register rtx addr;
+ rtx addr;
{
if (GET_RTX_CLASS (GET_CODE (addr)) == 'a'
&& GET_CODE (XEXP (addr, 0)) == REG
}
else if (GET_CODE (x) == PARALLEL)
{
- register int i;
+ int i;
for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
{
- register rtx y = XVECEXP (x, 0, i);
+ rtx y = XVECEXP (x, 0, i);
if (GET_CODE (y) == CLOBBER)
{
rtx ref = XEXP (y, 0);
case SYMBOL_REF:
case LABEL_REF:
case CONST_DOUBLE:
+ case CONST_VECTOR:
case PC:
case CC0:
case LO_SUM:
/* Detect a branch around a block of code. */
else if (skip_blocks && q != 0 && GET_CODE (q) != CODE_LABEL)
{
- register rtx tmp;
+ rtx tmp;
if (next_real_insn (q) == next)
{
FILE *file;
{
struct cse_basic_block_data val;
- register rtx insn = f;
- register int i;
+ rtx insn = f;
+ int i;
cse_jumps_altered = 0;
recorded_label_ref = 0;
static rtx
cse_basic_block (from, to, next_branch, around_loop)
- register rtx from, to;
+ rtx from, to;
struct branch_path *next_branch;
int around_loop;
{
- register rtx insn;
+ rtx insn;
int to_usage = 0;
rtx libcall_insn = NULL_RTX;
int num_insns = 0;
for (insn = from; insn != to; insn = NEXT_INSN (insn))
{
- register enum rtx_code code = GET_CODE (insn);
+ enum rtx_code code = GET_CODE (insn);
/* If we have processed 1,000 insns, flush the hash table to
avoid extreme quadratic behavior. We must not include NOTEs
}
\f
/* Called via for_each_rtx to see if an insn is using a LABEL_REF for which
- there isn't a REG_DEAD note. Return one if so. DATA is the insn. */
+ there isn't a REG_LABEL note. Return one if so. DATA is the insn. */
static int
check_for_label_ref (rtl, data)
LABEL_REF for a CODE_LABEL that isn't in the insn chain, don't do this
since no REG_LABEL will be added. */
return (GET_CODE (*rtl) == LABEL_REF
+ && ! LABEL_REF_NONLOCAL_P (*rtl)
+ && LABEL_P (XEXP (*rtl, 0))
&& INSN_UID (XEXP (*rtl, 0)) != 0
&& ! find_reg_note (insn, REG_LABEL, XEXP (*rtl, 0)));
}
case CONST:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_VECTOR:
case SYMBOL_REF:
case LABEL_REF:
return;
move dead invariants out of loops or make givs for dead quantities. The
remaining passes of the compilation are also sped up. */
-void
-delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks)
+int
+delete_trivially_dead_insns (insns, nreg)
rtx insns;
int nreg;
- int preserve_basic_blocks;
{
int *counts;
rtx insn, prev;
- int i;
int in_libcall = 0, dead_libcall = 0;
- basic_block bb;
+ int ndead = 0, nlastdead, niterations = 0;
+ timevar_push (TV_DELETE_TRIVIALLY_DEAD);
/* First count the number of times each register is used. */
counts = (int *) xcalloc (nreg, sizeof (int));
for (insn = next_real_insn (insns); insn; insn = next_real_insn (insn))
count_reg_usage (insn, counts, NULL_RTX, 1);
- /* Go from the last insn to the first and delete insns that only set unused
- registers or copy a register to itself. As we delete an insn, remove
- usage counts for registers it uses.
-
- The first jump optimization pass may leave a real insn as the last
- insn in the function. We must not skip that insn or we may end
- up deleting code that is not really dead. */
- insn = get_last_insn ();
- if (! INSN_P (insn))
- insn = prev_real_insn (insn);
-
- if (!preserve_basic_blocks)
- for (; insn; insn = prev)
- {
- int live_insn = 0;
-
- prev = prev_real_insn (insn);
-
- /* Don't delete any insns that are part of a libcall block unless
- we can delete the whole libcall block.
-
- Flow or loop might get confused if we did that. Remember
- that we are scanning backwards. */
- if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
- {
- in_libcall = 1;
- live_insn = 1;
- dead_libcall = dead_libcall_p (insn);
- }
- else if (in_libcall)
- live_insn = ! dead_libcall;
- else
- live_insn = insn_live_p (insn, counts);
-
- /* If this is a dead insn, delete it and show registers in it aren't
- being used. */
-
- if (! live_insn)
- {
- count_reg_usage (insn, counts, NULL_RTX, -1);
- delete_related_insns (insn);
- }
+ do
+ {
+ nlastdead = ndead;
+ niterations++;
+ /* Go from the last insn to the first and delete insns that only set unused
+ registers or copy a register to itself. As we delete an insn, remove
+ usage counts for registers it uses.
+
+ The first jump optimization pass may leave a real insn as the last
+ insn in the function. We must not skip that insn or we may end
+ up deleting code that is not really dead. */
+ insn = get_last_insn ();
+ if (! INSN_P (insn))
+ insn = prev_real_insn (insn);
- if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
- {
- in_libcall = 0;
- dead_libcall = 0;
- }
- }
- else
- for (i = 0; i < n_basic_blocks; i++)
- for (bb = BASIC_BLOCK (i), insn = bb->end; insn != bb->head; insn = prev)
+ for (; insn; insn = prev)
{
int live_insn = 0;
- prev = PREV_INSN (insn);
- if (!INSN_P (insn))
- continue;
+ prev = prev_real_insn (insn);
/* Don't delete any insns that are part of a libcall block unless
we can delete the whole libcall block.
if (! live_insn)
{
count_reg_usage (insn, counts, NULL_RTX, -1);
- delete_insn (insn);
+ delete_insn_and_edges (insn);
+ ndead++;
}
if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
dead_libcall = 0;
}
}
+ } while (ndead != nlastdead);
+ if (rtl_dump_file && ndead)
+ fprintf (rtl_dump_file, "Deleted %i trivially dead insns; %i iterations\n",
+ ndead, niterations);
/* Clean up. */
free (counts);
+ timevar_pop (TV_DELETE_TRIVIALLY_DEAD);
+ return ndead;
}