Message ID | nycvar.YFH.7.76.2008061457560.9963@zhemvz.fhfr.qr |
---|---|
State | New |
Headers | show |
Series | add move CTOR to auto_vec, use auto_vec for get_loop_exit_edges | expand |
On Thu, 6 Aug 2020, Richard Biener wrote: > 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). > > Bootstrap / regtest running on x86_64-unknown-linux-gnu. > > Does this all look sensible and is it a good change > (the get_loop_exit_edges one)? Regtest went OK, here's an update with a complete ChangeLog (how useful..) plus the move assign operator deleted, copy assign wouldn't work as auto-generated and at the moment there's no use of assigning. I guess if we'd have functions that take an auto_vec<> argument meaning they will destroy the vector that will become useful and we can implement it. OK for trunk? Thanks, Richard. From d74c346e95ff967d930b7c83daabc26b0227aea3 Mon Sep 17 00:00:00 2001 From: Richard Biener <rguenther@suse.de> Date: Thu, 6 Aug 2020 14:50:56 +0200 Subject: [PATCH] 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. --- gcc/cfgloop.c | 4 ++-- gcc/cfgloop.h | 2 +- gcc/cfgloopmanip.c | 3 +-- gcc/hash-table.h | 2 +- gcc/ipa-fnsummary.c | 4 +--- gcc/ira-build.c | 12 +++--------- gcc/ira-color.c | 4 +--- gcc/loop-unroll.c | 3 +-- gcc/predict.c | 9 ++------- gcc/tree-predcom.c | 3 +-- gcc/tree-ssa-loop-ch.c | 3 +-- gcc/tree-ssa-loop-im.c | 3 +-- gcc/tree-ssa-loop-ivcanon.c | 9 ++------- gcc/tree-ssa-loop-manip.c | 3 +-- gcc/tree-ssa-loop-niter.c | 20 +++++--------------- gcc/tree-ssa-loop-prefetch.c | 7 ++----- gcc/vec.h | 7 +++++++ 17 files changed, 33 insertions(+), 65 deletions(-) diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index 7720e6e5d2c..33a26cca6a4 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -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; diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 18b404e292f..f1687f37401 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -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 *); diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index 73134a20e33..3c9e2a0a99c 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -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; } diff --git a/gcc/hash-table.h b/gcc/hash-table.h index 32f3a634e1e..487003c3acf 100644 --- a/gcc/hash-table.h +++ b/gcc/hash-table.h @@ -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++; diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index 59e52927151..f750ec1725c 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -2767,7 +2767,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; @@ -2776,7 +2775,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)) @@ -2794,7 +2793,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 diff --git a/gcc/ira-build.c b/gcc/ira-build.c index 0bbdb4d0c4b..9b35d0e83a9 100644 --- a/gcc/ira-build.c +++ b/gcc/ira-build.c @@ -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 diff --git a/gcc/ira-color.c b/gcc/ira-color.c index dbb3b7a2a51..d3f8e23faff 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -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); diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c index 693c7768868..e1efe624361 100644 --- a/gcc/loop-unroll.c +++ b/gcc/loop-unroll.c @@ -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; } diff --git a/gcc/predict.c b/gcc/predict.c index 0a317a7a4ac..a847b9b4045 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -1915,7 +1915,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; @@ -1926,15 +1925,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", @@ -2048,7 +2044,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; diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c index d2dcfe7f42d..93e6da1e2ab 100644 --- a/gcc/tree-predcom.c +++ b/gcc/tree-predcom.c @@ -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; } diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c index b9002d8e294..b86acf7c39d 100644 --- a/gcc/tree-ssa-loop-ch.c +++ b/gcc/tree-ssa-loop-ch.c @@ -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); diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 35da1fb26a6..8b7eb57514f 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -2866,7 +2866,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); @@ -2876,7 +2876,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) diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index 298ab215530..5bb781dc7fa 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -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. */ diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index a2717a411a3..cdd1ac76833 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -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 (); } } diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 7d61ef080eb..8bb29c2470f 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -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); diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c index d19ece6410d..5e94a19c964 100644 --- a/gcc/tree-ssa-loop-prefetch.c +++ b/gcc/tree-ssa-loop-prefetch.c @@ -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; diff --git a/gcc/vec.h b/gcc/vec.h index 3ad99b83690..4f18116e1b8 100644 --- a/gcc/vec.h +++ b/gcc/vec.h @@ -1533,6 +1533,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; };
On Thu, 6 Aug 2020, Richard Biener wrote: > On Thu, 6 Aug 2020, Richard Biener wrote: > > > 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). > > > > Bootstrap / regtest running on x86_64-unknown-linux-gnu. > > > > Does this all look sensible and is it a good change > > (the get_loop_exit_edges one)? > > Regtest went OK, here's an update with a complete ChangeLog > (how useful..) plus the move assign operator deleted, copy > assign wouldn't work as auto-generated and at the moment > there's no use of assigning. I guess if we'd have functions > that take an auto_vec<> argument meaning they will destroy > the vector that will become useful and we can implement it. > > OK for trunk? Ping. > Thanks, > Richard. > > > From d74c346e95ff967d930b7c83daabc26b0227aea3 Mon Sep 17 00:00:00 2001 > From: Richard Biener <rguenther@suse.de> > Date: Thu, 6 Aug 2020 14:50:56 +0200 > Subject: [PATCH] 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. > --- > gcc/cfgloop.c | 4 ++-- > gcc/cfgloop.h | 2 +- > gcc/cfgloopmanip.c | 3 +-- > gcc/hash-table.h | 2 +- > gcc/ipa-fnsummary.c | 4 +--- > gcc/ira-build.c | 12 +++--------- > gcc/ira-color.c | 4 +--- > gcc/loop-unroll.c | 3 +-- > gcc/predict.c | 9 ++------- > gcc/tree-predcom.c | 3 +-- > gcc/tree-ssa-loop-ch.c | 3 +-- > gcc/tree-ssa-loop-im.c | 3 +-- > gcc/tree-ssa-loop-ivcanon.c | 9 ++------- > gcc/tree-ssa-loop-manip.c | 3 +-- > gcc/tree-ssa-loop-niter.c | 20 +++++--------------- > gcc/tree-ssa-loop-prefetch.c | 7 ++----- > gcc/vec.h | 7 +++++++ > 17 files changed, 33 insertions(+), 65 deletions(-) > > diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c > index 7720e6e5d2c..33a26cca6a4 100644 > --- a/gcc/cfgloop.c > +++ b/gcc/cfgloop.c > @@ -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; > diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h > index 18b404e292f..f1687f37401 100644 > --- a/gcc/cfgloop.h > +++ b/gcc/cfgloop.h > @@ -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 *); > diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c > index 73134a20e33..3c9e2a0a99c 100644 > --- a/gcc/cfgloopmanip.c > +++ b/gcc/cfgloopmanip.c > @@ -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; > } > > diff --git a/gcc/hash-table.h b/gcc/hash-table.h > index 32f3a634e1e..487003c3acf 100644 > --- a/gcc/hash-table.h > +++ b/gcc/hash-table.h > @@ -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++; > diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c > index 59e52927151..f750ec1725c 100644 > --- a/gcc/ipa-fnsummary.c > +++ b/gcc/ipa-fnsummary.c > @@ -2767,7 +2767,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; > @@ -2776,7 +2775,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)) > @@ -2794,7 +2793,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 > diff --git a/gcc/ira-build.c b/gcc/ira-build.c > index 0bbdb4d0c4b..9b35d0e83a9 100644 > --- a/gcc/ira-build.c > +++ b/gcc/ira-build.c > @@ -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 > diff --git a/gcc/ira-color.c b/gcc/ira-color.c > index dbb3b7a2a51..d3f8e23faff 100644 > --- a/gcc/ira-color.c > +++ b/gcc/ira-color.c > @@ -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); > diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c > index 693c7768868..e1efe624361 100644 > --- a/gcc/loop-unroll.c > +++ b/gcc/loop-unroll.c > @@ -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; > } > diff --git a/gcc/predict.c b/gcc/predict.c > index 0a317a7a4ac..a847b9b4045 100644 > --- a/gcc/predict.c > +++ b/gcc/predict.c > @@ -1915,7 +1915,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; > @@ -1926,15 +1925,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", > @@ -2048,7 +2044,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; > diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c > index d2dcfe7f42d..93e6da1e2ab 100644 > --- a/gcc/tree-predcom.c > +++ b/gcc/tree-predcom.c > @@ -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; > } > diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c > index b9002d8e294..b86acf7c39d 100644 > --- a/gcc/tree-ssa-loop-ch.c > +++ b/gcc/tree-ssa-loop-ch.c > @@ -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); > diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c > index 35da1fb26a6..8b7eb57514f 100644 > --- a/gcc/tree-ssa-loop-im.c > +++ b/gcc/tree-ssa-loop-im.c > @@ -2866,7 +2866,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); > > @@ -2876,7 +2876,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) > diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c > index 298ab215530..5bb781dc7fa 100644 > --- a/gcc/tree-ssa-loop-ivcanon.c > +++ b/gcc/tree-ssa-loop-ivcanon.c > @@ -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. */ > diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c > index a2717a411a3..cdd1ac76833 100644 > --- a/gcc/tree-ssa-loop-manip.c > +++ b/gcc/tree-ssa-loop-manip.c > @@ -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 (); > } > } > > diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c > index 7d61ef080eb..8bb29c2470f 100644 > --- a/gcc/tree-ssa-loop-niter.c > +++ b/gcc/tree-ssa-loop-niter.c > @@ -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); > diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c > index d19ece6410d..5e94a19c964 100644 > --- a/gcc/tree-ssa-loop-prefetch.c > +++ b/gcc/tree-ssa-loop-prefetch.c > @@ -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; > diff --git a/gcc/vec.h b/gcc/vec.h > index 3ad99b83690..4f18116e1b8 100644 > --- a/gcc/vec.h > +++ b/gcc/vec.h > @@ -1533,6 +1533,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; > }; > > >
On Wed, 26 Aug 2020, Richard Biener wrote: > On Thu, 6 Aug 2020, Richard Biener wrote: > > > On Thu, 6 Aug 2020, Richard Biener wrote: > > > > > 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). > > > > > > Bootstrap / regtest running on x86_64-unknown-linux-gnu. > > > > > > Does this all look sensible and is it a good change > > > (the get_loop_exit_edges one)? > > > > Regtest went OK, here's an update with a complete ChangeLog > > (how useful..) plus the move assign operator deleted, copy > > assign wouldn't work as auto-generated and at the moment > > there's no use of assigning. I guess if we'd have functions > > that take an auto_vec<> argument meaning they will destroy > > the vector that will become useful and we can implement it. > > > > OK for trunk? > > Ping. Ping^2. Thanks, Richard. > > Thanks, > > Richard. > > > > > > From d74c346e95ff967d930b7c83daabc26b0227aea3 Mon Sep 17 00:00:00 2001 > > From: Richard Biener <rguenther@suse.de> > > Date: Thu, 6 Aug 2020 14:50:56 +0200 > > Subject: [PATCH] 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. > > --- > > gcc/cfgloop.c | 4 ++-- > > gcc/cfgloop.h | 2 +- > > gcc/cfgloopmanip.c | 3 +-- > > gcc/hash-table.h | 2 +- > > gcc/ipa-fnsummary.c | 4 +--- > > gcc/ira-build.c | 12 +++--------- > > gcc/ira-color.c | 4 +--- > > gcc/loop-unroll.c | 3 +-- > > gcc/predict.c | 9 ++------- > > gcc/tree-predcom.c | 3 +-- > > gcc/tree-ssa-loop-ch.c | 3 +-- > > gcc/tree-ssa-loop-im.c | 3 +-- > > gcc/tree-ssa-loop-ivcanon.c | 9 ++------- > > gcc/tree-ssa-loop-manip.c | 3 +-- > > gcc/tree-ssa-loop-niter.c | 20 +++++--------------- > > gcc/tree-ssa-loop-prefetch.c | 7 ++----- > > gcc/vec.h | 7 +++++++ > > 17 files changed, 33 insertions(+), 65 deletions(-) > > > > diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c > > index 7720e6e5d2c..33a26cca6a4 100644 > > --- a/gcc/cfgloop.c > > +++ b/gcc/cfgloop.c > > @@ -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; > > diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h > > index 18b404e292f..f1687f37401 100644 > > --- a/gcc/cfgloop.h > > +++ b/gcc/cfgloop.h > > @@ -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 *); > > diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c > > index 73134a20e33..3c9e2a0a99c 100644 > > --- a/gcc/cfgloopmanip.c > > +++ b/gcc/cfgloopmanip.c > > @@ -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; > > } > > > > diff --git a/gcc/hash-table.h b/gcc/hash-table.h > > index 32f3a634e1e..487003c3acf 100644 > > --- a/gcc/hash-table.h > > +++ b/gcc/hash-table.h > > @@ -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++; > > diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c > > index 59e52927151..f750ec1725c 100644 > > --- a/gcc/ipa-fnsummary.c > > +++ b/gcc/ipa-fnsummary.c > > @@ -2767,7 +2767,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; > > @@ -2776,7 +2775,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)) > > @@ -2794,7 +2793,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 > > diff --git a/gcc/ira-build.c b/gcc/ira-build.c > > index 0bbdb4d0c4b..9b35d0e83a9 100644 > > --- a/gcc/ira-build.c > > +++ b/gcc/ira-build.c > > @@ -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 > > diff --git a/gcc/ira-color.c b/gcc/ira-color.c > > index dbb3b7a2a51..d3f8e23faff 100644 > > --- a/gcc/ira-color.c > > +++ b/gcc/ira-color.c > > @@ -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); > > diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c > > index 693c7768868..e1efe624361 100644 > > --- a/gcc/loop-unroll.c > > +++ b/gcc/loop-unroll.c > > @@ -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; > > } > > diff --git a/gcc/predict.c b/gcc/predict.c > > index 0a317a7a4ac..a847b9b4045 100644 > > --- a/gcc/predict.c > > +++ b/gcc/predict.c > > @@ -1915,7 +1915,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; > > @@ -1926,15 +1925,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", > > @@ -2048,7 +2044,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; > > diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c > > index d2dcfe7f42d..93e6da1e2ab 100644 > > --- a/gcc/tree-predcom.c > > +++ b/gcc/tree-predcom.c > > @@ -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; > > } > > diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c > > index b9002d8e294..b86acf7c39d 100644 > > --- a/gcc/tree-ssa-loop-ch.c > > +++ b/gcc/tree-ssa-loop-ch.c > > @@ -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); > > diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c > > index 35da1fb26a6..8b7eb57514f 100644 > > --- a/gcc/tree-ssa-loop-im.c > > +++ b/gcc/tree-ssa-loop-im.c > > @@ -2866,7 +2866,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); > > > > @@ -2876,7 +2876,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) > > diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c > > index 298ab215530..5bb781dc7fa 100644 > > --- a/gcc/tree-ssa-loop-ivcanon.c > > +++ b/gcc/tree-ssa-loop-ivcanon.c > > @@ -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. */ > > diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c > > index a2717a411a3..cdd1ac76833 100644 > > --- a/gcc/tree-ssa-loop-manip.c > > +++ b/gcc/tree-ssa-loop-manip.c > > @@ -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 (); > > } > > } > > > > diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c > > index 7d61ef080eb..8bb29c2470f 100644 > > --- a/gcc/tree-ssa-loop-niter.c > > +++ b/gcc/tree-ssa-loop-niter.c > > @@ -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); > > diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c > > index d19ece6410d..5e94a19c964 100644 > > --- a/gcc/tree-ssa-loop-prefetch.c > > +++ b/gcc/tree-ssa-loop-prefetch.c > > @@ -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; > > diff --git a/gcc/vec.h b/gcc/vec.h > > index 3ad99b83690..4f18116e1b8 100644 > > --- a/gcc/vec.h > > +++ b/gcc/vec.h > > @@ -1533,6 +1533,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; > > }; > > > > > > > >
On 24/09/20 11:11 +0200, Richard Biener wrote: >On Wed, 26 Aug 2020, Richard Biener wrote: > >> On Thu, 6 Aug 2020, Richard Biener wrote: >> >> > On Thu, 6 Aug 2020, Richard Biener wrote: >> > >> > > 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). >> > > >> > > Bootstrap / regtest running on x86_64-unknown-linux-gnu. >> > > >> > > Does this all look sensible and is it a good change >> > > (the get_loop_exit_edges one)? >> > >> > Regtest went OK, here's an update with a complete ChangeLog >> > (how useful..) plus the move assign operator deleted, copy >> > assign wouldn't work as auto-generated and at the moment >> > there's no use of assigning. I guess if we'd have functions >> > that take an auto_vec<> argument meaning they will destroy >> > the vector that will become useful and we can implement it. >> > >> > OK for trunk? >> >> Ping. > >Ping^2. Looks good to me as far as the use of C++ features goes.
On Thu, 24 Sep 2020, Jonathan Wakely wrote: > On 24/09/20 11:11 +0200, Richard Biener wrote: > >On Wed, 26 Aug 2020, Richard Biener wrote: > > > >> On Thu, 6 Aug 2020, Richard Biener wrote: > >> > >> > On Thu, 6 Aug 2020, Richard Biener wrote: > >> > > >> > > 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). > >> > > > >> > > Bootstrap / regtest running on x86_64-unknown-linux-gnu. > >> > > > >> > > Does this all look sensible and is it a good change > >> > > (the get_loop_exit_edges one)? > >> > > >> > Regtest went OK, here's an update with a complete ChangeLog > >> > (how useful..) plus the move assign operator deleted, copy > >> > assign wouldn't work as auto-generated and at the moment > >> > there's no use of assigning. I guess if we'd have functions > >> > that take an auto_vec<> argument meaning they will destroy > >> > the vector that will become useful and we can implement it. > >> > > >> > OK for trunk? > >> > >> Ping. > > > >Ping^2. > > Looks good to me as far as the use of C++ features goes. Thanks, now pushed after re-testing. Richard.
On 9/24/20 5:05 PM, Richard Biener wrote: > On Thu, 24 Sep 2020, Jonathan Wakely wrote: > >> On 24/09/20 11:11 +0200, Richard Biener wrote: >>> On Wed, 26 Aug 2020, Richard Biener wrote: >>> >>>> On Thu, 6 Aug 2020, Richard Biener wrote: >>>> >>>>> On Thu, 6 Aug 2020, Richard Biener wrote: >>>>> >>>>>> 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). >>>>>> >>>>>> Bootstrap / regtest running on x86_64-unknown-linux-gnu. >>>>>> >>>>>> Does this all look sensible and is it a good change >>>>>> (the get_loop_exit_edges one)? >>>>> >>>>> Regtest went OK, here's an update with a complete ChangeLog >>>>> (how useful..) plus the move assign operator deleted, copy >>>>> assign wouldn't work as auto-generated and at the moment >>>>> there's no use of assigning. I guess if we'd have functions >>>>> that take an auto_vec<> argument meaning they will destroy >>>>> the vector that will become useful and we can implement it. >>>>> >>>>> OK for trunk? >>>> >>>> Ping. >>> >>> Ping^2. >> >> Looks good to me as far as the use of C++ features goes. > > Thanks, now pushed after re-testing. Ran into a build breaker after this commit, reported here ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97207 ). Thanks, - Tom
diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index 7720e6e5d2c..33a26cca6a4 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -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; diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 18b404e292f..f1687f37401 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -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 *); diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index 73134a20e33..3c9e2a0a99c 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -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; } diff --git a/gcc/hash-table.h b/gcc/hash-table.h index 32f3a634e1e..487003c3acf 100644 --- a/gcc/hash-table.h +++ b/gcc/hash-table.h @@ -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++; diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index 59e52927151..f750ec1725c 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -2767,7 +2767,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; @@ -2776,7 +2775,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)) @@ -2794,7 +2793,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 diff --git a/gcc/ira-build.c b/gcc/ira-build.c index 0bbdb4d0c4b..9b35d0e83a9 100644 --- a/gcc/ira-build.c +++ b/gcc/ira-build.c @@ -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 diff --git a/gcc/ira-color.c b/gcc/ira-color.c index dbb3b7a2a51..d3f8e23faff 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -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); diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c index 693c7768868..e1efe624361 100644 --- a/gcc/loop-unroll.c +++ b/gcc/loop-unroll.c @@ -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; } diff --git a/gcc/predict.c b/gcc/predict.c index 0a317a7a4ac..a847b9b4045 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -1915,7 +1915,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; @@ -1926,15 +1925,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", @@ -2048,7 +2044,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; diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c index d2dcfe7f42d..93e6da1e2ab 100644 --- a/gcc/tree-predcom.c +++ b/gcc/tree-predcom.c @@ -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; } diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c index b9002d8e294..b86acf7c39d 100644 --- a/gcc/tree-ssa-loop-ch.c +++ b/gcc/tree-ssa-loop-ch.c @@ -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); diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 35da1fb26a6..8b7eb57514f 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -2866,7 +2866,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); @@ -2876,7 +2876,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) diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index 298ab215530..5bb781dc7fa 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -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. */ diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index a2717a411a3..cdd1ac76833 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -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 (); } } diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 7d61ef080eb..8bb29c2470f 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -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); diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c index d19ece6410d..5e94a19c964 100644 --- a/gcc/tree-ssa-loop-prefetch.c +++ b/gcc/tree-ssa-loop-prefetch.c @@ -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; diff --git a/gcc/vec.h b/gcc/vec.h index 3ad99b83690..38478bffc6b 100644 --- a/gcc/vec.h +++ b/gcc/vec.h @@ -1533,6 +1533,12 @@ 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; + } };