/* Dataflow support routines.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz,
mhayes@redhat.com)
the reg-def lists contain all the refs that define a given register
while the insn-use lists contain all the refs used by an insn.
-Note that the reg-def and reg-use chains are generally short (except for the
-hard registers) and thus it is much faster to search these chains
+Note that the reg-def and reg-use chains are generally short (except for
+the hard registers) and thus it is much faster to search these chains
rather than searching the def or use bitmaps.
If the insns are in SSA form then the reg-def and use-def lists
even though reg 41 is decremented before it is used for the memory
address in this second example.
-A set to a REG inside a ZERO_EXTRACT, SIGN_EXTRACT, or SUBREG invokes
-a read-modify write operation. We generate both a use and a def
-and again mark them read/write.
-*/
+A set to a REG inside a ZERO_EXTRACT, or a set to a non-paradoxical SUBREG
+for which the number of word_mode units covered by the outer mode is
+smaller than that covered by the inner mode, invokes a read-modify-write.
+operation. We generate both a use and a def and again mark them
+read/write.
+Paradoxical subreg writes don't leave a trace of the old content, so they
+are write-only operations. */
#include "config.h"
#include "system.h"
do \
{ \
unsigned int node_; \
- EXECUTE_IF_SET_IN_BITMAP (BITMAP, MIN, node_, \
- {(BB) = BASIC_BLOCK (node_); CODE;}); \
+ bitmap_iterator bi; \
+ EXECUTE_IF_SET_IN_BITMAP (BITMAP, MIN, node_, bi) \
+ { \
+ (BB) = BASIC_BLOCK (node_); \
+ CODE; \
+ } \
} \
while (0)
if (! df->insns_modified)
{
- df->insns_modified = BITMAP_XMALLOC ();
+ df->insns_modified = BITMAP_ALLOC (NULL);
bitmap_zero (df->insns_modified);
}
}
if (!bb_info->rd_in)
{
/* Allocate bitmaps for reaching definitions. */
- bb_info->rd_kill = BITMAP_XMALLOC ();
- bb_info->rd_gen = BITMAP_XMALLOC ();
- bb_info->rd_in = BITMAP_XMALLOC ();
- bb_info->rd_out = BITMAP_XMALLOC ();
+ bb_info->rd_kill = BITMAP_ALLOC (NULL);
+ bb_info->rd_gen = BITMAP_ALLOC (NULL);
+ bb_info->rd_in = BITMAP_ALLOC (NULL);
+ bb_info->rd_out = BITMAP_ALLOC (NULL);
}
else
{
if (!bb_info->ru_in)
{
/* Allocate bitmaps for upward exposed uses. */
- bb_info->ru_kill = BITMAP_XMALLOC ();
- bb_info->ru_gen = BITMAP_XMALLOC ();
- bb_info->ru_in = BITMAP_XMALLOC ();
- bb_info->ru_out = BITMAP_XMALLOC ();
+ bb_info->ru_kill = BITMAP_ALLOC (NULL);
+ bb_info->ru_gen = BITMAP_ALLOC (NULL);
+ bb_info->ru_in = BITMAP_ALLOC (NULL);
+ bb_info->ru_out = BITMAP_ALLOC (NULL);
}
else
{
if (!bb_info->lr_in)
{
/* Allocate bitmaps for live variables. */
- bb_info->lr_def = BITMAP_XMALLOC ();
- bb_info->lr_use = BITMAP_XMALLOC ();
- bb_info->lr_in = BITMAP_XMALLOC ();
- bb_info->lr_out = BITMAP_XMALLOC ();
+ bb_info->lr_def = BITMAP_ALLOC (NULL);
+ bb_info->lr_use = BITMAP_ALLOC (NULL);
+ bb_info->lr_in = BITMAP_ALLOC (NULL);
+ bb_info->lr_out = BITMAP_ALLOC (NULL);
}
else
{
if ((flags & DF_RD) && bb_info->rd_in)
{
/* Free bitmaps for reaching definitions. */
- BITMAP_XFREE (bb_info->rd_kill);
+ BITMAP_FREE (bb_info->rd_kill);
bb_info->rd_kill = NULL;
- BITMAP_XFREE (bb_info->rd_gen);
+ BITMAP_FREE (bb_info->rd_gen);
bb_info->rd_gen = NULL;
- BITMAP_XFREE (bb_info->rd_in);
+ BITMAP_FREE (bb_info->rd_in);
bb_info->rd_in = NULL;
- BITMAP_XFREE (bb_info->rd_out);
+ BITMAP_FREE (bb_info->rd_out);
bb_info->rd_out = NULL;
}
if ((flags & DF_RU) && bb_info->ru_in)
{
/* Free bitmaps for upward exposed uses. */
- BITMAP_XFREE (bb_info->ru_kill);
+ BITMAP_FREE (bb_info->ru_kill);
bb_info->ru_kill = NULL;
- BITMAP_XFREE (bb_info->ru_gen);
+ BITMAP_FREE (bb_info->ru_gen);
bb_info->ru_gen = NULL;
- BITMAP_XFREE (bb_info->ru_in);
+ BITMAP_FREE (bb_info->ru_in);
bb_info->ru_in = NULL;
- BITMAP_XFREE (bb_info->ru_out);
+ BITMAP_FREE (bb_info->ru_out);
bb_info->ru_out = NULL;
}
if ((flags & DF_LR) && bb_info->lr_in)
{
/* Free bitmaps for live variables. */
- BITMAP_XFREE (bb_info->lr_def);
+ BITMAP_FREE (bb_info->lr_def);
bb_info->lr_def = NULL;
- BITMAP_XFREE (bb_info->lr_use);
+ BITMAP_FREE (bb_info->lr_use);
bb_info->lr_use = NULL;
- BITMAP_XFREE (bb_info->lr_in);
+ BITMAP_FREE (bb_info->lr_in);
bb_info->lr_in = NULL;
- BITMAP_XFREE (bb_info->lr_out);
+ BITMAP_FREE (bb_info->lr_out);
bb_info->lr_out = NULL;
}
}
df_reg_table_realloc (df, df->n_regs);
- df->bbs_modified = BITMAP_XMALLOC ();
+ df->bbs_modified = BITMAP_ALLOC (NULL);
bitmap_zero (df->bbs_modified);
df->flags = 0;
df->bbs = xcalloc (last_basic_block, sizeof (struct bb_info));
- df->all_blocks = BITMAP_XMALLOC ();
+ df->all_blocks = BITMAP_ALLOC (NULL);
FOR_EACH_BB (bb)
bitmap_set_bit (df->all_blocks, bb->index);
}
df->regs = 0;
df->reg_size = 0;
- if (df->bbs_modified)
- BITMAP_XFREE (df->bbs_modified);
+ BITMAP_FREE (df->bbs_modified);
df->bbs_modified = 0;
- if (df->insns_modified)
- BITMAP_XFREE (df->insns_modified);
+ BITMAP_FREE (df->insns_modified);
df->insns_modified = 0;
- BITMAP_XFREE (df->all_blocks);
+ BITMAP_FREE (df->all_blocks);
df->all_blocks = 0;
free_alloc_pool (df_ref_pool);
/* Only a single ref. It must be the one we want.
If not, the def-use and use-def chains are likely to
be inconsistent. */
- if (link->ref != ref)
- abort ();
+ gcc_assert (link->ref == ref);
+
/* Now have an empty chain. */
*phead = NULL;
}
{
unsigned int regno;
- if (!REG_P (reg) && GET_CODE (reg) != SUBREG)
- abort ();
+ gcc_assert (REG_P (reg) || GET_CODE (reg) == SUBREG);
/* For the reg allocator we are interested in some SUBREG rtx's, but not
all. Notably only those representing a word extraction from a multi-word
}
-/* Return nonzero if writes to paradoxical SUBREGs, or SUBREGs which
- are too narrow, are read-modify-write. */
+/* A set to a non-paradoxical SUBREG for which the number of word_mode units
+ covered by the outer mode is smaller than that covered by the inner mode,
+ is a read-modify-write operation.
+ This function returns true iff the SUBREG X is such a SUBREG. */
bool
read_modify_subreg_p (rtx x)
{
return false;
isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
osize = GET_MODE_SIZE (GET_MODE (x));
- /* Paradoxical subreg writes don't leave a trace of the old content. */
return (isize > osize && isize > UNITS_PER_WORD);
}
be handy for the reg allocator. */
while (GET_CODE (dst) == STRICT_LOW_PART
|| GET_CODE (dst) == ZERO_EXTRACT
- || GET_CODE (dst) == SIGN_EXTRACT
- || ((df->flags & DF_FOR_REGALLOC) == 0
- && read_modify_subreg_p (dst)))
+ || read_modify_subreg_p (dst))
{
/* Strict low part always contains SUBREG, but we do not want to make
it appear outside, as whole register is always considered. */
case CLOBBER:
/* If we are clobbering a MEM, mark any registers inside the address
as being used. */
- if (GET_CODE (XEXP (x, 0)) == MEM)
+ if (MEM_P (XEXP (x, 0)))
df_uses_record (df, &XEXP (XEXP (x, 0), 0),
DF_REF_REG_MEM_STORE, bb, insn, flags);
switch (GET_CODE (dst))
{
case SUBREG:
- if ((df->flags & DF_FOR_REGALLOC) == 0
- && read_modify_subreg_p (dst))
+ if (read_modify_subreg_p (dst))
{
df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
insn, DF_REF_READ_WRITE);
bb, insn, 0);
break;
case STRICT_LOW_PART:
- /* A strict_low_part uses the whole REG and not just the SUBREG. */
+ /* A strict_low_part uses the whole REG and not just the
+ SUBREG. */
dst = XEXP (dst, 0);
- if (GET_CODE (dst) != SUBREG)
- abort ();
+ gcc_assert (GET_CODE (dst) == SUBREG);
df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
insn, DF_REF_READ_WRITE);
break;
dst = XEXP (dst, 0);
break;
default:
- abort ();
+ gcc_unreachable ();
}
return;
}
}
}
- if (GET_CODE (insn) == CALL_INSN)
+ if (CALL_P (insn))
{
rtx note;
rtx x;
if (global_regs[i])
{
x = df_reg_use_gen (i);
- df_uses_record (df, &SET_DEST (x),
+ df_uses_record (df, &XEXP (x, 0),
DF_REF_REG_USE, bb, insn, 0);
}
}
df_uses_record (df, &PATTERN (insn),
DF_REF_REG_USE, bb, insn, 0);
- if (GET_CODE (insn) == CALL_INSN)
+ if (CALL_P (insn))
{
rtx note;
{
#ifdef ENABLE_CHECKING
for (regno = 0; regno < df->n_regs; regno++)
- if (df->regs[regno].defs)
- abort ();
+ gcc_assert (!df->regs[regno].defs);
#endif
/* Pretend that all defs are new. */
{
#ifdef ENABLE_CHECKING
for (regno = 0; regno < df->n_regs; regno++)
- if (df->regs[regno].uses)
- abort ();
+ gcc_assert (!df->regs[regno].uses);
#endif
/* Pretend that all uses are new. */
bitmap ru;
basic_block bb;
- ru = BITMAP_XMALLOC ();
+ ru = BITMAP_ALLOC (NULL);
FOR_EACH_BB_IN_BITMAP (blocks, 0, bb,
{
df_bb_du_chain_create (df, bb, ru);
});
- BITMAP_XFREE (ru);
+ BITMAP_FREE (ru);
}
void *out, void *gen, void *kill,
void *data ATTRIBUTE_UNUSED)
{
- *changed = bitmap_union_of_diff (out, gen, in, kill);
+ *changed = bitmap_ior_and_compl (out, gen, in, kill);
}
void *out, void *gen, void *kill,
void *data ATTRIBUTE_UNUSED)
{
- *changed = bitmap_union_of_diff (in, gen, out, kill);
+ *changed = bitmap_ior_and_compl (in, gen, out, kill);
}
void *out, void *use, void *def,
void *data ATTRIBUTE_UNUSED)
{
- *changed = bitmap_union_of_diff (in, use, out, def);
+ *changed = bitmap_ior_and_compl (in, use, out, def);
}
{
struct bb_info *bb_info = DF_BB_INFO (df, bb);
rtx insn;
- bitmap seen = BITMAP_XMALLOC ();
+ bitmap seen = BITMAP_ALLOC (NULL);
bool call_seen = false;
FOR_BB_INSNS_REVERSE (bb, insn)
bitmap_set_bit (seen, regno);
}
- if (GET_CODE (insn) == CALL_INSN && (df->flags & DF_HARD_REGS))
+ if (CALL_P (insn) && (df->flags & DF_HARD_REGS))
{
- bitmap_operation (bb_info->rd_kill, bb_info->rd_kill,
- call_killed_defs, BITMAP_IOR);
+ bitmap_ior_into (bb_info->rd_kill, call_killed_defs);
call_seen = 1;
}
}
- BITMAP_XFREE (seen);
+ BITMAP_FREE (seen);
}
if (df->flags & DF_HARD_REGS)
{
- killed_by_call = BITMAP_XMALLOC ();
+ killed_by_call = BITMAP_ALLOC (NULL);
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
{
if (!TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
});
if (df->flags & DF_HARD_REGS)
- BITMAP_XFREE (killed_by_call);
+ BITMAP_FREE (killed_by_call);
}
unsigned int uid = INSN_UID (insn);
unsigned int regno;
struct df_link *link;
+ bitmap_iterator bi;
if (! INSN_P (insn))
continue;
}
/* Increment lifetimes of all live registers. */
- EXECUTE_IF_SET_IN_BITMAP (live, 0, regno,
- {
- reg_info[regno].lifetime++;
- });
+ EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
+ {
+ reg_info[regno].lifetime++;
+ }
}
}
basic_block bb;
bitmap live;
- live = BITMAP_XMALLOC ();
+ live = BITMAP_ALLOC (NULL);
FOR_EACH_BB_IN_BITMAP (blocks, 0, bb,
{
df_bb_reg_info_compute (df, bb, live);
});
- BITMAP_XFREE (live);
+ BITMAP_FREE (live);
}
df_refs_update (struct df *df, bitmap blocks)
{
basic_block bb;
- int count = 0, bbno;
+ unsigned count = 0, bbno;
df->n_regs = max_reg_num ();
if (df->n_regs >= df->reg_size)
}
else
{
- EXECUTE_IF_AND_IN_BITMAP (df->bbs_modified, blocks, 0, bbno,
+ bitmap_iterator bi;
+
+ EXECUTE_IF_AND_IN_BITMAP (df->bbs_modified, blocks, 0, bbno, bi)
{
count += df_bb_refs_update (df, BASIC_BLOCK (bbno));
- });
+ }
}
df_refs_process (df);
/* We could deal with additional basic blocks being created by
rescanning everything again. */
- if (df->n_bbs && df->n_bbs != (unsigned int) last_basic_block)
- abort ();
+ gcc_assert (!df->n_bbs || df->n_bbs == (unsigned int) last_basic_block);
update = df_modified_p (df, blocks);
if (update || (flags != df->flags))
if (blocks == (bitmap) -1)
blocks = df->bbs_modified;
- if (! df->n_bbs)
- abort ();
+ gcc_assert (df->n_bbs);
df_analyze_1 (df, blocks, flags, 1);
bitmap_zero (df->bbs_modified);
return last;
}
-/* Alternative entry point to the analysis. Analyse just the part of the cfg
+/* Alternative entry point to the analysis. Analyze just the part of the cfg
graph induced by BLOCKS.
TODO I am not quite sure how to avoid code duplication with df_analyze_1
handle the JUMP_LABEL? */
/* We should not be deleting the NOTE_INSN_BASIC_BLOCK or label. */
- if (insn == BB_HEAD (bb))
- abort ();
+ gcc_assert (insn != BB_HEAD (bb));
/* Delete the insn. */
delete_insn (insn);
if (! INSN_P (insn))
continue;
- if (bitmap_bit_p (blocks, DF_REF_BBNO (ref)))
- {
- df_ref_reg_replace (df, ref, oldreg, newreg);
+ gcc_assert (bitmap_bit_p (blocks, DF_REF_BBNO (ref)));
+
+ df_ref_reg_replace (df, ref, oldreg, newreg);
- /* Replace occurrences of the reg within the REG_NOTES. */
- if ((! link->next || DF_REF_INSN (ref)
- != DF_REF_INSN (link->next->ref))
- && REG_NOTES (insn))
- {
- args.insn = insn;
- for_each_rtx (®_NOTES (insn), df_rtx_reg_replace, &args);
- }
- }
- else
+ /* Replace occurrences of the reg within the REG_NOTES. */
+ if ((! link->next || DF_REF_INSN (ref)
+ != DF_REF_INSN (link->next->ref))
+ && REG_NOTES (insn))
{
- /* Temporary check to ensure that we have a grip on which
- regs should be replaced. */
- abort ();
+ args.insn = insn;
+ for_each_rtx (®_NOTES (insn), df_rtx_reg_replace, &args);
}
}
}
if (! INSN_P (DF_REF_INSN (ref)))
return 0;
- if (oldreg && oldreg != DF_REF_REG (ref))
- abort ();
+ gcc_assert (!oldreg || oldreg == DF_REF_REG (ref));
if (! validate_change (DF_REF_INSN (ref), DF_REF_LOC (ref), newreg, 1))
return 0;
/* A non-const call should not have slipped through the net. If
it does, we need to create a new basic block. Ouch. The
same applies for a label. */
- if ((GET_CODE (insn) == CALL_INSN
- && ! CONST_OR_PURE_CALL_P (insn))
- || GET_CODE (insn) == CODE_LABEL)
- abort ();
+ gcc_assert ((!CALL_P (insn) || CONST_OR_PURE_CALL_P (insn))
+ && !LABEL_P (insn));
uid = INSN_UID (insn);
rtx prev_insn = PREV_INSN (insn);
/* We should not be inserting before the start of the block. */
- if (insn == BB_HEAD (bb))
- abort ();
+ gcc_assert (insn != BB_HEAD (bb));
ret_insn = emit_insn_before (pattern, insn);
if (ret_insn == insn)
return ret_insn;
{
struct bb_info *bb_info = DF_BB_INFO (df, bb);
-#ifdef ENABLE_CHECKING
- if (! bb_info->lr_in)
- abort ();
-#endif
+ gcc_assert (bb_info->lr_in);
return bitmap_bit_p (bb_info->lr_in, REGNO (reg));
}
{
struct bb_info *bb_info = DF_BB_INFO (df, bb);
-#ifdef ENABLE_CHECKING
- if (! bb_info->lr_in)
- abort ();
-#endif
+ gcc_assert (bb_info->lr_in);
return bitmap_bit_p (bb_info->lr_out, REGNO (reg));
}
/* The regs must be local to BB. */
- if (df_regno_bb (df, regno1) != bb
- || df_regno_bb (df, regno2) != bb)
- abort ();
+ gcc_assert (df_regno_bb (df, regno1) == bb
+ && df_regno_bb (df, regno2) == bb);
def2 = df_bb_regno_first_def_find (df, bb, regno2);
use1 = df_bb_regno_last_use_find (df, bb, regno1);
def = df_bb_insn_regno_first_def_find (df, bb, insn, REGNO (reg));
- if (! def)
- abort ();
+ gcc_assert (def);
du_link = DF_REF_CHAIN (def);
}
\f
+/* Perform the set operation OP1 OP OP2, using set representation REPR, and
+ storing the result in OP1. */
+
static void
dataflow_set_a_op_b (enum set_representation repr,
enum df_confluence_op op,
- void *rslt, void *op1, void *op2)
+ void *op1, void *op2)
{
switch (repr)
{
switch (op)
{
case DF_UNION:
- sbitmap_a_or_b (rslt, op1, op2);
+ sbitmap_a_or_b (op1, op1, op2);
break;
case DF_INTERSECTION:
- sbitmap_a_and_b (rslt, op1, op2);
+ sbitmap_a_and_b (op1, op1, op2);
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
switch (op)
{
case DF_UNION:
- bitmap_a_or_b (rslt, op1, op2);
+ bitmap_ior_into (op1, op2);
break;
case DF_INTERSECTION:
- bitmap_a_and_b (rslt, op1, op2);
+ bitmap_and_into (op1, op2);
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
int changed;
int i = bb->index;
edge e;
+ edge_iterator ei;
SET_BIT (visited, bb->index);
- if (!TEST_BIT (pending, bb->index))
- abort ();
+ gcc_assert (TEST_BIT (pending, bb->index));
RESET_BIT (pending, i);
-#define HS(E_ANTI, E_ANTI_NEXT, E_ANTI_BB, E_ANTI_START_BB, IN_SET, \
- E, E_NEXT, E_BB, E_START_BB, OUT_SET) \
+#define HS(E_ANTI, E_ANTI_BB, E_ANTI_START_BB, IN_SET, \
+ E, E_BB, E_START_BB, OUT_SET) \
do \
{ \
/* Calculate <conf_op> of predecessor_outs. */ \
bitmap_zero (IN_SET[i]); \
- for (e = bb->E_ANTI; e; e = e->E_ANTI_NEXT) \
+ FOR_EACH_EDGE (e, ei, bb->E_ANTI) \
{ \
if (e->E_ANTI_BB == E_ANTI_START_BB) \
continue; \
continue; \
\
dataflow_set_a_op_b (dataflow->repr, dataflow->conf_op, \
- IN_SET[i], IN_SET[i], \
+ IN_SET[i], \
OUT_SET[e->E_ANTI_BB->index]); \
} \
\
if (!changed) \
break; \
\
- for (e = bb->E; e; e = e->E_NEXT) \
+ FOR_EACH_EDGE (e, ei, bb->E) \
{ \
if (e->E_BB == E_START_BB || e->E_BB->index == i) \
continue; \
SET_BIT (pending, e->E_BB->index); \
} \
\
- for (e = bb->E; e; e = e->E_NEXT) \
+ FOR_EACH_EDGE (e, ei, bb->E) \
{ \
if (e->E_BB == E_START_BB || e->E_BB->index == i) \
continue; \
} while (0)
if (dataflow->dir == DF_FORWARD)
- HS (pred, pred_next, src, ENTRY_BLOCK_PTR, dataflow->in,
- succ, succ_next, dest, EXIT_BLOCK_PTR, dataflow->out);
+ HS (preds, src, ENTRY_BLOCK_PTR, dataflow->in,
+ succs, dest, EXIT_BLOCK_PTR, dataflow->out);
else
- HS (succ, succ_next, dest, EXIT_BLOCK_PTR, dataflow->out,
- pred, pred_next, src, ENTRY_BLOCK_PTR, dataflow->in);
+ HS (succs, dest, EXIT_BLOCK_PTR, dataflow->out,
+ preds, src, ENTRY_BLOCK_PTR, dataflow->in);
}
/* This function will perform iterative bitvector dataflow described by