/* Scanning of rtl for dataflow analysis.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Originally contributed by Michael P. Hayes
(m.hayes@elec.canterbury.ac.nz, mhayes@redhat.com)
Major rewrite contributed by Danny Berlin (dberlin@dberlin.org)
basic_block, struct df_insn_info *,
int ref_flags);
+static void df_install_ref_incremental (df_ref);
static df_ref df_ref_create_structure (enum df_ref_class,
struct df_collection_rec *, rtx, rtx *,
basic_block, struct df_insn_info *,
}
if (DF_REG_EQ_USE_COUNT (i))
{
- fprintf (file, "%s%dd", sep, DF_REG_EQ_USE_COUNT (i));
+ fprintf (file, "%s%de", sep, DF_REG_EQ_USE_COUNT (i));
ecount += DF_REG_EQ_USE_COUNT (i);
}
fprintf (file, "} ");
icount++;
}
- fprintf (file, "\n;; total ref usage %d{%dd,%du,%de} in %d{%d regular + %d call} insns.\n",
- dcount + ucount + ecount, dcount, ucount, ecount, icount + ccount, icount, ccount);
+ fprintf (file, "\n;; total ref usage %d{%dd,%du,%de}"
+ " in %d{%d regular + %d call} insns.\n",
+ dcount + ucount + ecount, dcount, ucount, ecount,
+ icount + ccount, icount, ccount);
}
/* Dump the bb_info for a given basic block. */
}
}
+/* Create new refs under address LOC within INSN. This function is
+ only used externally. REF_FLAGS must be either 0 or DF_REF_IN_NOTE,
+ depending on whether LOC is inside PATTERN (INSN) or a note. */
+
+void
+df_uses_create (rtx *loc, rtx insn, int ref_flags)
+{
+ gcc_assert (!(ref_flags & ~DF_REF_IN_NOTE));
+ df_uses_record (NULL, loc, DF_REF_REG_USE,
+ BLOCK_FOR_INSN (insn),
+ DF_INSN_INFO_GET (insn),
+ ref_flags);
+}
/* Create a new ref of type DF_REF_TYPE for register REG at address
LOC within INSN of BB. This function is only used externally. */
enum df_ref_type ref_type,
int ref_flags)
{
- df_ref ref;
- struct df_reg_info **reg_info;
- struct df_ref_info *ref_info;
- df_ref *ref_rec;
- df_ref **ref_rec_ptr;
- unsigned int count = 0;
- bool add_to_table;
enum df_ref_class cl;
df_grow_reg_info ();
cl = DF_REF_REGULAR;
else
cl = DF_REF_BASE;
- ref = df_ref_create_structure (cl, NULL, reg, loc, bb, DF_INSN_INFO_GET (insn),
- ref_type, ref_flags);
+
+ return df_ref_create_structure (cl, NULL, reg, loc, bb,
+ DF_INSN_INFO_GET (insn),
+ ref_type, ref_flags);
+}
+
+static void
+df_install_ref_incremental (df_ref ref)
+{
+ struct df_reg_info **reg_info;
+ struct df_ref_info *ref_info;
+ df_ref *ref_rec;
+ df_ref **ref_rec_ptr;
+ unsigned int count = 0;
+ bool add_to_table;
+
+ rtx insn = DF_REF_INSN (ref);
+ basic_block bb = BLOCK_FOR_INSN (insn);
if (DF_REF_REG_DEF_P (ref))
{
to mark the block dirty ourselves. */
if (!DEBUG_INSN_P (DF_REF_INSN (ref)))
df_set_bb_dirty (bb);
-
- return ref;
}
}
df_refs_add_to_chains (&collection_rec, bb, insn);
- if (DEBUG_INSN_P (insn))
- df_set_bb_dirty_nonlr (bb);
- else
+ if (!DEBUG_INSN_P (insn))
df_set_bb_dirty (bb);
VEC_free (df_ref, stack, collection_rec.def_vec);
else
VEC_safe_push (df_ref, stack, collection_rec->use_vec, this_ref);
}
+ else
+ df_install_ref_incremental (this_ref);
return this_ref;
}
/* If this is a multiword hardreg, we create some extra
datastructures that will enable us to easily build REG_DEAD
and REG_UNUSED notes. */
- if ((endregno != regno + 1) && insn_info)
+ if (collection_rec
+ && (endregno != regno + 1) && insn_info)
{
/* Sets to a subreg of a multiword register are partial.
Sets to a non-subreg of a multiword register are not. */
NULL, bb, insn_info, DF_REF_REG_USE,
DF_REF_CALL_STACK_USAGE | flags);
- /* Calls may also reference any of the global registers,
- so they are recorded as used. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i])
- {
- df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[i],
- NULL, bb, insn_info, DF_REF_REG_USE, flags);
- df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[i],
- NULL, bb, insn_info, DF_REF_REG_DEF, flags);
- }
+ /* Calls to const functions cannot access any global registers and calls to
+ pure functions cannot set them. All other calls may reference any of the
+ global registers, so they are recorded as used. */
+ if (!RTL_CONST_CALL_P (insn_info->insn))
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (global_regs[i])
+ {
+ df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[i],
+ NULL, bb, insn_info, DF_REF_REG_USE, flags);
+ if (!RTL_PURE_CALL_P (insn_info->insn))
+ df_ref_record (DF_REF_BASE, collection_rec, regno_reg_rtx[i],
+ NULL, bb, insn_info, DF_REF_REG_DEF, flags);
+ }
is_sibling_call = SIBLING_CALL_P (insn_info->insn);
EXECUTE_IF_SET_IN_BITMAP (regs_invalidated_by_call_regset, 0, ui, bi)