/* 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).
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"
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_N_CALLS_CROSSED (regno)++;
+ 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))
+
+ 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);
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 thur
+ would really process the blocks directly rather than going through
lists of insns. If it did this, it could use the exact regs that
cross an individual call rather than using this info that merges
the info for all calls.
-/* Compute callse crossed for BB. Live is a scratch bitvector. */
+/* Compute calls crossed for BB. Live is a scratch bitvector. */
static void
regstat_bb_compute_calls_crossed (unsigned int bb_index, bitmap live)
{
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;
{
bitmap_iterator bi;
EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
- REG_N_CALLS_CROSSED (regno)++;
+ {
+ REG_N_CALLS_CROSSED (regno)++;
+ 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;
}