/* Scanning of rtl for dataflow analysis.
- Copyright (C) 2007
+ Copyright (C) 2007, 2008, 2009, 2010
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
+/* If a pass need to change these values in some magical way or the
pass needs to have accurate values for these and is not using
incremental df scanning, then it should use REG_N_SETS and
REG_N_USES. If the pass is doing incremental scanning then it
regstat_n_sets_and_refs = XNEWVEC (struct regstat_n_sets_and_refs_t, max_regno);
- 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));
- }
+ 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)
{
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 (DF_MWS_REG_DEF_P (mws))
+ 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++)
|| (!(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++)
{
df_ref use = *use_rec;
else if (REG_BASIC_BLOCK (uregno) != bb->index)
REG_BASIC_BLOCK (uregno) = REG_BLOCK_GLOBAL;
}
-
- if (!bitmap_bit_p (live, uregno))
+
+ if (bitmap_set_bit (live, uregno))
{
/* This register is now live. */
- bitmap_set_bit (live, uregno);
/* If we have seen this regno, then it has already been
processed correctly with the per insn increment. If
}
}
}
-
+
/* 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);
{
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
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++)
bitmap_clear_bit (live, DF_REF_REGNO (def));
}
}
-
+
for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
{
df_ref use = *use_rec;
{
gcc_assert (reg_info_p);
reg_info_p_size = 0;
- free (reg_info_p);
+ free (reg_info_p);
reg_info_p = NULL;
}