/* Scanning of rtl for dataflow analysis.
- Copyright (C) 1999-2015 Free Software Foundation, Inc.
+ Copyright (C) 1999-2016 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 "input.h"
-#include "alias.h"
-#include "symtab.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 "tm_p.h"
+#include "regs.h"
#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */
+#include "dumpfile.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 *,
it gets run. It also has no need for the iterative solver.
----------------------------------------------------------------------------*/
-#define SCAN_PROBLEM_DATA_BLOCK_SIZE 512
-
/* Problem data for the scanning dataflow function. */
struct df_scan_problem_data
{
- pool_allocator<df_base_ref> *ref_base_pool;
- pool_allocator<df_artificial_ref> *ref_artificial_pool;
- pool_allocator<df_regular_ref> *ref_regular_pool;
- pool_allocator<df_insn_info> *insn_pool;
- pool_allocator<df_reg_info> *reg_pool;
- pool_allocator<df_mw_hardreg> *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)
df_scan->problem_data = problem_data;
df_scan->computed = true;
- problem_data->ref_base_pool = new pool_allocator<df_base_ref>
- ("df_scan ref base", SCAN_PROBLEM_DATA_BLOCK_SIZE);
- problem_data->ref_artificial_pool = new pool_allocator<df_artificial_ref>
- ("df_scan ref artificial", SCAN_PROBLEM_DATA_BLOCK_SIZE);
- problem_data->ref_regular_pool = new pool_allocator<df_regular_ref>
- ("df_scan ref regular", SCAN_PROBLEM_DATA_BLOCK_SIZE);
- problem_data->insn_pool = new pool_allocator<df_insn_info>
- ("df_scan insn", SCAN_PROBLEM_DATA_BLOCK_SIZE);
- problem_data->reg_pool = new pool_allocator<df_reg_info>
- ("df_scan reg", SCAN_PROBLEM_DATA_BLOCK_SIZE);
- problem_data->mw_reg_pool = new pool_allocator<df_mw_hardreg>
- ("df_scan mw_reg", SCAN_PROBLEM_DATA_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);
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 = 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;
}
}
}
+/* 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);
-
+ df_insn_info_free_fields (insn_info);
problem_data->insn_pool->remove (insn_info);
DF_INSN_UID_SET (uid, NULL);
}
/* 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
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
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)
/* 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 (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);
/* 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)
{