add move CTOR to auto_vec, use auto_vec for get_loop_exit_edges
This adds a move CTOR to auto_vec<T, 0> and makes use of a auto_vec<edge> return value for get_loop_exit_edges denoting that lifetime management of the vector is handed to the caller. The move CTOR prompted the hash_table change because it appearantly makes the copy CTOR implicitely deleted (good) and hash-table expansion of the odr_enum_map which is hash_map <nofree_string_hash, odr_enum> where odr_enum has an auto_vec<odr_enum_val, 0> member triggers this. Not sure if there's a latent bug there before this (I think we're not invoking DTORs, but we're invoking copy-CTORs). 2020-08-06 Richard Biener <rguenther@suse.de> * vec.h (auto_vec<T, 0>::auto_vec (auto_vec &&)): New move CTOR. (auto_vec<T, 0>::operator=(auto_vec &&)): Delete. * hash-table.h (hash_table::expand): Use std::move when expanding. * cfgloop.h (get_loop_exit_edges): Return auto_vec<edge>. * cfgloop.c (get_loop_exit_edges): Adjust. * cfgloopmanip.c (fix_loop_placement): Likewise. * ipa-fnsummary.c (analyze_function_body): Likewise. * ira-build.c (create_loop_tree_nodes): Likewise. (create_loop_tree_node_allocnos): Likewise. (loop_with_complex_edge_p): Likewise. * ira-color.c (ira_loop_edge_freq): Likewise. * loop-unroll.c (analyze_insns_in_loop): Likewise. * predict.c (predict_loops): Likewise. * tree-predcom.c (last_always_executed_block): Likewise. * tree-ssa-loop-ch.c (ch_base::copy_headers): Likewise. * tree-ssa-loop-im.c (store_motion_loop): Likewise. * tree-ssa-loop-ivcanon.c (loop_edge_to_cancel): Likewise. (canonicalize_loop_induction_variables): Likewise. * tree-ssa-loop-manip.c (get_loops_exits): Likewise. * tree-ssa-loop-niter.c (find_loop_niter): Likewise. (finite_loop_p): Likewise. (find_loop_niter_by_eval): Likewise. (estimate_numbers_of_iterations): Likewise. * tree-ssa-loop-prefetch.c (emit_mfence_after_loop): Likewise. (may_use_storent_in_loop_p): Likewise.
This commit is contained in:
parent
2e66e53b1e
commit
4b9d61f79c
17 changed files with 33 additions and 65 deletions
|
@ -1202,10 +1202,10 @@ release_recorded_exits (function *fn)
|
|||
|
||||
/* Returns the list of the exit edges of a LOOP. */
|
||||
|
||||
vec<edge>
|
||||
auto_vec<edge>
|
||||
get_loop_exit_edges (const class loop *loop, basic_block *body)
|
||||
{
|
||||
vec<edge> edges = vNULL;
|
||||
auto_vec<edge> edges;
|
||||
edge e;
|
||||
unsigned i;
|
||||
edge_iterator ei;
|
||||
|
|
|
@ -383,7 +383,7 @@ extern basic_block *get_loop_body_in_custom_order (const class loop *,
|
|||
extern basic_block *get_loop_body_in_custom_order (const class loop *, void *,
|
||||
int (*) (const void *, const void *, void *));
|
||||
|
||||
extern vec<edge> get_loop_exit_edges (const class loop *, basic_block * = NULL);
|
||||
extern auto_vec<edge> get_loop_exit_edges (const class loop *, basic_block * = NULL);
|
||||
extern edge single_exit (const class loop *);
|
||||
extern edge single_likely_exit (class loop *loop, vec<edge>);
|
||||
extern unsigned num_loop_branches (const class loop *);
|
||||
|
|
|
@ -126,7 +126,7 @@ fix_loop_placement (class loop *loop, bool *irred_invalidated)
|
|||
{
|
||||
unsigned i;
|
||||
edge e;
|
||||
vec<edge> exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
class loop *father = current_loops->tree_root, *act;
|
||||
bool ret = false;
|
||||
|
||||
|
@ -157,7 +157,6 @@ fix_loop_placement (class loop *loop, bool *irred_invalidated)
|
|||
ret = true;
|
||||
}
|
||||
|
||||
exits.release ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -819,7 +819,7 @@ hash_table<Descriptor, Lazy, Allocator>::expand ()
|
|||
if (!is_empty (x) && !is_deleted (x))
|
||||
{
|
||||
value_type *q = find_empty_slot_for_expand (Descriptor::hash (x));
|
||||
new ((void*) q) value_type (x);
|
||||
new ((void*) q) value_type (std::move (x));
|
||||
}
|
||||
|
||||
p++;
|
||||
|
|
|
@ -2808,7 +2808,6 @@ analyze_function_body (struct cgraph_node *node, bool early)
|
|||
scev_initialize ();
|
||||
FOR_EACH_LOOP (loop, 0)
|
||||
{
|
||||
vec<edge> exits;
|
||||
edge ex;
|
||||
unsigned int j;
|
||||
class tree_niter_desc niter_desc;
|
||||
|
@ -2817,7 +2816,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
|
|||
else
|
||||
bb_predicate = false;
|
||||
|
||||
exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
FOR_EACH_VEC_ELT (exits, j, ex)
|
||||
if (number_of_iterations_exit (loop, ex, &niter_desc, false)
|
||||
&& !is_gimple_min_invariant (niter_desc.niter))
|
||||
|
@ -2835,7 +2834,6 @@ analyze_function_body (struct cgraph_node *node, bool early)
|
|||
loop with independent predicate. */
|
||||
loop_iterations &= will_be_nonconstant;
|
||||
}
|
||||
exits.release ();
|
||||
}
|
||||
|
||||
/* To avoid quadratic behavior we analyze stride predicates only
|
||||
|
|
|
@ -128,7 +128,6 @@ create_loop_tree_nodes (void)
|
|||
bool skip_p;
|
||||
edge_iterator ei;
|
||||
edge e;
|
||||
vec<edge> edges;
|
||||
loop_p loop;
|
||||
|
||||
ira_bb_nodes
|
||||
|
@ -173,14 +172,13 @@ create_loop_tree_nodes (void)
|
|||
}
|
||||
if (skip_p)
|
||||
continue;
|
||||
edges = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> edges = get_loop_exit_edges (loop);
|
||||
FOR_EACH_VEC_ELT (edges, j, e)
|
||||
if ((e->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (e))
|
||||
{
|
||||
skip_p = true;
|
||||
break;
|
||||
}
|
||||
edges.release ();
|
||||
if (skip_p)
|
||||
continue;
|
||||
}
|
||||
|
@ -1964,17 +1962,15 @@ create_loop_tree_node_allocnos (ira_loop_tree_node_t loop_node)
|
|||
int i;
|
||||
edge_iterator ei;
|
||||
edge e;
|
||||
vec<edge> edges;
|
||||
|
||||
ira_assert (current_loops != NULL);
|
||||
FOR_EACH_EDGE (e, ei, loop_node->loop->header->preds)
|
||||
if (e->src != loop_node->loop->latch)
|
||||
create_loop_allocnos (e);
|
||||
|
||||
edges = get_loop_exit_edges (loop_node->loop);
|
||||
auto_vec<edge> edges = get_loop_exit_edges (loop_node->loop);
|
||||
FOR_EACH_VEC_ELT (edges, i, e)
|
||||
create_loop_allocnos (e);
|
||||
edges.release ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2167,13 +2163,12 @@ loop_with_complex_edge_p (class loop *loop)
|
|||
int i;
|
||||
edge_iterator ei;
|
||||
edge e;
|
||||
vec<edge> edges;
|
||||
bool res;
|
||||
|
||||
FOR_EACH_EDGE (e, ei, loop->header->preds)
|
||||
if (e->flags & EDGE_EH)
|
||||
return true;
|
||||
edges = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> edges = get_loop_exit_edges (loop);
|
||||
res = false;
|
||||
FOR_EACH_VEC_ELT (edges, i, e)
|
||||
if (e->flags & EDGE_COMPLEX)
|
||||
|
@ -2181,7 +2176,6 @@ loop_with_complex_edge_p (class loop *loop)
|
|||
res = true;
|
||||
break;
|
||||
}
|
||||
edges.release ();
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2539,7 +2539,6 @@ ira_loop_edge_freq (ira_loop_tree_node_t loop_node, int regno, bool exit_p)
|
|||
int freq, i;
|
||||
edge_iterator ei;
|
||||
edge e;
|
||||
vec<edge> edges;
|
||||
|
||||
ira_assert (current_loops != NULL && loop_node->loop != NULL
|
||||
&& (regno < 0 || regno >= FIRST_PSEUDO_REGISTER));
|
||||
|
@ -2555,13 +2554,12 @@ ira_loop_edge_freq (ira_loop_tree_node_t loop_node, int regno, bool exit_p)
|
|||
}
|
||||
else
|
||||
{
|
||||
edges = get_loop_exit_edges (loop_node->loop);
|
||||
auto_vec<edge> edges = get_loop_exit_edges (loop_node->loop);
|
||||
FOR_EACH_VEC_ELT (edges, i, e)
|
||||
if (regno < 0
|
||||
|| (bitmap_bit_p (df_get_live_out (e->src), regno)
|
||||
&& bitmap_bit_p (df_get_live_in (e->dest), regno)))
|
||||
freq += EDGE_FREQUENCY (e);
|
||||
edges.release ();
|
||||
}
|
||||
|
||||
return REG_FREQ_FROM_EDGE_FREQ (freq);
|
||||
|
|
|
@ -1580,7 +1580,7 @@ analyze_insns_in_loop (class loop *loop)
|
|||
struct var_to_expand *ves = NULL;
|
||||
iv_to_split **slot1;
|
||||
var_to_expand **slot2;
|
||||
vec<edge> edges = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> edges = get_loop_exit_edges (loop);
|
||||
edge exit;
|
||||
bool can_apply = false;
|
||||
|
||||
|
@ -1656,7 +1656,6 @@ analyze_insns_in_loop (class loop *loop)
|
|||
}
|
||||
}
|
||||
|
||||
edges.release ();
|
||||
free (body);
|
||||
return opt_info;
|
||||
}
|
||||
|
|
|
@ -1916,7 +1916,6 @@ predict_loops (void)
|
|||
{
|
||||
basic_block bb, *bbs;
|
||||
unsigned j, n_exits = 0;
|
||||
vec<edge> exits;
|
||||
class tree_niter_desc niter_desc;
|
||||
edge ex;
|
||||
class nb_iter_bound *nb_iter;
|
||||
|
@ -1927,15 +1926,12 @@ predict_loops (void)
|
|||
gcond *stmt = NULL;
|
||||
bool recursion = with_recursion.contains (loop);
|
||||
|
||||
exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
FOR_EACH_VEC_ELT (exits, j, ex)
|
||||
if (!unlikely_executed_edge_p (ex) && !(ex->flags & EDGE_ABNORMAL_CALL))
|
||||
n_exits ++;
|
||||
if (!n_exits)
|
||||
{
|
||||
exits.release ();
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
fprintf (dump_file, "Predicting loop %i%s with %i exits.\n",
|
||||
|
@ -2049,7 +2045,6 @@ predict_loops (void)
|
|||
probability = RDIV (REG_BR_PROB_BASE, nitercst);
|
||||
predict_edge (ex, predictor, probability);
|
||||
}
|
||||
exits.release ();
|
||||
|
||||
/* Find information about loop bound variables. */
|
||||
for (nb_iter = loop->bounds; nb_iter;
|
||||
|
|
|
@ -737,13 +737,12 @@ static basic_block
|
|||
last_always_executed_block (class loop *loop)
|
||||
{
|
||||
unsigned i;
|
||||
vec<edge> exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
edge ex;
|
||||
basic_block last = loop->latch;
|
||||
|
||||
FOR_EACH_VEC_ELT (exits, i, ex)
|
||||
last = nearest_common_dominator (CDI_DOMINATORS, last, ex->src);
|
||||
exits.release ();
|
||||
|
||||
return last;
|
||||
}
|
||||
|
|
|
@ -504,14 +504,13 @@ ch_base::copy_headers (function *fun)
|
|||
{
|
||||
edge entry = copied[i].first;
|
||||
loop_p loop = copied[i].second;
|
||||
vec<edge> exit_edges = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exit_edges = get_loop_exit_edges (loop);
|
||||
bitmap exit_bbs = BITMAP_ALLOC (NULL);
|
||||
for (unsigned j = 0; j < exit_edges.length (); ++j)
|
||||
bitmap_set_bit (exit_bbs, exit_edges[j]->dest->index);
|
||||
bitmap_set_bit (exit_bbs, loop->header->index);
|
||||
do_rpo_vn (cfun, entry, exit_bbs);
|
||||
BITMAP_FREE (exit_bbs);
|
||||
exit_edges.release ();
|
||||
}
|
||||
}
|
||||
free (bbs);
|
||||
|
|
|
@ -2868,7 +2868,7 @@ loop_suitable_for_sm (class loop *loop ATTRIBUTE_UNUSED,
|
|||
static void
|
||||
store_motion_loop (class loop *loop, bitmap sm_executed)
|
||||
{
|
||||
vec<edge> exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
class loop *subloop;
|
||||
bitmap sm_in_loop = BITMAP_ALLOC (&lim_bitmap_obstack);
|
||||
|
||||
|
@ -2878,7 +2878,6 @@ store_motion_loop (class loop *loop, bitmap sm_executed)
|
|||
if (!bitmap_empty_p (sm_in_loop))
|
||||
hoist_memory_references (loop, sm_in_loop, exits);
|
||||
}
|
||||
exits.release ();
|
||||
|
||||
bitmap_ior_into (sm_executed, sm_in_loop);
|
||||
for (subloop = loop->inner; subloop != NULL; subloop = subloop->next)
|
||||
|
|
|
@ -444,7 +444,6 @@ estimated_unrolled_size (struct loop_size *size,
|
|||
static edge
|
||||
loop_edge_to_cancel (class loop *loop)
|
||||
{
|
||||
vec<edge> exits;
|
||||
unsigned i;
|
||||
edge edge_to_cancel;
|
||||
gimple_stmt_iterator gsi;
|
||||
|
@ -453,7 +452,7 @@ loop_edge_to_cancel (class loop *loop)
|
|||
if (EDGE_COUNT (loop->latch->preds) > 1)
|
||||
return NULL;
|
||||
|
||||
exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
|
||||
FOR_EACH_VEC_ELT (exits, i, edge_to_cancel)
|
||||
{
|
||||
|
@ -477,8 +476,6 @@ loop_edge_to_cancel (class loop *loop)
|
|||
if (edge_to_cancel->dest != loop->latch)
|
||||
continue;
|
||||
|
||||
exits.release ();
|
||||
|
||||
/* Verify that the code in loop latch does nothing that may end program
|
||||
execution without really reaching the exit. This may include
|
||||
non-pure/const function calls, EH statements, volatile ASMs etc. */
|
||||
|
@ -487,7 +484,6 @@ loop_edge_to_cancel (class loop *loop)
|
|||
return NULL;
|
||||
return edge_to_cancel;
|
||||
}
|
||||
exits.release ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1222,10 +1218,9 @@ canonicalize_loop_induction_variables (class loop *loop,
|
|||
by find_loop_niter_by_eval. Be sure to keep it for future. */
|
||||
if (niter && TREE_CODE (niter) == INTEGER_CST)
|
||||
{
|
||||
vec<edge> exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
record_niter_bound (loop, wi::to_widest (niter),
|
||||
exit == single_likely_exit (loop, exits), true);
|
||||
exits.release ();
|
||||
}
|
||||
|
||||
/* Force re-computation of loop bounds so we can remove redundant exits. */
|
||||
|
|
|
@ -368,11 +368,10 @@ get_loops_exits (bitmap *loop_exits)
|
|||
|
||||
FOR_EACH_LOOP (loop, 0)
|
||||
{
|
||||
vec<edge> exit_edges = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exit_edges = get_loop_exit_edges (loop);
|
||||
loop_exits[loop->num] = BITMAP_ALLOC (&loop_renamer_obstack);
|
||||
FOR_EACH_VEC_ELT (exit_edges, j, e)
|
||||
bitmap_set_bit (loop_exits[loop->num], e->dest->index);
|
||||
exit_edges.release ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2752,7 +2752,7 @@ tree
|
|||
find_loop_niter (class loop *loop, edge *exit)
|
||||
{
|
||||
unsigned i;
|
||||
vec<edge> exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
edge ex;
|
||||
tree niter = NULL_TREE, aniter;
|
||||
class tree_niter_desc desc;
|
||||
|
@ -2803,7 +2803,6 @@ find_loop_niter (class loop *loop, edge *exit)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
exits.release ();
|
||||
|
||||
return niter ? niter : chrec_dont_know;
|
||||
}
|
||||
|
@ -2837,21 +2836,18 @@ finite_loop_p (class loop *loop)
|
|||
if (loop->finite_p)
|
||||
{
|
||||
unsigned i;
|
||||
vec<edge> exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
edge ex;
|
||||
|
||||
/* If the loop has a normal exit, we can assume it will terminate. */
|
||||
FOR_EACH_VEC_ELT (exits, i, ex)
|
||||
if (!(ex->flags & (EDGE_EH | EDGE_ABNORMAL | EDGE_FAKE)))
|
||||
{
|
||||
exits.release ();
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Assume loop %i to be finite: it has an exit "
|
||||
"and -ffinite-loops is on.\n", loop->num);
|
||||
return true;
|
||||
}
|
||||
|
||||
exits.release ();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -3114,7 +3110,7 @@ tree
|
|||
find_loop_niter_by_eval (class loop *loop, edge *exit)
|
||||
{
|
||||
unsigned i;
|
||||
vec<edge> exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
edge ex;
|
||||
tree niter = NULL_TREE, aniter;
|
||||
|
||||
|
@ -3123,10 +3119,7 @@ find_loop_niter_by_eval (class loop *loop, edge *exit)
|
|||
/* Loops with multiple exits are expensive to handle and less important. */
|
||||
if (!flag_expensive_optimizations
|
||||
&& exits.length () > 1)
|
||||
{
|
||||
exits.release ();
|
||||
return chrec_dont_know;
|
||||
}
|
||||
return chrec_dont_know;
|
||||
|
||||
FOR_EACH_VEC_ELT (exits, i, ex)
|
||||
{
|
||||
|
@ -3144,7 +3137,6 @@ find_loop_niter_by_eval (class loop *loop, edge *exit)
|
|||
niter = aniter;
|
||||
*exit = ex;
|
||||
}
|
||||
exits.release ();
|
||||
|
||||
return niter ? niter : chrec_dont_know;
|
||||
}
|
||||
|
@ -4236,7 +4228,6 @@ get_upper_bound_based_on_builtin_expr_with_prob (gcond *cond)
|
|||
void
|
||||
estimate_numbers_of_iterations (class loop *loop)
|
||||
{
|
||||
vec<edge> exits;
|
||||
tree niter, type;
|
||||
unsigned i;
|
||||
class tree_niter_desc niter_desc;
|
||||
|
@ -4275,7 +4266,7 @@ estimate_numbers_of_iterations (class loop *loop)
|
|||
number_of_latch_executions (loop);
|
||||
|
||||
basic_block *body = get_loop_body (loop);
|
||||
exits = get_loop_exit_edges (loop, body);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop, body);
|
||||
likely_exit = single_likely_exit (loop, exits);
|
||||
FOR_EACH_VEC_ELT (exits, i, ex)
|
||||
{
|
||||
|
@ -4311,7 +4302,6 @@ estimate_numbers_of_iterations (class loop *loop)
|
|||
true, ex == likely_exit, true);
|
||||
record_control_iv (loop, &niter_desc);
|
||||
}
|
||||
exits.release ();
|
||||
|
||||
if (flag_aggressive_loop_optimizations)
|
||||
infer_loop_bounds_from_undefined (loop, body);
|
||||
|
|
|
@ -1289,7 +1289,7 @@ mark_nontemporal_store (struct mem_ref *ref)
|
|||
static void
|
||||
emit_mfence_after_loop (class loop *loop)
|
||||
{
|
||||
vec<edge> exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
edge exit;
|
||||
gcall *call;
|
||||
gimple_stmt_iterator bsi;
|
||||
|
@ -1309,7 +1309,6 @@ emit_mfence_after_loop (class loop *loop)
|
|||
gsi_insert_before (&bsi, call, GSI_NEW_STMT);
|
||||
}
|
||||
|
||||
exits.release ();
|
||||
update_ssa (TODO_update_ssa_only_virtuals);
|
||||
}
|
||||
|
||||
|
@ -1327,7 +1326,7 @@ may_use_storent_in_loop_p (class loop *loop)
|
|||
is a suitable place for it at each of the loop exits. */
|
||||
if (FENCE_FOLLOWING_MOVNT != NULL_TREE)
|
||||
{
|
||||
vec<edge> exits = get_loop_exit_edges (loop);
|
||||
auto_vec<edge> exits = get_loop_exit_edges (loop);
|
||||
unsigned i;
|
||||
edge exit;
|
||||
|
||||
|
@ -1335,8 +1334,6 @@ may_use_storent_in_loop_p (class loop *loop)
|
|||
if ((exit->flags & EDGE_ABNORMAL)
|
||||
&& exit->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
|
||||
ret = false;
|
||||
|
||||
exits.release ();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -1540,6 +1540,13 @@ public:
|
|||
auto_vec () { this->m_vec = NULL; }
|
||||
auto_vec (size_t n) { this->create (n); }
|
||||
~auto_vec () { this->release (); }
|
||||
|
||||
auto_vec (auto_vec&& r)
|
||||
{
|
||||
this->m_vec = r.m_vec;
|
||||
r.m_vec = NULL;
|
||||
}
|
||||
void operator= (auto_vec&&) = delete;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue