/* Scanning of rtl for dataflow analysis.
- Copyright (C) 1999-2015 Free Software Foundation, Inc.
+ Copyright (C) 1999-2018 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)
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "target.h"
#include "rtl.h"
-#include "tm_p.h"
-#include "insn-config.h"
-#include "recog.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "vec.h"
-#include "double-int.h"
-#include "input.h"
-#include "alias.h"
-#include "symtab.h"
-#include "wide-int.h"
-#include "inchash.h"
-#include "hard-reg-set.h"
-#include "input.h"
-#include "function.h"
-#include "regs.h"
-#include "alloc-pool.h"
-#include "flags.h"
-#include "predict.h"
-#include "dominance.h"
-#include "cfg.h"
-#include "basic-block.h"
-#include "sbitmap.h"
-#include "bitmap.h"
-#include "dumpfile.h"
#include "tree.h"
-#include "target.h"
-#include "target-def.h"
#include "df.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "regs.h"
#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */
+#include "dumpfile.h"
+#include "calls.h"
-typedef struct df_mw_hardreg *df_mw_hardreg_ptr;
-
-
-#ifndef HAVE_prologue
-#define HAVE_prologue 0
-#endif
-#ifndef HAVE_sibcall_epilogue
-#define HAVE_sibcall_epilogue 0
-#endif
-
/* The set of hard registers in eliminables[i].from. */
static HARD_REG_SET elim_reg_set;
auto_vec<df_ref, 128> def_vec;
auto_vec<df_ref, 32> use_vec;
auto_vec<df_ref, 32> eq_use_vec;
- auto_vec<df_mw_hardreg_ptr, 32> mw_vec;
+ auto_vec<df_mw_hardreg *, 32> mw_vec;
};
static void df_ref_record (enum df_ref_class, struct df_collection_rec *,
/* Problem data for the scanning dataflow function. */
struct df_scan_problem_data
{
- alloc_pool ref_base_pool;
- alloc_pool ref_artificial_pool;
- alloc_pool ref_regular_pool;
- alloc_pool insn_pool;
- alloc_pool reg_pool;
- alloc_pool mw_reg_pool;
+ object_allocator<df_base_ref> *ref_base_pool;
+ object_allocator<df_artificial_ref> *ref_artificial_pool;
+ object_allocator<df_regular_ref> *ref_regular_pool;
+ object_allocator<df_insn_info> *insn_pool;
+ object_allocator<df_reg_info> *reg_pool;
+ object_allocator<df_mw_hardreg> *mw_reg_pool;
+
bitmap_obstack reg_bitmaps;
bitmap_obstack insn_bitmaps;
};
-typedef struct df_scan_bb_info *df_scan_bb_info_t;
-
-
/* Internal function to shut down the scanning problem. */
static void
df_scan_free_internal (void)
bitmap_clear (&df->insns_to_rescan);
bitmap_clear (&df->insns_to_notes_rescan);
- free_alloc_pool (problem_data->ref_base_pool);
- free_alloc_pool (problem_data->ref_artificial_pool);
- free_alloc_pool (problem_data->ref_regular_pool);
- free_alloc_pool (problem_data->insn_pool);
- free_alloc_pool (problem_data->reg_pool);
- free_alloc_pool (problem_data->mw_reg_pool);
+ delete problem_data->ref_base_pool;
+ delete problem_data->ref_artificial_pool;
+ delete problem_data->ref_regular_pool;
+ delete problem_data->insn_pool;
+ delete problem_data->reg_pool;
+ delete problem_data->mw_reg_pool;
bitmap_obstack_release (&problem_data->reg_bitmaps);
bitmap_obstack_release (&problem_data->insn_bitmaps);
free (df_scan->problem_data);
{
struct df_scan_problem_data *problem_data;
unsigned int insn_num = get_max_uid () + 1;
- unsigned int block_size = 512;
basic_block bb;
/* Given the number of pools, this is really faster than tearing
df_scan->problem_data = problem_data;
df_scan->computed = true;
- problem_data->ref_base_pool
- = create_alloc_pool ("df_scan ref base",
- sizeof (struct df_base_ref), block_size);
- problem_data->ref_artificial_pool
- = create_alloc_pool ("df_scan ref artificial",
- sizeof (struct df_artificial_ref), block_size);
- problem_data->ref_regular_pool
- = create_alloc_pool ("df_scan ref regular",
- sizeof (struct df_regular_ref), block_size);
- problem_data->insn_pool
- = create_alloc_pool ("df_scan insn",
- sizeof (struct df_insn_info), block_size);
- problem_data->reg_pool
- = create_alloc_pool ("df_scan reg",
- sizeof (struct df_reg_info), block_size);
- problem_data->mw_reg_pool
- = create_alloc_pool ("df_scan mw_reg",
- sizeof (struct df_mw_hardreg), block_size / 16);
+ problem_data->ref_base_pool = new object_allocator<df_base_ref>
+ ("df_scan ref base");
+ problem_data->ref_artificial_pool = new object_allocator<df_artificial_ref>
+ ("df_scan ref artificial");
+ problem_data->ref_regular_pool = new object_allocator<df_regular_ref>
+ ("df_scan ref regular");
+ problem_data->insn_pool = new object_allocator<df_insn_info>
+ ("df_scan insn");
+ problem_data->reg_pool = new object_allocator<df_reg_info>
+ ("df_scan reg");
+ problem_data->mw_reg_pool = new object_allocator<df_mw_hardreg>
+ ("df_scan mw_reg");
bitmap_obstack_initialize (&problem_data->reg_bitmaps);
bitmap_obstack_initialize (&problem_data->insn_bitmaps);
fprintf (file, ";; regs ever live \t");
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (df_regs_ever_live_p (i))
- fprintf (file, " %d[%s]", i, reg_names[i]);
+ fprintf (file, " %d [%s]", i, reg_names[i]);
fprintf (file, "\n;; ref usage \t");
for (i = 0; i < (int)df->regs_inited; i++)
#endif
}
-static struct df_problem problem_SCAN =
+static const struct df_problem problem_SCAN =
{
DF_SCAN, /* Problem id. */
DF_NONE, /* Direction. */
{
struct df_reg_info *reg_info;
- reg_info = (struct df_reg_info *) pool_alloc (problem_data->reg_pool);
+ // TODO
+ reg_info = problem_data->reg_pool->allocate ();
memset (reg_info, 0, sizeof (struct df_reg_info));
df->def_regs[i] = reg_info;
- reg_info = (struct df_reg_info *) pool_alloc (problem_data->reg_pool);
+ reg_info = problem_data->reg_pool->allocate ();
memset (reg_info, 0, sizeof (struct df_reg_info));
df->use_regs[i] = reg_info;
- reg_info = (struct df_reg_info *) pool_alloc (problem_data->reg_pool);
+ reg_info = problem_data->reg_pool->allocate ();
memset (reg_info, 0, sizeof (struct df_reg_info));
df->eq_use_regs[i] = reg_info;
df->def_info.begin[i] = 0;
switch (DF_REF_CLASS (ref))
{
case DF_REF_BASE:
- pool_free (problem_data->ref_base_pool, ref);
+ problem_data->ref_base_pool->remove ((df_base_ref *) (ref));
break;
case DF_REF_ARTIFICIAL:
- pool_free (problem_data->ref_artificial_pool, ref);
+ problem_data->ref_artificial_pool->remove
+ ((df_artificial_ref *) (ref));
break;
case DF_REF_REGULAR:
- pool_free (problem_data->ref_regular_pool, ref);
+ problem_data->ref_regular_pool->remove
+ ((df_regular_ref *) (ref));
break;
}
}
df_free_ref (ref);
}
+/* Initialize INSN_INFO to describe INSN. */
+
+static void
+df_insn_info_init_fields (df_insn_info *insn_info, rtx_insn *insn)
+{
+ memset (insn_info, 0, sizeof (struct df_insn_info));
+ insn_info->insn = insn;
+}
/* Create the insn record for INSN. If there was one there, zero it
out. */
insn_rec = DF_INSN_INFO_GET (insn);
if (!insn_rec)
{
- insn_rec = (struct df_insn_info *) pool_alloc (problem_data->insn_pool);
+ insn_rec = problem_data->insn_pool->allocate ();
DF_INSN_INFO_SET (insn, insn_rec);
}
- memset (insn_rec, 0, sizeof (struct df_insn_info));
- insn_rec->insn = insn;
+ df_insn_info_init_fields (insn_rec, insn);
return insn_rec;
}
for (; hardregs; hardregs = next)
{
next = DF_MWS_NEXT (hardregs);
- pool_free (problem_data->mw_reg_pool, hardregs);
+ problem_data->mw_reg_pool->remove (hardregs);
}
}
+/* Remove the contents of INSN_INFO (but don't free INSN_INFO itself). */
+
+static void
+df_insn_info_free_fields (df_insn_info *insn_info)
+{
+ /* In general, notes do not have the insn_info fields
+ initialized. However, combine deletes insns by changing them
+ to notes. How clever. So we cannot just check if it is a
+ valid insn before short circuiting this code, we need to see
+ if we actually initialized it. */
+ df_mw_hardreg_chain_delete (insn_info->mw_hardregs);
+
+ if (df_chain)
+ {
+ df_ref_chain_delete_du_chain (insn_info->defs);
+ df_ref_chain_delete_du_chain (insn_info->uses);
+ df_ref_chain_delete_du_chain (insn_info->eq_uses);
+ }
+
+ df_ref_chain_delete (insn_info->defs);
+ df_ref_chain_delete (insn_info->uses);
+ df_ref_chain_delete (insn_info->eq_uses);
+}
/* Delete all of the refs information from the insn with UID.
Internal helper for df_insn_delete, df_insn_rescan, and other
struct df_scan_problem_data *problem_data
= (struct df_scan_problem_data *) df_scan->problem_data;
- /* In general, notes do not have the insn_info fields
- initialized. However, combine deletes insns by changing them
- to notes. How clever. So we cannot just check if it is a
- valid insn before short circuiting this code, we need to see
- if we actually initialized it. */
- df_mw_hardreg_chain_delete (insn_info->mw_hardregs);
-
- if (df_chain)
- {
- df_ref_chain_delete_du_chain (insn_info->defs);
- df_ref_chain_delete_du_chain (insn_info->uses);
- df_ref_chain_delete_du_chain (insn_info->eq_uses);
- }
-
- df_ref_chain_delete (insn_info->defs);
- df_ref_chain_delete (insn_info->uses);
- df_ref_chain_delete (insn_info->eq_uses);
-
- pool_free (problem_data->insn_pool, insn_info);
+ df_insn_info_free_fields (insn_info);
+ problem_data->insn_pool->remove (insn_info);
DF_INSN_UID_SET (uid, NULL);
}
}
FOR_EACH_VEC_ELT (collection_rec->eq_use_vec, ix, ref)
df_free_ref (ref);
FOR_EACH_VEC_ELT (collection_rec->mw_vec, ix, mw)
- pool_free (problem_data->mw_reg_pool, mw);
+ problem_data->mw_reg_pool->remove (mw);
collection_rec->def_vec.release ();
collection_rec->use_vec.release ();
/* There's change - we need to delete the existing info.
Since the insn isn't moved, we can salvage its LUID. */
luid = DF_INSN_LUID (insn);
- df_insn_info_delete (uid);
- df_insn_create_insn_record (insn);
+ df_insn_info_free_fields (insn_info);
+ df_insn_info_init_fields (insn_info, insn);
DF_INSN_LUID (insn) = luid;
}
else
basic_block bb;
bitmap_iterator bi;
unsigned int uid;
- bitmap_head tmp;
-
- bitmap_initialize (&tmp, &df_bitmap_obstack);
if (df->changeable_flags & DF_NO_INSN_RESCAN)
{
defer_insn_rescan = true;
}
- bitmap_copy (&tmp, &df->insns_to_delete);
- EXECUTE_IF_SET_IN_BITMAP (&tmp, 0, uid, bi)
+ auto_bitmap tmp (&df_bitmap_obstack);
+ bitmap_copy (tmp, &df->insns_to_delete);
+ EXECUTE_IF_SET_IN_BITMAP (tmp, 0, uid, bi)
{
struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
if (insn_info)
df_insn_info_delete (uid);
}
- bitmap_clear (&tmp);
bitmap_clear (&df->insns_to_delete);
bitmap_clear (&df->insns_to_rescan);
bitmap_clear (&df->insns_to_notes_rescan);
bool defer_insn_rescan = false;
bitmap_iterator bi;
unsigned int uid;
- bitmap_head tmp;
-
- bitmap_initialize (&tmp, &df_bitmap_obstack);
if (df->changeable_flags & DF_NO_INSN_RESCAN)
{
if (dump_file)
fprintf (dump_file, "starting the processing of deferred insns\n");
- bitmap_copy (&tmp, &df->insns_to_delete);
- EXECUTE_IF_SET_IN_BITMAP (&tmp, 0, uid, bi)
+ auto_bitmap tmp (&df_bitmap_obstack);
+ bitmap_copy (tmp, &df->insns_to_delete);
+ EXECUTE_IF_SET_IN_BITMAP (tmp, 0, uid, bi)
{
struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
if (insn_info)
df_insn_info_delete (uid);
}
- bitmap_copy (&tmp, &df->insns_to_rescan);
- EXECUTE_IF_SET_IN_BITMAP (&tmp, 0, uid, bi)
+ bitmap_copy (tmp, &df->insns_to_rescan);
+ EXECUTE_IF_SET_IN_BITMAP (tmp, 0, uid, bi)
{
struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
if (insn_info)
df_insn_rescan (insn_info->insn);
}
- bitmap_copy (&tmp, &df->insns_to_notes_rescan);
- EXECUTE_IF_SET_IN_BITMAP (&tmp, 0, uid, bi)
+ bitmap_copy (tmp, &df->insns_to_notes_rescan);
+ EXECUTE_IF_SET_IN_BITMAP (tmp, 0, uid, bi)
{
struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
if (insn_info)
if (dump_file)
fprintf (dump_file, "ending the processing of deferred insns\n");
- bitmap_clear (&tmp);
bitmap_clear (&df->insns_to_delete);
bitmap_clear (&df->insns_to_rescan);
bitmap_clear (&df->insns_to_notes_rescan);
static void
df_ref_change_reg_with_loc_1 (struct df_reg_info *old_df,
struct df_reg_info *new_df,
- int new_regno, rtx loc)
+ unsigned int new_regno, rtx loc)
{
df_ref the_ref = old_df->reg_chain;
}
-/* Change the regno of all refs that contained LOC from OLD_REGNO to
- NEW_REGNO. Refs that do not match LOC are not changed which means
- that artificial refs are not changed since they have no loc. This
- call is to support the SET_REGNO macro. */
+/* Change the regno of register LOC to NEW_REGNO and update the df
+ information accordingly. Refs that do not match LOC are not changed
+ which means that artificial refs are not changed since they have no loc.
+ This call is to support the SET_REGNO macro. */
void
-df_ref_change_reg_with_loc (int old_regno, int new_regno, rtx loc)
+df_ref_change_reg_with_loc (rtx loc, unsigned int new_regno)
{
- if ((!df) || (old_regno == -1) || (old_regno == new_regno))
+ unsigned int old_regno = REGNO (loc);
+ if (old_regno == new_regno)
return;
- df_grow_reg_info ();
-
- df_ref_change_reg_with_loc_1 (DF_REG_DEF_GET (old_regno),
- DF_REG_DEF_GET (new_regno), new_regno, loc);
- df_ref_change_reg_with_loc_1 (DF_REG_USE_GET (old_regno),
- DF_REG_USE_GET (new_regno), new_regno, loc);
- df_ref_change_reg_with_loc_1 (DF_REG_EQ_USE_GET (old_regno),
- DF_REG_EQ_USE_GET (new_regno), new_regno, loc);
+ if (df)
+ {
+ df_grow_reg_info ();
+
+ df_ref_change_reg_with_loc_1 (DF_REG_DEF_GET (old_regno),
+ DF_REG_DEF_GET (new_regno),
+ new_regno, loc);
+ df_ref_change_reg_with_loc_1 (DF_REG_USE_GET (old_regno),
+ DF_REG_USE_GET (new_regno),
+ new_regno, loc);
+ df_ref_change_reg_with_loc_1 (DF_REG_EQ_USE_GET (old_regno),
+ DF_REG_EQ_USE_GET (new_regno),
+ new_regno, loc);
+ }
+ set_mode_and_regno (loc, GET_MODE (loc), new_regno);
}
if (mw->flags & DF_REF_IN_NOTE)
{
*mw_ptr = DF_MWS_NEXT (mw);
- pool_free (problem_data->mw_reg_pool, mw);
+ problem_data->mw_reg_pool->remove (mw);
}
else
mw_ptr = &DF_MWS_NEXT (mw);
return df_ref_compare (*(const df_ref *) r1, *(const df_ref *) r2);
}
-static void
-df_swap_refs (vec<df_ref, va_heap> *ref_vec, int i, int j)
-{
- df_ref tmp = (*ref_vec)[i];
- (*ref_vec)[i] = (*ref_vec)[j];
- (*ref_vec)[j] = tmp;
-}
-
/* Sort and compress a set of refs. */
static void
df_ref r0 = (*ref_vec)[0];
df_ref r1 = (*ref_vec)[1];
if (df_ref_compare (r0, r1) > 0)
- df_swap_refs (ref_vec, 0, 1);
+ std::swap ((*ref_vec)[0], (*ref_vec)[1]);
}
else
{
/* Sort and compress a set of refs. */
static void
-df_sort_and_compress_mws (vec<df_mw_hardreg_ptr, va_heap> *mw_vec)
+df_sort_and_compress_mws (vec<df_mw_hardreg *, va_heap> *mw_vec)
{
unsigned int count;
struct df_scan_problem_data *problem_data
while (i + dist + 1 < count
&& df_mw_equal_p ((*mw_vec)[i], (*mw_vec)[i + dist + 1]))
{
- pool_free (problem_data->mw_reg_pool,
- (*mw_vec)[i + dist + 1]);
+ problem_data->mw_reg_pool->remove ((*mw_vec)[i + dist + 1]);
dist++;
}
/* Copy it down to the next position. */
insn. */
static struct df_mw_hardreg *
-df_install_mws (const vec<df_mw_hardreg_ptr, va_heap> *old_vec)
+df_install_mws (const vec<df_mw_hardreg *, va_heap> *old_vec)
{
unsigned int count = old_vec->length ();
if (count)
int ref_flags)
{
df_ref this_ref = NULL;
- int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
+ unsigned int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
struct df_scan_problem_data *problem_data
= (struct df_scan_problem_data *) df_scan->problem_data;
switch (cl)
{
case DF_REF_BASE:
- this_ref = (df_ref) pool_alloc (problem_data->ref_base_pool);
+ this_ref = (df_ref) (problem_data->ref_base_pool->allocate ());
gcc_checking_assert (loc == NULL);
break;
case DF_REF_ARTIFICIAL:
- this_ref = (df_ref) pool_alloc (problem_data->ref_artificial_pool);
+ this_ref = (df_ref) (problem_data->ref_artificial_pool->allocate ());
this_ref->artificial_ref.bb = bb;
gcc_checking_assert (loc == NULL);
break;
case DF_REF_REGULAR:
- this_ref = (df_ref) pool_alloc (problem_data->ref_regular_pool);
+ this_ref = (df_ref) (problem_data->ref_regular_pool->allocate ());
this_ref->regular_ref.loc = loc;
gcc_checking_assert (loc);
break;
endregno = regno + subreg_nregs (reg);
}
else
- endregno = END_HARD_REGNO (reg);
+ endregno = END_REGNO (reg);
/* If this is a multiword hardreg, we create some extra
datastructures that will enable us to easily build REG_DEAD
ref_flags |= DF_REF_PARTIAL;
ref_flags |= DF_REF_MW_HARDREG;
- hardreg = (struct df_mw_hardreg *) pool_alloc (problem_data->mw_reg_pool);
+ hardreg = problem_data->mw_reg_pool->allocate ();
hardreg->type = ref_type;
hardreg->flags = ref_flags;
hardreg->mw_reg = reg;
}
-/* 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
-df_read_modify_subreg_p (rtx x)
-{
- unsigned int isize, osize;
- if (GET_CODE (x) != SUBREG)
- return false;
- isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
- osize = GET_MODE_SIZE (GET_MODE (x));
- return isize > osize
- && isize > REGMODE_NATURAL_SIZE (GET_MODE (SUBREG_REG (x)));
-}
-
-
/* Process all the registers defined in the rtx pointed by LOC.
Autoincrement/decrement definitions will be picked up by df_uses_record.
Any change here has to be matched in df_find_hard_reg_defs_1. */
}
else if (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst)))
{
- if (df_read_modify_subreg_p (dst))
+ if (read_modify_subreg_p (dst))
flags |= DF_REF_READ_WRITE | DF_REF_PARTIAL;
flags |= DF_REF_SUBREG;
df_uses_record (collection_rec, loc, ref_type, bb, insn_info, flags);
return;
}
- /* ... Fall through ... */
+ /* Fall through */
case REG:
df_ref_record (DF_REF_REGULAR, collection_rec,
switch (GET_CODE (dst))
{
case SUBREG:
- if (df_read_modify_subreg_p (dst))
+ if (read_modify_subreg_p (dst))
{
df_uses_record (collection_rec, &SUBREG_REG (dst),
DF_REF_REG_USE, bb, insn_info,
}
}
+ int flags = (is_cond_exec) ? DF_REF_CONDITIONAL : 0;
/* For CALL_INSNs, first record DF_REF_BASE register defs, as well as
uses from CALL_INSN_FUNCTION_USAGE. */
if (CALL_P (insn_info->insn))
- df_get_call_refs (collection_rec, bb, insn_info,
- (is_cond_exec) ? DF_REF_CONDITIONAL : 0);
+ df_get_call_refs (collection_rec, bb, insn_info, flags);
+
+ if (asm_noperands (PATTERN (insn_info->insn)) >= 0)
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (global_regs[i])
+ {
+ /* As with calls, asm statements reference all global regs. */
+ 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);
+ }
/* Record other defs. These should be mostly for DF_REF_REGULAR, so
that a qsort on the defs is unnecessary in most cases. */
bitmap_set_bit (regular_block_artificial_uses,
HARD_FRAME_POINTER_REGNUM);
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* Pseudos with argument area equivalences may require
reloading via the argument pointer. */
- if (fixed_regs[ARG_POINTER_REGNUM])
+ if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ && fixed_regs[ARG_POINTER_REGNUM])
bitmap_set_bit (regular_block_artificial_uses, ARG_POINTER_REGNUM);
-#endif
/* Any constant, or pseudo with constant equivalences, may
require reloading from memory using the pic register. */
bitmap_set_bit (eh_block_artificial_uses,
HARD_FRAME_POINTER_REGNUM);
}
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- if (fixed_regs[ARG_POINTER_REGNUM])
+ if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ && fixed_regs[ARG_POINTER_REGNUM])
bitmap_set_bit (eh_block_artificial_uses, ARG_POINTER_REGNUM);
-#endif
}
}
static void
df_mark_reg (rtx reg, void *vset)
{
- bitmap set = (bitmap) vset;
- int regno = REGNO (reg);
-
- gcc_assert (GET_MODE (reg) != BLKmode);
-
- if (regno < FIRST_PSEUDO_REGISTER)
- {
- int n = hard_regno_nregs[regno][GET_MODE (reg)];
- bitmap_set_range (set, regno, n);
- }
- else
- bitmap_set_bit (set, regno);
+ bitmap_set_range ((bitmap) vset, REGNO (reg), REG_NREGS (reg));
}
bitmap_clear (entry_block_defs);
+ /* For separate shrink-wrapping we use LIVE to analyze which basic blocks
+ need a prologue for some component to be executed before that block,
+ and we do not care about any other registers. Hence, we do not want
+ any register for any component defined in the entry block, and we can
+ just leave all registers undefined. */
+ if (df_scan->local_flags & DF_SCAN_EMPTY_ENTRY_EXIT)
+ return;
+
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
if (global_regs[i])
/* Once the prologue has been generated, all of these registers
should just show up in the first regular block. */
- if (HAVE_prologue && epilogue_completed)
+ if (targetm.have_prologue () && epilogue_completed)
{
/* Defs for the callee saved registers are inserted so that the
pushes have some defining location. */
/* If the function has an incoming STATIC_CHAIN, it has to show up
in the entry def set. */
- r = targetm.calls.static_chain (current_function_decl, true);
+ r = rtx_for_static_chain (current_function_decl, true);
if (r && REG_P (r))
bitmap_set_bit (entry_block_defs, REGNO (r));
/* These registers are live everywhere. */
if (!reload_completed)
{
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* Pseudos with argument area equivalences may require
reloading via the argument pointer. */
- if (fixed_regs[ARG_POINTER_REGNUM])
+ if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ && fixed_regs[ARG_POINTER_REGNUM])
bitmap_set_bit (entry_block_defs, ARG_POINTER_REGNUM);
-#endif
/* Any constant, or pseudo with constant equivalences, may
require reloading from memory using the pic register. */
void
df_update_entry_block_defs (void)
{
- bitmap_head refs;
bool changed = false;
- bitmap_initialize (&refs, &df_bitmap_obstack);
- df_get_entry_block_def_set (&refs);
+ auto_bitmap refs (&df_bitmap_obstack);
+ df_get_entry_block_def_set (refs);
if (df->entry_block_defs)
{
- if (!bitmap_equal_p (df->entry_block_defs, &refs))
+ if (!bitmap_equal_p (df->entry_block_defs, refs))
{
struct df_scan_bb_info *bb_info = df_scan_get_bb_info (ENTRY_BLOCK);
df_ref_chain_delete_du_chain (bb_info->artificial_defs);
if (changed)
{
- df_record_entry_block_defs (&refs);
- bitmap_copy (df->entry_block_defs, &refs);
+ df_record_entry_block_defs (refs);
+ bitmap_copy (df->entry_block_defs, refs);
df_set_bb_dirty (BASIC_BLOCK_FOR_FN (cfun, ENTRY_BLOCK));
}
- bitmap_clear (&refs);
}
bitmap_clear (exit_block_uses);
+ /* For separate shrink-wrapping we use LIVE to analyze which basic blocks
+ need an epilogue for some component to be executed after that block,
+ and we do not care about any other registers. Hence, we do not want
+ any register for any component seen as used in the exit block, and we
+ can just say no registers at all are used. */
+ if (df_scan->local_flags & DF_SCAN_EMPTY_ENTRY_EXIT)
+ return;
+
/* Stack pointer is always live at the exit. */
bitmap_set_bit (exit_block_uses, STACK_POINTER_REGNUM);
if (global_regs[i] || EPILOGUE_USES (i))
bitmap_set_bit (exit_block_uses, i);
- if (HAVE_epilogue && epilogue_completed)
+ if (targetm.have_epilogue () && epilogue_completed)
{
/* Mark all call-saved registers that we actually used. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
}
#ifdef EH_RETURN_STACKADJ_RTX
- if ((!HAVE_epilogue || ! epilogue_completed)
+ if ((!targetm.have_epilogue () || ! epilogue_completed)
&& crtl->calls_eh_return)
{
rtx tmp = EH_RETURN_STACKADJ_RTX;
}
#endif
-#ifdef EH_RETURN_HANDLER_RTX
- if ((!HAVE_epilogue || ! epilogue_completed)
+ if ((!targetm.have_epilogue () || ! epilogue_completed)
&& crtl->calls_eh_return)
{
rtx tmp = EH_RETURN_HANDLER_RTX;
if (tmp && REG_P (tmp))
df_mark_reg (tmp, exit_block_uses);
}
-#endif
/* Mark function return value. */
diddle_return_value (df_mark_reg, (void*) exit_block_uses);
df_ref_record (DF_REF_ARTIFICIAL, collection_rec, regno_reg_rtx[i], NULL,
EXIT_BLOCK_PTR_FOR_FN (cfun), NULL, DF_REF_REG_USE, 0);
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* It is deliberate that this is not put in the exit block uses but
I do not know why. */
- if (reload_completed
+ if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ && reload_completed
&& !bitmap_bit_p (exit_block_uses, ARG_POINTER_REGNUM)
&& bb_has_eh_pred (EXIT_BLOCK_PTR_FOR_FN (cfun))
&& fixed_regs[ARG_POINTER_REGNUM])
df_ref_record (DF_REF_ARTIFICIAL, collection_rec, regno_reg_rtx[ARG_POINTER_REGNUM], NULL,
EXIT_BLOCK_PTR_FOR_FN (cfun), NULL, DF_REF_REG_USE, 0);
-#endif
df_canonize_collection_rec (collection_rec);
}
void
df_update_exit_block_uses (void)
{
- bitmap_head refs;
bool changed = false;
- bitmap_initialize (&refs, &df_bitmap_obstack);
- df_get_exit_block_use_set (&refs);
+ auto_bitmap refs (&df_bitmap_obstack);
+ df_get_exit_block_use_set (refs);
if (df->exit_block_uses)
{
- if (!bitmap_equal_p (df->exit_block_uses, &refs))
+ if (!bitmap_equal_p (df->exit_block_uses, refs))
{
struct df_scan_bb_info *bb_info = df_scan_get_bb_info (EXIT_BLOCK);
df_ref_chain_delete_du_chain (bb_info->artificial_uses);
if (changed)
{
- df_record_exit_block_uses (&refs);
- bitmap_copy (df->exit_block_uses,& refs);
+ df_record_exit_block_uses (refs);
+ bitmap_copy (df->exit_block_uses, refs);
df_set_bb_dirty (BASIC_BLOCK_FOR_FN (cfun, EXIT_BLOCK));
}
- bitmap_clear (&refs);
}
static bool initialized = false;
void
df_hard_reg_init (void)
{
-#ifdef ELIMINABLE_REGS
int i;
static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
-#endif
+
if (initialized)
return;
mark_used_regs. */
CLEAR_HARD_REG_SET (elim_reg_set);
-#ifdef ELIMINABLE_REGS
for (i = 0; i < (int) ARRAY_SIZE (eliminables); i++)
SET_HARD_REG_BIT (elim_reg_set, eliminables[i].from);
-#else
- SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
-#endif
initialized = true;
}
/* Verify that NEW_REC and OLD_REC have exactly the same members. */
static bool
-df_mws_verify (const vec<df_mw_hardreg_ptr, va_heap> *new_rec,
+df_mws_verify (const vec<df_mw_hardreg *, va_heap> *new_rec,
struct df_mw_hardreg *old_rec,
bool abort_if_fail)
{
rtx_insn *insn,
bool abort_if_fail)
{
- bool ret1, ret2, ret3, ret4;
+ bool ret1, ret2, ret3;
unsigned int uid = INSN_UID (insn);
struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
df_insn_refs_collect (collection_rec, bb, insn_info);
/* Unfortunately we cannot opt out early if one of these is not
- right because the marks will not get cleared. */
+ right and abort_if_fail is set because the marks will not get cleared. */
ret1 = df_refs_verify (&collection_rec->def_vec, DF_INSN_UID_DEFS (uid),
abort_if_fail);
+ if (!ret1 && !abort_if_fail)
+ return false;
ret2 = df_refs_verify (&collection_rec->use_vec, DF_INSN_UID_USES (uid),
abort_if_fail);
+ if (!ret2 && !abort_if_fail)
+ return false;
ret3 = df_refs_verify (&collection_rec->eq_use_vec, DF_INSN_UID_EQ_USES (uid),
abort_if_fail);
- ret4 = df_mws_verify (&collection_rec->mw_vec, DF_INSN_UID_MWS (uid),
- abort_if_fail);
- return (ret1 && ret2 && ret3 && ret4);
+ if (!ret3 && !abort_if_fail)
+ return false;
+ if (! df_mws_verify (&collection_rec->mw_vec, DF_INSN_UID_MWS (uid),
+ abort_if_fail))
+ return false;
+ return (ret1 && ret2 && ret3);
}
static bool
df_entry_block_bitmap_verify (bool abort_if_fail)
{
- bitmap_head entry_block_defs;
bool is_eq;
- bitmap_initialize (&entry_block_defs, &df_bitmap_obstack);
- df_get_entry_block_def_set (&entry_block_defs);
+ auto_bitmap entry_block_defs (&df_bitmap_obstack);
+ df_get_entry_block_def_set (entry_block_defs);
- is_eq = bitmap_equal_p (&entry_block_defs, df->entry_block_defs);
+ is_eq = bitmap_equal_p (entry_block_defs, df->entry_block_defs);
if (!is_eq && abort_if_fail)
{
fprintf (stderr, "entry_block_defs = ");
- df_print_regset (stderr, &entry_block_defs);
+ df_print_regset (stderr, entry_block_defs);
fprintf (stderr, "df->entry_block_defs = ");
df_print_regset (stderr, df->entry_block_defs);
gcc_assert (0);
}
- bitmap_clear (&entry_block_defs);
-
return is_eq;
}
static bool
df_exit_block_bitmap_verify (bool abort_if_fail)
{
- bitmap_head exit_block_uses;
bool is_eq;
- bitmap_initialize (&exit_block_uses, &df_bitmap_obstack);
- df_get_exit_block_use_set (&exit_block_uses);
+ auto_bitmap exit_block_uses (&df_bitmap_obstack);
+ df_get_exit_block_use_set (exit_block_uses);
- is_eq = bitmap_equal_p (&exit_block_uses, df->exit_block_uses);
+ is_eq = bitmap_equal_p (exit_block_uses, df->exit_block_uses);
if (!is_eq && abort_if_fail)
{
fprintf (stderr, "exit_block_uses = ");
- df_print_regset (stderr, &exit_block_uses);
+ df_print_regset (stderr, exit_block_uses);
fprintf (stderr, "df->exit_block_uses = ");
df_print_regset (stderr, df->exit_block_uses);
gcc_assert (0);
}
- bitmap_clear (&exit_block_uses);
-
return is_eq;
}
{
unsigned int i;
basic_block bb;
- bitmap_head regular_block_artificial_uses;
- bitmap_head eh_block_artificial_uses;
if (!df)
return;
/* (2) There are various bitmaps whose value may change over the
course of the compilation. This step recomputes them to make
sure that they have not slipped out of date. */
- bitmap_initialize (®ular_block_artificial_uses, &df_bitmap_obstack);
- bitmap_initialize (&eh_block_artificial_uses, &df_bitmap_obstack);
+ auto_bitmap regular_block_artificial_uses (&df_bitmap_obstack);
+ auto_bitmap eh_block_artificial_uses (&df_bitmap_obstack);
- df_get_regular_block_artificial_uses (®ular_block_artificial_uses);
- df_get_eh_block_artificial_uses (&eh_block_artificial_uses);
+ df_get_regular_block_artificial_uses (regular_block_artificial_uses);
+ df_get_eh_block_artificial_uses (eh_block_artificial_uses);
- bitmap_ior_into (&eh_block_artificial_uses,
- ®ular_block_artificial_uses);
+ bitmap_ior_into (eh_block_artificial_uses,
+ regular_block_artificial_uses);
/* Check artificial_uses bitmaps didn't change. */
- gcc_assert (bitmap_equal_p (®ular_block_artificial_uses,
+ gcc_assert (bitmap_equal_p (regular_block_artificial_uses,
&df->regular_block_artificial_uses));
- gcc_assert (bitmap_equal_p (&eh_block_artificial_uses,
+ gcc_assert (bitmap_equal_p (eh_block_artificial_uses,
&df->eh_block_artificial_uses));
- bitmap_clear (®ular_block_artificial_uses);
- bitmap_clear (&eh_block_artificial_uses);
-
/* Verify entry block and exit block. These only verify the bitmaps,
the refs are verified in df_bb_verify. */
df_entry_block_bitmap_verify (true);