#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "hash-table.h"
#include "tm.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 "tree.h"
#include "fold-const.h"
#include "gimple-pretty-print.h"
#include "tree-ssa-alias.h"
#include "internal-fn.h"
#include "gimple-expr.h"
-#include "is-a.h"
#include "gimple.h"
#include "gimple-iterator.h"
#include "gimple-ssa.h"
#include "ssa-iterators.h"
#include "stringpool.h"
#include "tree-ssanames.h"
-#include "hashtab.h"
#include "rtl.h"
#include "flags.h"
-#include "statistics.h"
-#include "real.h"
-#include "fixed-value.h"
#include "insn-config.h"
#include "expmed.h"
#include "dojump.h"
#include "diagnostic-core.h"
#include "debug.h"
#include "tree-ssa.h"
+#include "lto-streamer.h"
+#include "cgraph.h"
+#include "ipa-utils.h"
#ifdef ENABLE_CHECKING
static void verify_live_on_entry (tree_live_info_p);
/* Hashtable helpers. */
-struct tree_int_map_hasher : typed_noop_remove <tree_int_map>
+struct tree_int_map_hasher : nofree_ptr_hash <tree_int_map>
{
- typedef tree_int_map value_type;
- typedef tree_int_map compare_type;
- static inline hashval_t hash (const value_type *);
- static inline bool equal (const value_type *, const compare_type *);
+ static inline hashval_t hash (const tree_int_map *);
+ static inline bool equal (const tree_int_map *, const tree_int_map *);
};
inline hashval_t
-tree_int_map_hasher::hash (const value_type *v)
+tree_int_map_hasher::hash (const tree_int_map *v)
{
return tree_map_base_hash (v);
}
inline bool
-tree_int_map_hasher::equal (const value_type *v, const compare_type *c)
+tree_int_map_hasher::equal (const tree_int_map *v, const tree_int_map *c)
{
return tree_int_map_eq (v, c);
}
done by the inliner. */
static bool
-remove_unused_scope_block_p (tree scope)
+remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block)
{
tree *t, *next;
bool unused = !TREE_USED (scope);
int nsubblocks = 0;
+ /* For ipa-polymorphic-call.c purposes, preserve blocks:
+ 1) with BLOCK_ABSTRACT_ORIGIN of a ctor/dtor or their clones */
+ if (inlined_polymorphic_ctor_dtor_block_p (scope, true))
+ {
+ in_ctor_dtor_block = true;
+ unused = false;
+ }
+ /* 2) inside such blocks, the outermost block with BLOCK_ABSTRACT_ORIGIN
+ being a FUNCTION_DECL. */
+ else if (in_ctor_dtor_block
+ && BLOCK_ABSTRACT_ORIGIN (scope)
+ && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (scope)) == FUNCTION_DECL)
+ {
+ in_ctor_dtor_block = false;
+ unused = false;
+ }
+
for (t = &BLOCK_VARS (scope); *t; t = next)
{
next = &DECL_CHAIN (*t);
}
for (t = &BLOCK_SUBBLOCKS (scope); *t ;)
- if (remove_unused_scope_block_p (*t))
+ if (remove_unused_scope_block_p (*t, in_ctor_dtor_block))
{
if (BLOCK_SUBBLOCKS (*t))
{
cfun->local_decls->truncate (dstidx);
}
- remove_unused_scope_block_p (DECL_INITIAL (current_function_decl));
+ remove_unused_scope_block_p (DECL_INITIAL (current_function_decl), false);
clear_unused_block_pointer ();
BITMAP_FREE (usedvars);
timevar_pop (TV_REMOVE_UNUSED);
}
-/* Obstack for globale liveness info bitmaps. We don't want to put these
- on the default obstack because these bitmaps can grow quite large and
- we'll hold on to all that memory until the end of the compiler run.
- As a bonus, delete_tree_live_info can destroy all the bitmaps by just
- releasing the whole obstack. */
-static bitmap_obstack liveness_bitmap_obstack;
-
/* Allocate and return a new live range information object base on MAP. */
static tree_live_info_p
live->map = map;
live->num_blocks = last_basic_block_for_fn (cfun);
+ bitmap_obstack_initialize (&live->livein_obstack);
+ bitmap_obstack_initialize (&live->liveout_obstack);
live->livein = XNEWVEC (bitmap_head, last_basic_block_for_fn (cfun));
FOR_EACH_BB_FN (bb, cfun)
- bitmap_initialize (&live->livein[bb->index], &liveness_bitmap_obstack);
+ bitmap_initialize (&live->livein[bb->index], &live->livein_obstack);
live->liveout = XNEWVEC (bitmap_head, last_basic_block_for_fn (cfun));
FOR_EACH_BB_FN (bb, cfun)
- bitmap_initialize (&live->liveout[bb->index], &liveness_bitmap_obstack);
+ bitmap_initialize (&live->liveout[bb->index], &live->liveout_obstack);
live->work_stack = XNEWVEC (int, last_basic_block_for_fn (cfun));
live->stack_top = live->work_stack;
- live->global = BITMAP_ALLOC (&liveness_bitmap_obstack);
+ live->global = BITMAP_ALLOC (NULL);
return live;
}
void
delete_tree_live_info (tree_live_info_p live)
{
- bitmap_obstack_release (&liveness_bitmap_obstack);
+ if (live->livein)
+ {
+ bitmap_obstack_release (&live->livein_obstack);
+ free (live->livein);
+ }
+ if (live->liveout)
+ {
+ bitmap_obstack_release (&live->liveout_obstack);
+ free (live->liveout);
+ }
+ BITMAP_FREE (live->global);
free (live->work_stack);
- free (live->liveout);
- free (live->livein);
free (live);
}
it each time. */
static void
-loe_visit_block (tree_live_info_p live, basic_block bb, sbitmap visited,
- bitmap tmp)
+loe_visit_block (tree_live_info_p live, basic_block bb, sbitmap visited)
{
edge e;
bool change;
pred_bb = e->src;
if (pred_bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
continue;
- /* TMP is variables live-on-entry from BB that aren't defined in the
+ /* Variables live-on-entry from BB that aren't defined in the
predecessor block. This should be the live on entry vars to pred.
Note that liveout is the DEFs in a block while live on entry is
- being calculated. */
- bitmap_and_compl (tmp, loe, &live->liveout[pred_bb->index]);
-
- /* Add these bits to live-on-entry for the pred. if there are any
+ being calculated.
+ Add these bits to live-on-entry for the pred. if there are any
changes, and pred_bb has been visited already, add it to the
revisit stack. */
- change = bitmap_ior_into (live_on_entry (live, pred_bb), tmp);
- if (bitmap_bit_p (visited, pred_bb->index) && change)
+ change = bitmap_ior_and_compl_into (live_on_entry (live, pred_bb),
+ loe, &live->liveout[pred_bb->index]);
+ if (change
+ && bitmap_bit_p (visited, pred_bb->index))
{
bitmap_clear_bit (visited, pred_bb->index);
*(live->stack_top)++ = pred_bb->index;
unsigned b;
basic_block bb;
sbitmap visited = sbitmap_alloc (last_basic_block_for_fn (cfun) + 1);
- bitmap tmp = BITMAP_ALLOC (&liveness_bitmap_obstack);
bitmap_clear (visited);
/* Visit all the blocks in reverse order and propagate live on entry values
into the predecessors blocks. */
FOR_EACH_BB_REVERSE_FN (bb, cfun)
- loe_visit_block (live, bb, visited, tmp);
+ loe_visit_block (live, bb, visited);
/* Process any blocks which require further iteration. */
while (live->stack_top != live->work_stack)
{
b = *--(live->stack_top);
- loe_visit_block (live, BASIC_BLOCK_FOR_FN (cfun, b), visited, tmp);
+ loe_visit_block (live, BASIC_BLOCK_FOR_FN (cfun, b), visited);
}
- BITMAP_FREE (tmp);
sbitmap_free (visited);
}
/* Calculate the live on exit vectors based on the entry info in LIVEINFO. */
-void
+static void
calculate_live_on_exit (tree_live_info_p liveinfo)
{
basic_block bb;
each partition. Return a new live info object. */
tree_live_info_p
-calculate_live_ranges (var_map map)
+calculate_live_ranges (var_map map, bool want_livein)
{
tree var;
unsigned i;
tree_live_info_p live;
- bitmap_obstack_initialize (&liveness_bitmap_obstack);
live = new_tree_live_info (map);
for (i = 0; i < num_var_partitions (map); i++)
{
#endif
calculate_live_on_exit (live);
+
+ if (!want_livein)
+ {
+ bitmap_obstack_release (&live->livein_obstack);
+ free (live->livein);
+ live->livein = NULL;
+ }
+
return live;
}