/* Scanning of rtl for dataflow analysis.
- Copyright (C) 2007
+ Copyright (C) 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Kenneth Zadeck (zadeck@naturalbridge.com).
struct regstat_n_sets_and_refs_t *regstat_n_sets_and_refs;
-struct regstat_n_sets_and_refs_t *regstat_n_sets_and_refs;
/*----------------------------------------------------------------------------
- REG_N_SETS and REG_N_REFS.
+ REG_N_SETS and REG_N_REFS.
----------------------------------------------------------------------------*/
/* If a pass need to change these values in some magical way or or the
df_grow_reg_info ();
gcc_assert (!regstat_n_sets_and_refs);
- regstat_n_sets_and_refs = xmalloc (max_regno * sizeof (struct regstat_n_sets_and_refs_t));
-
- for (i = 0; i < max_regno; i++)
- {
- SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
- SET_REG_N_REFS (i, DF_REG_USE_COUNT (i) + REG_N_SETS (i));
- }
+ regstat_n_sets_and_refs = XNEWVEC (struct regstat_n_sets_and_refs_t, max_regno);
+
+ if (MAY_HAVE_DEBUG_INSNS)
+ for (i = 0; i < max_regno; i++)
+ {
+ int use_count;
+ df_ref use;
+
+ use_count = DF_REG_USE_COUNT (i);
+ for (use = DF_REG_USE_CHAIN (i); use; use = DF_REF_NEXT_REG (use))
+ if (DF_REF_INSN_INFO (use) && DEBUG_INSN_P (DF_REF_INSN (use)))
+ use_count--;
+
+
+ SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
+ SET_REG_N_REFS (i, use_count + REG_N_SETS (i));
+ }
+ else
+ for (i = 0; i < max_regno; i++)
+ {
+ SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
+ SET_REG_N_REFS (i, DF_REG_USE_COUNT (i) + REG_N_SETS (i));
+ }
timevar_pop (TV_REG_STATS);
}
here. */
static void
-regstat_bb_compute_ri (unsigned int bb_index,
+regstat_bb_compute_ri (unsigned int bb_index,
bitmap live, bitmap do_not_gen, bitmap artificial_uses,
bitmap local_live, bitmap local_processed)
{
basic_block bb = BASIC_BLOCK (bb_index);
rtx insn;
- struct df_ref **def_rec;
- struct df_ref **use_rec;
+ df_ref *def_rec;
+ df_ref *use_rec;
int luid = 0;
bitmap_iterator bi;
unsigned int regno;
to begin processing. */
for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
{
- struct df_ref *def = *def_rec;
+ df_ref def = *def_rec;
if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
bitmap_clear_bit (live, DF_REF_REGNO (def));
}
for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
{
- struct df_ref *use = *use_rec;
+ df_ref use = *use_rec;
if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
{
regno = DF_REF_REGNO (use);
bitmap_set_bit (artificial_uses, regno);
}
}
-
+
FOR_BB_INSNS_REVERSE (bb, insn)
{
unsigned int uid = INSN_UID (insn);
bitmap_iterator bi;
struct df_mw_hardreg **mws_rec;
rtx link;
-
- if (!INSN_P (insn))
+
+ if (!NONDEBUG_INSN_P (insn))
continue;
/* Increment the live_length for all of the registers that
REG_LIVE_LENGTH (regno)++;
}
luid++;
-
+
bitmap_clear (do_not_gen);
link = REG_NOTES (insn);
/* Process the defs. */
if (CALL_P (insn))
{
- bool can_throw = can_throw_internal (insn);
+ bool can_throw = can_throw_internal (insn);
bool set_jump = (find_reg_note (insn, REG_SETJMP, NULL) != NULL);
EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
{
REG_FREQ_CALLS_CROSSED (regno) += REG_FREQ_FROM_BB (bb);
if (can_throw)
REG_N_THROWING_CALLS_CROSSED (regno)++;
-
+
/* We have a problem with any pseudoreg that lives
across the setjmp. ANSI says that if a user variable
does not change in value between the setjmp and the
bitmap_set_bit (setjmp_crosses, regno);
}
}
-
+
/* We only care about real sets for calls. Clobbers only
may clobbers cannot be depended on. */
for (mws_rec = DF_INSN_UID_MWS (uid); *mws_rec; mws_rec++)
{
- struct df_mw_hardreg *mws = *mws_rec;
- if (mws->type == DF_REF_REG_DEF)
+ struct df_mw_hardreg *mws = *mws_rec;
+ if (DF_MWS_REG_DEF_P (mws))
{
bool all_dead = true;
unsigned int r;
-
+
for (r=mws->start_regno; r <= mws->end_regno; r++)
if ((bitmap_bit_p (live, r))
|| bitmap_bit_p (artificial_uses, r))
all_dead = false;
break;
}
-
+
if (all_dead)
{
unsigned int regno = mws->start_regno;
}
}
}
-
+
/* All of the defs except the return value are some sort of
clobber. This code is for the return. */
for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
{
- struct df_ref *def = *def_rec;
+ df_ref def = *def_rec;
if ((!CALL_P (insn))
|| (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))))
{
unsigned int dregno = DF_REF_REGNO (def);
-
+
if (bitmap_bit_p (live, dregno))
{
/* If we have seen this regno, then it has already been
{
REG_LIVE_LENGTH (dregno)++;
}
-
+
if (dregno >= FIRST_PSEUDO_REGISTER)
{
REG_FREQ (dregno) += REG_FREQ_FROM_BB (bb);
else if (REG_BASIC_BLOCK (dregno) != bb->index)
REG_BASIC_BLOCK (dregno) = REG_BLOCK_GLOBAL;
}
-
+
if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER + DF_REF_MAY_CLOBBER)))
bitmap_set_bit (do_not_gen, dregno);
-
+
/* Kill this register if it is not a subreg store or conditional store. */
if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
bitmap_clear_bit (live, dregno);
}
}
-
+
for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
{
- struct df_ref *use = *use_rec;
+ df_ref use = *use_rec;
unsigned int uregno = DF_REF_REGNO (use);
if (uregno >= FIRST_PSEUDO_REGISTER)
else if (REG_BASIC_BLOCK (uregno) != bb->index)
REG_BASIC_BLOCK (uregno) = REG_BLOCK_GLOBAL;
}
-
+
if (!bitmap_bit_p (live, uregno))
{
/* This register is now live. */
}
}
}
-
+
/* Add the length of the block to all of the registers that were not
referenced, but still live in this block. */
bitmap_and_compl_into (live, local_processed);
setjmp_crosses = BITMAP_ALLOC (&df_bitmap_obstack);
max_regno = max_reg_num ();
reg_info_p_size = max_regno;
- reg_info_p = xcalloc (max_regno, sizeof (struct reg_info_t));
+ reg_info_p = XCNEWVEC (struct reg_info_t, max_regno);
FOR_EACH_BB (bb)
{
{
REG_BASIC_BLOCK (regno) = REG_BLOCK_UNKNOWN;
REG_LIVE_LENGTH (regno) = -1;
- }
-
+ }
+
BITMAP_FREE (local_live);
BITMAP_FREE (local_processed);
timevar_pop (TV_REG_STATS);
{
gcc_assert (reg_info_p);
reg_info_p_size = 0;
- free (reg_info_p);
+ free (reg_info_p);
reg_info_p = NULL;
BITMAP_FREE (setjmp_crosses);
}
-/* Return a bitmap containing the set of registers that cross a setjmp.
+/* Return a bitmap containing the set of registers that cross a setjmp.
The client should not change or delete this bitmap. */
bitmap
}
/*----------------------------------------------------------------------------
- Process REG_N_CALLS_CROSSED.
+ Process REG_N_CALLS_CROSSED.
This is used by sched_deps. A good implementation of sched-deps
would really process the blocks directly rather than going through
{
basic_block bb = BASIC_BLOCK (bb_index);
rtx insn;
- struct df_ref **def_rec;
- struct df_ref **use_rec;
+ df_ref *def_rec;
+ df_ref *use_rec;
bitmap_copy (live, df_get_live_out (bb));
to begin processing. */
for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
{
- struct df_ref *def = *def_rec;
+ df_ref def = *def_rec;
if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
bitmap_clear_bit (live, DF_REF_REGNO (def));
}
for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
{
- struct df_ref *use = *use_rec;
+ df_ref use = *use_rec;
if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
bitmap_set_bit (live, DF_REF_REGNO (use));
}
-
+
FOR_BB_INSNS_REVERSE (bb, insn)
{
unsigned int uid = INSN_UID (insn);
unsigned int regno;
-
+
if (!INSN_P (insn))
continue;
REG_FREQ_CALLS_CROSSED (regno) += REG_FREQ_FROM_BB (bb);
}
}
-
+
/* All of the defs except the return value are some sort of
clobber. This code is for the return. */
for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
{
- struct df_ref *def = *def_rec;
+ df_ref def = *def_rec;
if ((!CALL_P (insn))
|| (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))))
{
bitmap_clear_bit (live, DF_REF_REGNO (def));
}
}
-
+
for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
{
- struct df_ref *use = *use_rec;
+ df_ref use = *use_rec;
bitmap_set_bit (live, DF_REF_REGNO (use));
}
}
timevar_push (TV_REG_STATS);
max_regno = max_reg_num ();
reg_info_p_size = max_regno;
- reg_info_p = xcalloc (max_regno, sizeof (struct reg_info_t));
+ reg_info_p = XCNEWVEC (struct reg_info_t, max_regno);
FOR_EACH_BB (bb)
{
{
gcc_assert (reg_info_p);
reg_info_p_size = 0;
- free (reg_info_p);
+ free (reg_info_p);
reg_info_p = NULL;
}