+2015-10-27 Richard Biener <rguenther@suse.de>
+
+ * cfg.c (free_edge): Add function argument and use it instead of cfun.
+ (clear_edges): Likewise.
+ * cfg.h (clear_edges): Adjust prototype.
+ * cfgexpand.c (pass_expand::execute): Adjust.
+ * cfgloop.c (release_recorded_exits): Add function argument and use
+ it instead of cfun.
+ * cfgloop.h (release_recorded_exits): Adjust prototype.
+ (loops_state_satisfies_p): Add overload with function argument.
+ (loops_state_set): Likewise.
+ (loops_state_clear): Likewise.
+ (struct loop_iterator): Add function argument to constructor
+ and iterator and use it instead of cfun.
+ (FOR_EACH_LOOP_FN): New macro.
+ (loop_optimizer_finalize): Add overload with function argument.
+ * loop-init.c (loop_optimizer_init): Adjust.
+ (fix_loop_structure): Likewise.
+ (loop_optimizer_finaliz): Add function argument and use it
+ instead of cfun.
+ * tree-cfg.c (delete_tree_cfg_annotations): Likewise.
+ * tree-cfg.h (delete_tree_cfg_annotations): Adjust prototype.
+ * cgraph.c (release_function_body): Do not push/pop cfun.
+ * final.c (rest_of_clean_state): Adjust.
+ * graphite.c (graphite_finalize): Likewise.
+ * tree-ssa-copy.c (fini_copy_prop): Likewise.
+ * tree-ssa-dce.c (perform_tree_ssa_dce): Likewise.
+ * tree-ssa-loop-ivcanon.c (canonicalize_induction_variables): Likewise.
+ (tree_unroll_loops_completely): Likewise.
+ (pass_complete_unrolli::execute): Likewise.
+ * tree-ssa-loop-niter.c (free_numbers_of_iterations_estimates):
+ Add function argument and use it instead of cfun.
+ * tree-ssa-loop-niter.h (free_numbers_of_iterations_estimates):
+ Adjust prototype.
+ * tree-ssa-loop.c (tree_ssa_loop_done): Adjust.
+ * tree-ssa.c (delete_tree_ssa): Add function argument and use it
+ instead of cfun.
+ * tree-ssa.h (delete_tree_ssa): Adjust prototype.
+ * tree-ssanames.c (fini_ssanames): Add function argument and use it
+ instead of cfun.
+ * tree-ssanames.c (fini_ssanames): Adjust prototype.
+ * tree-vrp.c (execute_vrp): Adjust.
+ * value-prof.c (free_histograms): Add function argument and use it
+ instead of cfun.
+ * value-prof.h (free_histograms): Adjust prototype.
+
2015-10-27 Thomas Schwinge <thomas@codesourcery.com>
* tree.h (OACC_PARALLEL_BODY, OACC_PARALLEL_CLAUSES)
without actually removing it from the pred/succ arrays. */
static void
-free_edge (edge e)
+free_edge (function *fn, edge e)
{
- n_edges_for_fn (cfun)--;
+ n_edges_for_fn (fn)--;
ggc_free (e);
}
/* Free the memory associated with the edge structures. */
void
-clear_edges (void)
+clear_edges (struct function *fn)
{
basic_block bb;
edge e;
edge_iterator ei;
- FOR_EACH_BB_FN (bb, cfun)
+ FOR_EACH_BB_FN (bb, fn)
{
FOR_EACH_EDGE (e, ei, bb->succs)
- free_edge (e);
+ free_edge (fn, e);
vec_safe_truncate (bb->succs, 0);
vec_safe_truncate (bb->preds, 0);
}
- FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
- free_edge (e);
- vec_safe_truncate (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds, 0);
- vec_safe_truncate (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs, 0);
+ FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (fn)->succs)
+ free_edge (fn, e);
+ vec_safe_truncate (EXIT_BLOCK_PTR_FOR_FN (fn)->preds, 0);
+ vec_safe_truncate (ENTRY_BLOCK_PTR_FOR_FN (fn)->succs, 0);
- gcc_assert (!n_edges_for_fn (cfun));
+ gcc_assert (!n_edges_for_fn (fn));
}
\f
/* Allocate memory for basic_block. */
disconnect_src (e);
disconnect_dest (e);
- free_edge (e);
+ free_edge (cfun, e);
}
/* Redirect an edge's successor from one block to another. */
};
-extern void init_flow (struct function *);
-extern void clear_edges (void);
+extern void init_flow (function *);
+extern void clear_edges (function *);
extern basic_block alloc_block (void);
extern void link_block (basic_block, basic_block);
extern void unlink_block (basic_block);
/* Free stuff we no longer need after GIMPLE optimizations. */
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
- delete_tree_cfg_annotations ();
+ delete_tree_cfg_annotations (fun);
timevar_push (TV_OUT_OF_SSA);
finish_out_of_ssa (&SA);
/* Expansion is used by optimization passes too, set maybe_hot_insn_p
conservatively to true until they are all profile aware. */
delete lab_rtx_for_bb;
- free_histograms ();
+ free_histograms (fun);
construct_exit_block ();
insn_locations_finalize ();
/* Releases lists of loop exits. */
void
-release_recorded_exits (void)
+release_recorded_exits (function *fn)
{
- gcc_assert (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS));
- current_loops->exits->empty ();
- current_loops->exits = NULL;
- loops_state_clear (LOOPS_HAVE_RECORDED_EXITS);
+ gcc_assert (loops_state_satisfies_p (fn, LOOPS_HAVE_RECORDED_EXITS));
+ loops_for_fn (fn)->exits->empty ();
+ loops_for_fn (fn)->exits = NULL;
+ loops_state_clear (fn, LOOPS_HAVE_RECORDED_EXITS);
}
/* Returns the list of the exit edges of a LOOP. */
int flow_loop_nodes_find (basic_block, struct loop *);
unsigned fix_loop_structure (bitmap changed_bbs);
bool mark_irreducible_loops (void);
-void release_recorded_exits (void);
+void release_recorded_exits (function *);
void record_loop_exits (void);
void rescan_loop_exit (edge, bool, bool);
/* Returns true if state of the loops satisfies all properties
described by FLAGS. */
+static inline bool
+loops_state_satisfies_p (function *fn, unsigned flags)
+{
+ return (loops_for_fn (fn)->state & flags) == flags;
+}
+
static inline bool
loops_state_satisfies_p (unsigned flags)
{
- return (current_loops->state & flags) == flags;
+ return loops_state_satisfies_p (cfun, flags);
}
/* Sets FLAGS to the loops state. */
+static inline void
+loops_state_set (function *fn, unsigned flags)
+{
+ loops_for_fn (fn)->state |= flags;
+}
+
static inline void
loops_state_set (unsigned flags)
{
- current_loops->state |= flags;
+ loops_state_set (cfun, flags);
}
/* Clears FLAGS from the loops state. */
+static inline void
+loops_state_clear (function *fn, unsigned flags)
+{
+ loops_for_fn (fn)->state &= ~flags;
+}
+
static inline void
loops_state_clear (unsigned flags)
{
if (!current_loops)
return;
- current_loops->state &= ~flags;
+ loops_state_clear (cfun, flags);
}
/* Loop iterators. */
struct loop_iterator
{
- loop_iterator (loop_p *loop, unsigned flags);
+ loop_iterator (function *fn, loop_p *loop, unsigned flags);
~loop_iterator ();
inline loop_p next ();
+ /* The function we are visiting. */
+ function *fn;
+
/* The list of loops to visit. */
vec<int> to_visit;
while (this->to_visit.iterate (this->idx, &anum))
{
this->idx++;
- loop_p loop = get_loop (cfun, anum);
+ loop_p loop = get_loop (fn, anum);
if (loop)
return loop;
}
}
inline
-loop_iterator::loop_iterator (loop_p *loop, unsigned flags)
+loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)
{
struct loop *aloop;
unsigned i;
int mn;
this->idx = 0;
- if (!current_loops)
+ this->fn = fn;
+ if (!loops_for_fn (fn))
{
this->to_visit.create (0);
*loop = NULL;
return;
}
- this->to_visit.create (number_of_loops (cfun));
+ this->to_visit.create (number_of_loops (fn));
mn = (flags & LI_INCLUDE_ROOT) ? 0 : 1;
if (flags & LI_ONLY_INNERMOST)
{
- for (i = 0; vec_safe_iterate (current_loops->larray, i, &aloop); i++)
+ for (i = 0; vec_safe_iterate (loops_for_fn (fn)->larray, i, &aloop); i++)
if (aloop != NULL
&& aloop->inner == NULL
&& aloop->num >= mn)
else if (flags & LI_FROM_INNERMOST)
{
/* Push the loops to LI->TO_VISIT in postorder. */
- for (aloop = current_loops->tree_root;
+ for (aloop = loops_for_fn (fn)->tree_root;
aloop->inner != NULL;
aloop = aloop->inner)
continue;
else
{
/* Push the loops to LI->TO_VISIT in preorder. */
- aloop = current_loops->tree_root;
+ aloop = loops_for_fn (fn)->tree_root;
while (1)
{
if (aloop->num >= mn)
}
#define FOR_EACH_LOOP(LOOP, FLAGS) \
- for (loop_iterator li(&(LOOP), FLAGS); \
+ for (loop_iterator li(cfun, &(LOOP), FLAGS); \
+ (LOOP); \
+ (LOOP) = li.next ())
+
+#define FOR_EACH_LOOP_FN(FN, LOOP, FLAGS) \
+ for (loop_iterator li(fn, &(LOOP), FLAGS); \
(LOOP); \
(LOOP) = li.next ())
/* Loop optimizer initialization. */
extern void loop_optimizer_init (unsigned);
-extern void loop_optimizer_finalize (void);
+extern void loop_optimizer_finalize (function *);
+inline void
+loop_optimizer_finalize ()
+{
+ loop_optimizer_finalize (cfun);
+}
/* Optimization passes. */
enum
void
release_function_body (tree decl)
{
- if (DECL_STRUCT_FUNCTION (decl))
+ function *fn = DECL_STRUCT_FUNCTION (decl);
+ if (fn)
{
- if (DECL_STRUCT_FUNCTION (decl)->cfg
- || DECL_STRUCT_FUNCTION (decl)->gimple_df)
+ if (fn->cfg
+ || fn->gimple_df)
{
- push_cfun (DECL_STRUCT_FUNCTION (decl));
- if (cfun->cfg
- && current_loops)
+ if (fn->cfg
+ && loops_for_fn (fn))
{
- cfun->curr_properties &= ~PROP_loops;
- loop_optimizer_finalize ();
+ fn->curr_properties &= ~PROP_loops;
+ loop_optimizer_finalize (fn);
}
- if (cfun->gimple_df)
+ if (fn->gimple_df)
{
- delete_tree_ssa ();
- delete_tree_cfg_annotations ();
- cfun->eh = NULL;
+ delete_tree_ssa (fn);
+ delete_tree_cfg_annotations (fn);
+ fn->eh = NULL;
}
- if (cfun->cfg)
+ if (fn->cfg)
{
- gcc_assert (!dom_info_available_p (CDI_DOMINATORS));
- gcc_assert (!dom_info_available_p (CDI_POST_DOMINATORS));
- clear_edges ();
- cfun->cfg = NULL;
+ gcc_assert (!dom_info_available_p (fn, CDI_DOMINATORS));
+ gcc_assert (!dom_info_available_p (fn, CDI_POST_DOMINATORS));
+ clear_edges (fn);
+ fn->cfg = NULL;
}
- if (cfun->value_histograms)
- free_histograms ();
- pop_cfun ();
+ if (fn->value_histograms)
+ free_histograms (fn);
}
gimple_set_body (decl, NULL);
/* Struct function hangs a lot of data that would leak if we didn't
removed all pointers to it. */
- ggc_free (DECL_STRUCT_FUNCTION (decl));
+ ggc_free (fn);
DECL_STRUCT_FUNCTION (decl) = NULL;
}
DECL_SAVED_TREE (decl) = NULL;
free_bb_for_insn ();
- delete_tree_ssa ();
+ delete_tree_ssa (cfun);
/* We can reduce stack alignment on call site only when we are sure that
the function body just produced will be actually used in the final
scev_reset ();
cleanup_tree_cfg ();
profile_status_for_fn (cfun) = PROFILE_ABSENT;
- release_recorded_exits ();
+ release_recorded_exits (cfun);
tree_estimate_probability ();
}
/* Clear all flags. */
if (recorded_exits)
- release_recorded_exits ();
+ release_recorded_exits (cfun);
loops_state_clear (~0U);
if (needs_fixup)
/* Finalize loop structures. */
void
-loop_optimizer_finalize (void)
+loop_optimizer_finalize (struct function *fn)
{
struct loop *loop;
basic_block bb;
timevar_push (TV_LOOP_FINI);
- if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS))
- release_recorded_exits ();
+ if (loops_state_satisfies_p (fn, LOOPS_HAVE_RECORDED_EXITS))
+ release_recorded_exits (fn);
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (fn);
/* If we should preserve loop structure, do not free it but clear
flags that advanced properties are there as we are not preserving
that in full. */
- if (cfun->curr_properties & PROP_loops)
+ if (fn->curr_properties & PROP_loops)
{
- loops_state_clear (LOOP_CLOSED_SSA
+ loops_state_clear (fn, LOOP_CLOSED_SSA
| LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS
| LOOPS_HAVE_PREHEADERS
| LOOPS_HAVE_SIMPLE_LATCHES
| LOOPS_HAVE_FALLTHRU_PREHEADERS);
- loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
+ loops_state_set (fn, LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
goto loop_fini_done;
}
- gcc_assert (current_loops != NULL);
-
- FOR_EACH_LOOP (loop, 0)
+ FOR_EACH_LOOP_FN (fn, loop, 0)
free_simple_loop_desc (loop);
/* Clean up. */
- flow_loops_free (current_loops);
- ggc_free (current_loops);
- current_loops = NULL;
+ flow_loops_free (loops_for_fn (fn));
+ ggc_free (loops_for_fn (fn));
+ set_loops_for_fn (fn, NULL);
- FOR_ALL_BB_FN (bb, cfun)
+ FOR_ALL_BB_FN (bb, fn)
{
bb->loop_father = NULL;
}
if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS))
{
- release_recorded_exits ();
+ release_recorded_exits (cfun);
record_exits = LOOPS_HAVE_RECORDED_EXITS;
}
/* Remove block annotations and other data structures. */
void
-delete_tree_cfg_annotations (void)
+delete_tree_cfg_annotations (struct function *fn)
{
- vec_free (label_to_block_map_for_fn (cfun));
+ vec_free (label_to_block_map_for_fn (fn));
}
/* Return the virtual phi in BB. */
extern bool simple_goto_p (gimple *);
extern bool stmt_ends_bb_p (gimple *);
extern bool assert_unreachable_fallthru_edge_p (edge);
-extern void delete_tree_cfg_annotations (void);
+extern void delete_tree_cfg_annotations (function *);
extern gphi *get_virtual_phi (basic_block);
extern gimple *first_stmt (basic_block);
extern gimple *last_stmt (basic_block);
bool changed = substitute_and_fold (get_value, NULL, true);
if (changed)
{
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (cfun);
if (scev_initialized_p ())
scev_reset ();
}
if (something_changed)
{
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (cfun);
if (scev_initialized_p ())
scev_reset ();
return TODO_update_ssa | TODO_cleanup_cfg;
bool irred_invalidated = false;
bitmap loop_closed_ssa_invalidated = BITMAP_ALLOC (NULL);
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (cfun);
estimate_numbers_of_iterations ();
FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
loop_closed_ssa_invalidated = BITMAP_ALLOC (NULL);
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (cfun);
estimate_numbers_of_iterations ();
changed = tree_unroll_loops_completely_1 (may_increase_size,
{
scev_initialize ();
ret = tree_unroll_loops_completely (optimize >= 3, false);
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (fun);
scev_finalize ();
}
loop_optimizer_finalize ();
/* Frees the information on upper bounds on numbers of iterations of loops. */
void
-free_numbers_of_iterations_estimates (void)
+free_numbers_of_iterations_estimates (function *fn)
{
struct loop *loop;
- FOR_EACH_LOOP (loop, 0)
+ FOR_EACH_LOOP_FN (fn, loop, 0)
{
free_numbers_of_iterations_estimates_loop (loop);
}
extern bool scev_probably_wraps_p (tree, tree, gimple *, struct loop *, bool);
extern void free_loop_control_ivs (struct loop *);
extern void free_numbers_of_iterations_estimates_loop (struct loop *);
-extern void free_numbers_of_iterations_estimates (void);
+extern void free_numbers_of_iterations_estimates (function *);
extern void substitute_in_loop_info (struct loop *, tree, tree);
#endif /* GCC_TREE_SSA_LOOP_NITER_H */
static unsigned int
tree_ssa_loop_done (void)
{
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (cfun);
scev_finalize ();
loop_optimizer_finalize ();
return 0;
/* Deallocate memory associated with SSA data structures for FNDECL. */
void
-delete_tree_ssa (void)
+delete_tree_ssa (struct function *fn)
{
- fini_ssanames ();
+ fini_ssanames (fn);
/* We no longer maintain the SSA operand cache at this point. */
- if (ssa_operands_active (cfun))
- fini_ssa_operands (cfun);
-
- cfun->gimple_df->default_defs->empty ();
- cfun->gimple_df->default_defs = NULL;
- pt_solution_reset (&cfun->gimple_df->escaped);
- if (cfun->gimple_df->decls_to_pointers != NULL)
- delete cfun->gimple_df->decls_to_pointers;
- cfun->gimple_df->decls_to_pointers = NULL;
- cfun->gimple_df->modified_noreturn_calls = NULL;
- cfun->gimple_df = NULL;
-
- /* We no longer need the edge variable maps. */
- redirect_edge_var_map_destroy ();
+ if (ssa_operands_active (fn))
+ fini_ssa_operands (fn);
+
+ fn->gimple_df->default_defs->empty ();
+ fn->gimple_df->default_defs = NULL;
+ pt_solution_reset (&fn->gimple_df->escaped);
+ if (fn->gimple_df->decls_to_pointers != NULL)
+ delete fn->gimple_df->decls_to_pointers;
+ fn->gimple_df->decls_to_pointers = NULL;
+ fn->gimple_df->modified_noreturn_calls = NULL;
+ fn->gimple_df = NULL;
}
/* Return true if EXPR is a useless type conversion, otherwise return
extern void reset_debug_uses (gimple *);
extern void release_defs_bitset (bitmap toremove);
extern void verify_ssa (bool, bool);
-extern void init_tree_ssa (struct function *);
-extern void delete_tree_ssa (void);
+extern void init_tree_ssa (function *);
+extern void delete_tree_ssa (function *);
extern bool tree_ssa_useless_type_conversion (tree);
extern tree tree_ssa_strip_useless_type_conversions (tree);
/* Finalize management of SSA_NAMEs. */
void
-fini_ssanames (void)
+fini_ssanames (struct function *fn)
{
- vec_free (SSANAMES (cfun));
- vec_free (FREE_SSANAMES (cfun));
- vec_free (FREE_SSANAMES_QUEUE (cfun));
+ vec_free (SSANAMES (fn));
+ vec_free (FREE_SSANAMES (fn));
+ vec_free (FREE_SSANAMES_QUEUE (fn));
}
/* Dump some simple statistics regarding the re-use of SSA_NAME nodes. */
extern void set_nonzero_bits (tree, const wide_int_ref &);
extern wide_int get_nonzero_bits (const_tree);
extern void init_ssanames (struct function *, int);
-extern void fini_ssanames (void);
+extern void fini_ssanames (struct function *);
extern void ssanames_print_statistics (void);
extern tree make_ssa_name_fn (struct function *, tree, gimple *);
extern void release_ssa_name_fn (struct function *, tree);
ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node);
vrp_finalize ();
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (cfun);
/* ASSERT_EXPRs must be removed before finalizing jump threads
as finalizing jump threads calls the CFG cleanup code which
}
void
-free_histograms (void)
+free_histograms (struct function *fn)
{
- if (VALUE_HISTOGRAMS (cfun))
+ if (VALUE_HISTOGRAMS (fn))
{
- htab_traverse (VALUE_HISTOGRAMS (cfun), free_hist, NULL);
- htab_delete (VALUE_HISTOGRAMS (cfun));
- VALUE_HISTOGRAMS (cfun) = NULL;
+ htab_traverse (VALUE_HISTOGRAMS (fn), free_hist, NULL);
+ htab_delete (VALUE_HISTOGRAMS (fn));
+ VALUE_HISTOGRAMS (fn) = NULL;
}
}
struct function *, gimple *);
void gimple_move_stmt_histograms (struct function *, gimple *, gimple *);
void verify_histograms (void);
-void free_histograms (void);
+void free_histograms (function *);
void stringop_block_profile (gimple *, unsigned int *, HOST_WIDE_INT *);
gcall *gimple_ic (gcall *, struct cgraph_node *, int, gcov_type,
gcov_type);