public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Martin Sebor <msebor@gmail.com>
To: Richard Biener <richard.guenther@gmail.com>
Cc: Jason Merrill <jason@redhat.com>,
	gcc-patches <gcc-patches@gcc.gnu.org>,
	Jonathan Wakely <jwakely@redhat.com>
Subject: Re: [PING][PATCH] define auto_vec copy ctor and assignment (PR 90904)
Date: Wed, 7 Jul 2021 08:37:41 -0600	[thread overview]
Message-ID: <d4dc05d2-af46-876a-a3c3-fb76a0d1d5c0@gmail.com> (raw)
In-Reply-To: <CAFiYyc1Lhopj5B=zCrNteYP5sQv0teAOfTc9Mi1vDn=QNJ2njA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 11980 bytes --]

On 7/7/21 1:28 AM, Richard Biener wrote:
> On Tue, Jul 6, 2021 at 5:06 PM Martin Sebor <msebor@gmail.com> wrote:
>>
>> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573968.html
>>
>> Any questions/suggestions on the final patch or is it okay to commit?
> 
> I don't remember seeing one (aka saying "bootstrapped/tested, OK to commit?"
> or so) - and the link above doesn't have one.
> 
> So, can you re-post it please?

The patch is attached to the email above with the following text
at the end:

   Attached is a revised patch with these changes (a superset of
   those I sent in response to Jason's question), tested on x86_64.

I've also attached it to this reply.

Martin

> 
> Thanks,
> Richard.
> 
>> On 6/29/21 7:46 PM, Martin Sebor wrote:
>>> On 6/29/21 4:58 AM, Richard Biener wrote:
>>>> On Mon, Jun 28, 2021 at 8:07 PM Martin Sebor <msebor@gmail.com> wrote:
>>>>>
>>>>> On 6/28/21 2:07 AM, Richard Biener wrote:
>>>>>> On Sat, Jun 26, 2021 at 12:36 AM Martin Sebor <msebor@gmail.com> wrote:
>>>>>>>
>>>>>>> On 6/25/21 4:11 PM, Jason Merrill wrote:
>>>>>>>> On 6/25/21 4:51 PM, Martin Sebor wrote:
>>>>>>>>> On 6/1/21 3:38 PM, Jason Merrill wrote:
>>>>>>>>>> On 6/1/21 3:56 PM, Martin Sebor wrote:
>>>>>>>>>>> On 5/27/21 2:53 PM, Jason Merrill wrote:
>>>>>>>>>>>> On 4/27/21 11:52 AM, Martin Sebor via Gcc-patches wrote:
>>>>>>>>>>>>> On 4/27/21 8:04 AM, Richard Biener wrote:
>>>>>>>>>>>>>> On Tue, Apr 27, 2021 at 3:59 PM Martin Sebor <msebor@gmail.com>
>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> On 4/27/21 1:58 AM, Richard Biener wrote:
>>>>>>>>>>>>>>>> On Tue, Apr 27, 2021 at 2:46 AM Martin Sebor via Gcc-patches
>>>>>>>>>>>>>>>> <gcc-patches@gcc.gnu.org> wrote:
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> PR 90904 notes that auto_vec is unsafe to copy and assign
>>>>>>>>>>>>>>>>> because
>>>>>>>>>>>>>>>>> the class manages its own memory but doesn't define (or
>>>>>>>>>>>>>>>>> delete)
>>>>>>>>>>>>>>>>> either special function.  Since I first ran into the
>>>>>>>>>>>>>>>>> problem,
>>>>>>>>>>>>>>>>> auto_vec has grown a move ctor and move assignment from
>>>>>>>>>>>>>>>>> a dynamically-allocated vec but still no copy ctor or copy
>>>>>>>>>>>>>>>>> assignment operator.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> The attached patch adds the two special functions to
>>>>>>>>>>>>>>>>> auto_vec
>>>>>>>>>>>>>>>>> along
>>>>>>>>>>>>>>>>> with a few simple tests.  It makes auto_vec safe to use in
>>>>>>>>>>>>>>>>> containers
>>>>>>>>>>>>>>>>> that expect copyable and assignable element types and passes
>>>>>>>>>>>>>>>>> bootstrap
>>>>>>>>>>>>>>>>> and regression testing on x86_64-linux.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> The question is whether we want such uses to appear since
>>>>>>>>>>>>>>>> those
>>>>>>>>>>>>>>>> can be quite inefficient?  Thus the option is to delete those
>>>>>>>>>>>>>>>> operators?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I would strongly prefer the generic vector class to have the
>>>>>>>>>>>>>>> properties
>>>>>>>>>>>>>>> expected of any other generic container: copyable and
>>>>>>>>>>>>>>> assignable.  If
>>>>>>>>>>>>>>> we also want another vector type with this restriction I
>>>>>>>>>>>>>>> suggest
>>>>>>>>>>>>>>> to add
>>>>>>>>>>>>>>> another "noncopyable" type and make that property explicit in
>>>>>>>>>>>>>>> its name.
>>>>>>>>>>>>>>> I can submit one in a followup patch if you think we need one.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I'm not sure (and not strictly against the copy and assign).
>>>>>>>>>>>>>> Looking around
>>>>>>>>>>>>>> I see that vec<> does not do deep copying.  Making
>>>>>>>>>>>>>> auto_vec<> do it
>>>>>>>>>>>>>> might be surprising (I added the move capability to match
>>>>>>>>>>>>>> how vec<>
>>>>>>>>>>>>>> is used - as "reference" to a vector)
>>>>>>>>>>>>>
>>>>>>>>>>>>> The vec base classes are special: they have no ctors at all
>>>>>>>>>>>>> (because
>>>>>>>>>>>>> of their use in unions).  That's something we might have to
>>>>>>>>>>>>> live with
>>>>>>>>>>>>> but it's not a model to follow in ordinary containers.
>>>>>>>>>>>>
>>>>>>>>>>>> I don't think we have to live with it anymore, now that we're
>>>>>>>>>>>> writing C++11.
>>>>>>>>>>>>
>>>>>>>>>>>>> The auto_vec class was introduced to fill the need for a
>>>>>>>>>>>>> conventional
>>>>>>>>>>>>> sequence container with a ctor and dtor.  The missing copy
>>>>>>>>>>>>> ctor and
>>>>>>>>>>>>> assignment operators were an oversight, not a deliberate
>>>>>>>>>>>>> feature.
>>>>>>>>>>>>> This change fixes that oversight.
>>>>>>>>>>>>>
>>>>>>>>>>>>> The revised patch also adds a copy ctor/assignment to the
>>>>>>>>>>>>> auto_vec
>>>>>>>>>>>>> primary template (that's also missing it).  In addition, it adds
>>>>>>>>>>>>> a new class called auto_vec_ncopy that disables copying and
>>>>>>>>>>>>> assignment as you prefer.
>>>>>>>>>>>>
>>>>>>>>>>>> Hmm, adding another class doesn't really help with the confusion
>>>>>>>>>>>> richi mentions.  And many uses of auto_vec will pass them as vec,
>>>>>>>>>>>> which will still do a shallow copy.  I think it's probably better
>>>>>>>>>>>> to disable the copy special members for auto_vec until we fix
>>>>>>>>>>>> vec<>.
>>>>>>>>>>>
>>>>>>>>>>> There are at least a couple of problems that get in the way of
>>>>>>>>>>> fixing
>>>>>>>>>>> all of vec to act like a well-behaved C++ container:
>>>>>>>>>>>
>>>>>>>>>>> 1) The embedded vec has a trailing "flexible" array member with
>>>>>>>>>>> its
>>>>>>>>>>> instances having different size.  They're initialized by memset
>>>>>>>>>>> and
>>>>>>>>>>> copied by memcpy.  The class can't have copy ctors or assignments
>>>>>>>>>>> but it should disable/delete them instead.
>>>>>>>>>>>
>>>>>>>>>>> 2) The heap-based vec is used throughout GCC with the
>>>>>>>>>>> assumption of
>>>>>>>>>>> shallow copy semantics (not just as function arguments but also as
>>>>>>>>>>> members of other such POD classes).  This can be changed by
>>>>>>>>>>> providing
>>>>>>>>>>> copy and move ctors and assignment operators for it, and also for
>>>>>>>>>>> some of the classes in which it's a member and that are used with
>>>>>>>>>>> the same assumption.
>>>>>>>>>>>
>>>>>>>>>>> 3) The heap-based vec::block_remove() assumes its elements are
>>>>>>>>>>> PODs.
>>>>>>>>>>> That breaks in VEC_ORDERED_REMOVE_IF (used in gcc/dwarf2cfi.c:2862
>>>>>>>>>>> and tree-vect-patterns.c).
>>>>>>>>>>>
>>>>>>>>>>> I took a stab at both and while (1) is easy, (2) is shaping up to
>>>>>>>>>>> be a big and tricky project.  Tricky because it involves using
>>>>>>>>>>> std::move in places where what's moved is subsequently still used.
>>>>>>>>>>> I can keep plugging away at it but it won't change the fact that
>>>>>>>>>>> the embedded and heap-based vecs have different requirements.
>>>>>>>>>>>
>>>>>>>>>>> It doesn't seem to me that having a safely copyable auto_vec needs
>>>>>>>>>>> to be put on hold until the rats nest above is untangled.  It
>>>>>>>>>>> won't
>>>>>>>>>>> make anything worse than it is.  (I have a project that depends on
>>>>>>>>>>> a sane auto_vec working).
>>>>>>>>>>>
>>>>>>>>>>> A couple of alternatives to solving this are to use std::vector or
>>>>>>>>>>> write an equivalent vector class just for GCC.
>>>>>>>>>>
>>>>>>>>>> It occurs to me that another way to work around the issue of
>>>>>>>>>> passing
>>>>>>>>>> an auto_vec by value as a vec, and thus doing a shallow copy, would
>>>>>>>>>> be to add a vec ctor taking an auto_vec, and delete that.  This
>>>>>>>>>> would
>>>>>>>>>> mean if you want to pass an auto_vec to a vec interface, it
>>>>>>>>>> needs to
>>>>>>>>>> be by reference.  We might as well do the same for operator=,
>>>>>>>>>> though
>>>>>>>>>> that isn't as important.
>>>>>>>>>
>>>>>>>>> Thanks, that sounds like a good idea.  Attached is an implementation
>>>>>>>>> of this change.  Since the auto_vec copy ctor and assignment have
>>>>>>>>> been deleted by someone else in the interim, this patch doesn't
>>>>>>>>> reverse that.  I will propose it separately after these changes
>>>>>>>>> are finalized.
>>>>>>>>>
>>>>>>>>> My approach was to 1) disable the auto_vec to vec conversion,
>>>>>>>>> 2) introduce an auto_vec::to_vec() to make the conversion possible
>>>>>>>>> explicitly, and 3) resolve compilation errors by either changing
>>>>>>>>> APIs to take a vec by reference or callers to convert auto_vec to
>>>>>>>>> vec explicitly by to_vec().  In (3) I tried to minimize churn while
>>>>>>>>> improving the const-correctness of the APIs.
>>>>>>>>
>>>>>>>> What did you base the choice between reference or to_vec on?  For
>>>>>>>> instance, it seems like c_parser_declaration_or_fndef could use a
>>>>>>>> reference, but you changed the callers instead.
>>>>>>>
>>>>>>> I went with a reference whenever I could.  That doesn't work when
>>>>>>> there are callers that pass in a vNULL, so there, and in assignments,
>>>>>>> I used to_vec().
>>>>>>
>>>>>> Is there a way to "fix" the ugliness with vNULL?  All those functions
>>>>>> should be able to use const vec<>& as otherwise they'd leak memory?
>>>>>> Can't we pass vNULL to a const vec<>&?
>>>>>
>>>>> vNULL can bind to a const vec& (via the vec conversion ctor) but
>>>>> not to vec&.  The three functions that in the patch are passed
>>>>> vNULL modify the argument when it's not vNULL but not otherwise.
>>>>> An alternate design is to have them take a vec* and pass in
>>>>> a plain NULL (or nullptr) instead of vNULL.  That would require
>>>>> some surgery on the function bodies that I've been trying to
>>>>> avoid in the first pass.
>>>>
>>>> But I wonder if since you now identified them they could be massaged
>>>> prior to doing the change.
>>>>
>>>> I do hope we end up not needing .to_vec () after all, if no users
>>>> remain ;)
>>>
>>> I'd be happy to if none remained.  I see how to eliminate those in
>>> calls to functions like c_parser_declaration_or_fndef() (done in
>>> the attached revision of the patch), but no easy way to get rid
>>> of those that replace other implicit conversions, like all those
>>> assignments to the vec members of the ipa_call_arg_values ctor.
>>> If it's appropriate to std::move those then that would get rid
>>> of the .to_vec () call.  I'm not familiar with the code but I
>>> have the impression it might be meant more as a reference to
>>> some "remote" object (an instance of ipa_auto_call_arg_values?)
>>> If that's right then making the vec members auto_vec references
>>> (or pointers) would be one way to "fix" this.
>>>
>>>>> Functions that don't leak memory now shouldn't leak with these
>>>>> changes, and conversely, those that do will still leak.  The patch
>>>>> doesn't change that (as far as I know).
>>>>
>>>> It just occurs to me those cases could pass auto_vec<>() by reference
>>>> instead
>>>> of vNULL?  So if the vector is modified then it's released afterwards?
>>>> That would fix the memleak.
>>>
>>> I see what you mean.  A function that modified the unnamed vec
>>> temporary constructed from vNULL then the modified vector would
>>> leak.  I don't think the functions the patch touches do that but
>>> I've removed the vNULL conversion from all of them.  There are
>>> many others that pass vNULL to a vec arguments that that the patch
>>> doesn't touch but those would be worth a closer look at some point.
>>>
>>> Attached is a revised patch with these changes (a superset of
>>> those I sent in response to Jason's question), tested on x86_64.
>>>
>>> Martin
>>>
>>>>
>>>>> Going forward I think it's possible to replace most uses of vNULL
>>>>> in GCC with direct initialization (e.g., vec<T> v{ }).  Those that
>>>>> can't be readily replaced are the ones where vNULL is passed as
>>>>> an argument to functions taking a vec by value.  Those could be
>>>>> changed to avoid vNULL too, but it would take a different approach
>>>>> and more effort.  I'm not against it but I'd rather decouple those
>>>>> changes from this already sizeable patch.
>>>>>
>>>>> Martin
>>>>>
>>>>>>
>>>>>> Richard.
>>>>>>
>>>>>>>
>>>>>>> Martin
>>>>>>>
>>>>>
>>>
>>


[-- Attachment #2: gcc-auto_vec-no-convert.diff --]
[-- Type: text/x-patch, Size: 75527 bytes --]

Disable implicit conversion from auto_vec to vec.


	* c-common.c (c_build_shufflevector): Adjust to vec change.
	* c-common.h (c_build_shufflevector): Same.

gcc/c/ChangeLog:

	* c-parser.c (c_finish_omp_declare_simd): Adjust to vec change.
	(c_parser_omp_declare_simd): Same.
	* c-tree.h (c_build_function_call_vec): Same.
	* c-typeck.c (c_build_function_call_vec): Same.

gcc/ChangeLog:

	* cfgloop.h (single_likely_exit): Adjust to vec change.
	* cfgloopanal.c (single_likely_exit): Same.
	* cgraph.h (struct cgraph_node): Same.
	* cgraphclones.c (cgraph_node::create_virtual_clone): Same.
	* dominance.c (prune_bbs_to_update_dominators): Same.
	(iterate_fix_dominators): Same.
	* dominance.h (iterate_fix_dominators): Same.
	* genautomata.c (merge_states): Same.
	* genextract.c (VEC_char_to_string): Same.
	* genmatch.c (dt_node::gen_kids_1): Same.
	(walk_captures): Same.
	* gimple-ssa-store-merging.c (check_no_overlap): Same.
	* gimple.c (gimple_build_call_vec): Same.
	(gimple_build_call_internal_vec): Same.
	(gimple_build_switch): Same.
	(sort_case_labels): Same.
	(preprocess_case_label_vec_for_gimple): Same.
	* gimple.h (gimple_build_call_vec): Same.
	(gimple_build_call_internal_vec): Same.
	(gimple_build_switch): Same.
	(sort_case_labels): Same.
	(preprocess_case_label_vec_for_gimple): Same.
	* haifa-sched.c (calc_priorities): Same.
	(haifa_sched_init): Same.
	(sched_init_luids): Same.
	(haifa_init_h_i_d): Same.
	* ipa-cp.c (ipa_get_indirect_edge_target_1): Same.
	(adjust_callers_for_value_intersection): Same.
	(find_more_scalar_values_for_callers_subset): Same.
	(find_more_contexts_for_caller_subset): Same.
	(find_aggregate_values_for_callers_subset): Same.
	(copy_useful_known_contexts): Same.
	* ipa-fnsummary.c (remap_edge_summaries): Same.
	(remap_freqcounting_predicate): Same.
	* ipa-inline.c (add_new_edges_to_heap): Same.
	* ipa-predicate.c (predicate::remap_after_inlining): Same.
	* ipa-predicate.h:
	* ipa-prop.c (ipa_find_agg_cst_for_param): Same.
	* ipa-prop.h (ipa_find_agg_cst_for_param): Same.
	* ira-build.c (ira_loop_tree_body_rev_postorder): Same.
	* read-rtl.c (apply_iterators): Same.
	* rtl.h (native_decode_rtx): Same.
	(native_decode_vector_rtx): Same.
	* sched-int.h (sched_init_luids): Same.
	(haifa_init_h_i_d): Same.
	* simplify-rtx.c (native_decode_vector_rtx): Same.
	(native_decode_rtx): Same.
	* tree-call-cdce.c (gen_shrink_wrap_conditions): Same.
	(shrink_wrap_one_built_in_call_with_conds): Same.
	(shrink_wrap_conditional_dead_built_in_calls): Same.
	* tree-data-ref.c (create_runtime_alias_checks): Same.
	(compute_all_dependences): Same.
	* tree-data-ref.h (compute_all_dependences): Same.
	(create_runtime_alias_checks): Same.
	(index_in_loop_nest): Same.
	* tree-if-conv.c (mask_exists): Same.
	* tree-loop-distribution.c (class loop_distribution): Same.
	(loop_distribution::create_rdg_vertices): Same.
	(dump_rdg_partitions): Same.
	(debug_rdg_partitions): Same.
	(partition_contains_all_rw): Same.
	(loop_distribution::distribute_loop): Same.
	* tree-parloops.c (oacc_entry_exit_ok_1): Same.
	(oacc_entry_exit_single_gang): Same.
	* tree-ssa-loop-im.c (hoist_memory_references): Same.
	(loop_suitable_for_sm): Same.
	* tree-ssa-loop-niter.c (bound_index): Same.
	* tree-ssa-pre.c (insert_into_preds_of_block): Same.
	* tree-ssa-reassoc.c (update_ops): Same.
	(swap_ops_for_binary_stmt): Same.
	(rewrite_expr_tree): Same.
	(rewrite_expr_tree_parallel): Same.
	* tree-ssa-sccvn.c (ao_ref_init_from_vn_reference): Same.
	* tree-ssa-sccvn.h (ao_ref_init_from_vn_reference): Same.
	* tree-ssa-structalias.c (process_all_all_constraints): Same.
	(make_constraints_to): Same.
	(find_func_aliases_for_call): Same.
	(sort_fieldstack): Same.
	(check_for_overlaps): Same.
	* tree-vect-data-refs.c (vect_check_nonzero_value): Same.
	(vect_enhance_data_refs_alignment): Same.
	(vect_check_lower_bound): Same.
	(vect_prune_runtime_alias_test_list): Same.
	(vect_permute_store_chain): Same.
	* tree-vect-loop-manip.c (vect_create_cond_for_align_checks): Same.
	(vect_create_cond_for_unequal_addrs): Same.
	(vect_create_cond_for_lower_bounds): Same.
	(vect_create_cond_for_alias_checks): Same.
	* tree-vect-slp-patterns.c (vect_normalize_conj_loc): Same.
	(vect_validate_multiplication): Same.
	* tree-vect-slp.c (vect_analyze_slp_instance): Same.
	(vect_make_slp_decision): Same.
	(vect_slp_bbs): Same.
	(duplicate_and_interleave): Same.
	(vect_transform_slp_perm_load): Same.
	(vect_schedule_slp): Same.
	* tree-vect-stmts.c (vect_create_vectorized_demotion_stmts): Same.
	* tree-vectorizer.h (vect_permute_store_chain): Same.
	(vect_transform_slp_perm_load): Same.
	(vect_schedule_slp): Same.
	(duplicate_and_interleave): Same.
	* tree.c (build_vector_from_ctor): Same.
	(build_vector): Same.
	(check_vector_cst): Same.
	(check_vector_cst_duplicate): Same.
	(check_vector_cst_fill): Same.
	(check_vector_cst_stepped): Same.
	* tree.h (build_vector_from_ctor): Same.
	* vec.c (test_init): New.
	(vec_c_tests): Call test_init.
	* vec.h (struct vnull): Simplify.
	(auto_vec::to_vec): New member function.
	(vl_ptr>::copy): Use value initialization.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index c4eb2b1c920..9841a320f89 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -1115,8 +1115,8 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask,
    and have vector types, V0 has the same element type as V1, and the
    number of elements the result is that of MASK.  */
 tree
-c_build_shufflevector (location_t loc, tree v0, tree v1, vec<tree> mask,
-		       bool complain)
+c_build_shufflevector (location_t loc, tree v0, tree v1,
+		       const vec<tree> &mask, bool complain)
 {
   tree ret;
   bool wrap = true;
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 88022d0b0a9..e43b12ae1dc 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1049,7 +1049,7 @@ extern bool vector_targets_convertible_p (const_tree t1, const_tree t2);
 extern bool vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note);
 extern tree c_build_vec_perm_expr (location_t, tree, tree, tree, bool = true);
 extern tree c_build_shufflevector (location_t, tree, tree,
-				   vec<tree>, bool = true);
+				   const vec<tree> &, bool = true);
 extern tree c_build_vec_convert (location_t, tree, location_t, tree, bool = true);
 
 extern void init_c_lex (void);
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 27034f88f49..b77e5b4f5c0 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1489,7 +1489,8 @@ static tree c_parser_std_attribute_specifier_sequence (c_parser *);
 static void c_parser_external_declaration (c_parser *);
 static void c_parser_asm_definition (c_parser *);
 static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
-					   bool, bool, tree *, vec<c_token>,
+					   bool, bool, tree * = NULL,
+					   vec<c_token> * = NULL,
 					   bool have_attrs = false,
 					   tree attrs = NULL,
 					   struct oacc_routine_data * = NULL,
@@ -1774,13 +1775,12 @@ c_parser_external_declaration (c_parser *parser)
 	 an @interface or @protocol with prefix attributes).  We can
 	 only tell which after parsing the declaration specifiers, if
 	 any, and the first declarator.  */
-      c_parser_declaration_or_fndef (parser, true, true, true, false, true,
-				     NULL, vNULL);
+      c_parser_declaration_or_fndef (parser, true, true, true, false, true);
       break;
     }
 }
 
-static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
+static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token> &);
 static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
 
 /* Build and add a DEBUG_BEGIN_STMT statement with location LOC.  */
@@ -1890,11 +1890,15 @@ static void
 c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 			       bool static_assert_ok, bool empty_ok,
 			       bool nested, bool start_attr_ok,
-			       tree *objc_foreach_object_declaration,
-			       vec<c_token> omp_declare_simd_clauses,
-			       bool have_attrs, tree attrs,
-			       struct oacc_routine_data *oacc_routine_data,
-			       bool *fallthru_attr_p)
+			       tree *objc_foreach_object_declaration
+			       /* = NULL */,
+			       vec<c_token> *omp_declare_simd_clauses
+			       /* = NULL */,
+			       bool have_attrs /* = false */,
+			       tree attrs /* = NULL_TREE */,
+			       struct oacc_routine_data *oacc_routine_data
+			       /* = NULL */,
+			       bool *fallthru_attr_p /* = NULL */)
 {
   struct c_declspecs *specs;
   tree prefix_attrs;
@@ -2150,9 +2154,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 					C_DTR_NORMAL, &dummy);
       if (declarator == NULL)
 	{
-	  if (omp_declare_simd_clauses.exists ())
+	  if (omp_declare_simd_clauses)
 	    c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
-				       omp_declare_simd_clauses);
+				       *omp_declare_simd_clauses);
 	  if (oacc_routine_data)
 	    c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
 	  c_parser_skip_to_end_of_block_or_statement (parser);
@@ -2250,9 +2254,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 				  chainon (postfix_attrs, all_prefix_attrs));
 		  if (!d)
 		    d = error_mark_node;
-		  if (omp_declare_simd_clauses.exists ())
+		  if (omp_declare_simd_clauses)
 		    c_finish_omp_declare_simd (parser, d, NULL_TREE,
-					       omp_declare_simd_clauses);
+					       *omp_declare_simd_clauses);
 		}
 	      else
 		{
@@ -2262,9 +2266,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 				  chainon (postfix_attrs, all_prefix_attrs));
 		  if (!d)
 		    d = error_mark_node;
-		  if (omp_declare_simd_clauses.exists ())
+		  if (omp_declare_simd_clauses)
 		    c_finish_omp_declare_simd (parser, d, NULL_TREE,
-					       omp_declare_simd_clauses);
+					       *omp_declare_simd_clauses);
 		  init_loc = c_parser_peek_token (parser)->location;
 		  rich_location richloc (line_table, init_loc);
 		  start_init (d, asm_name, global_bindings_p (), &richloc);
@@ -2342,7 +2346,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 		      warn_parm_array_mismatch (lastloc, d, parms);
 		    }
 		}
-	      if (omp_declare_simd_clauses.exists ())
+	      if (omp_declare_simd_clauses)
 		{
 		  tree parms = NULL_TREE;
 		  if (d && TREE_CODE (d) == FUNCTION_DECL)
@@ -2360,7 +2364,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 		  if (parms)
 		    temp_store_parm_decls (d, parms);
 		  c_finish_omp_declare_simd (parser, d, parms,
-					     omp_declare_simd_clauses);
+					     *omp_declare_simd_clauses);
 		  if (parms)
 		    temp_pop_parm_decls ();
 		}
@@ -2496,11 +2500,11 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
       while (c_parser_next_token_is_not (parser, CPP_EOF)
 	     && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
 	c_parser_declaration_or_fndef (parser, false, false, false,
-				       true, false, NULL, vNULL);
+				       true, false);
       store_parm_decls ();
-      if (omp_declare_simd_clauses.exists ())
+      if (omp_declare_simd_clauses)
 	c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
-				   omp_declare_simd_clauses);
+				   *omp_declare_simd_clauses);
       if (oacc_routine_data)
 	c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
       location_t startloc = c_parser_peek_token (parser)->location;
@@ -5699,7 +5703,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
 	  bool fallthru_attr_p = false;
 	  c_parser_declaration_or_fndef (parser, true, !have_std_attrs,
 					 true, true, true, NULL,
-					 vNULL, have_std_attrs, std_attrs,
+					 NULL, have_std_attrs, std_attrs,
 					 NULL, &fallthru_attr_p);
 
 	  if (last_stmt && !fallthru_attr_p)
@@ -5731,7 +5735,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
 	      last_label = false;
 	      mark_valid_location_for_stdc_pragma (false);
 	      c_parser_declaration_or_fndef (parser, true, true, true, true,
-					     true, NULL, vNULL);
+					     true);
 	      /* Following the old parser, __extension__ does not
 		 disable this diagnostic.  */
 	      restore_extension_diagnostics (ext);
@@ -6782,7 +6786,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
 	       || c_parser_nth_token_starts_std_attributes (parser, 1))
 	{
 	  c_parser_declaration_or_fndef (parser, true, true, true, true, true, 
-					 &object_expression, vNULL);
+					 &object_expression);
 	  parser->objc_could_be_foreach_context = false;
 	  
 	  if (c_parser_next_token_is_keyword (parser, RID_IN))
@@ -6813,7 +6817,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
 	      ext = disable_extension_diagnostics ();
 	      c_parser_consume_token (parser);
 	      c_parser_declaration_or_fndef (parser, true, true, true, true,
-					     true, &object_expression, vNULL);
+					     true, &object_expression);
 	      parser->objc_could_be_foreach_context = false;
 	      
 	      restore_extension_diagnostics (ext);
@@ -11277,7 +11281,7 @@ c_parser_objc_methodprotolist (c_parser *parser)
 	    }
 	  else
 	    c_parser_declaration_or_fndef (parser, false, false, true,
-					   false, true, NULL, vNULL);
+					   false, true);
 	  break;
 	}
     }
@@ -17273,12 +17277,12 @@ c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
 	  while (c_parser_next_token_is (parser, CPP_KEYWORD)
 		 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
 	  c_parser_declaration_or_fndef (parser, true, true, true, false, true,
-					 NULL, vNULL, false, NULL, &data);
+					 NULL, NULL, false, NULL, &data);
 	  restore_extension_diagnostics (ext);
 	}
       else
 	c_parser_declaration_or_fndef (parser, true, true, true, false, true,
-				       NULL, vNULL, false, NULL, &data);
+				       NULL, NULL, false, NULL, &data);
     }
 }
 
@@ -18383,8 +18387,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
 	    vec_safe_push (for_block, c_begin_compound_stmt (true));
 	  this_pre_body = push_stmt_list ();
 	  c_in_omp_for = true;
-	  c_parser_declaration_or_fndef (parser, true, true, true, true, true,
-					 NULL, vNULL);
+	  c_parser_declaration_or_fndef (parser, true, true, true, true, true);
 	  c_in_omp_for = false;
 	  if (this_pre_body)
 	    {
@@ -20325,12 +20328,12 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
 	  while (c_parser_next_token_is (parser, CPP_KEYWORD)
 		 && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
 	  c_parser_declaration_or_fndef (parser, true, true, true, false, true,
-					 NULL, clauses);
+					 NULL, &clauses);
 	  restore_extension_diagnostics (ext);
 	}
       else
 	c_parser_declaration_or_fndef (parser, true, true, true, false, true,
-				       NULL, clauses);
+				       NULL, &clauses);
       break;
     case pragma_struct:
     case pragma_param:
@@ -20351,7 +20354,7 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
 	  if (c_parser_next_tokens_start_declaration (parser))
 	    {
 	      c_parser_declaration_or_fndef (parser, true, true, true, true,
-					     true, NULL, clauses);
+					     true, NULL, &clauses);
 	      restore_extension_diagnostics (ext);
 	      break;
 	    }
@@ -20360,7 +20363,7 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
       else if (c_parser_next_tokens_start_declaration (parser))
 	{
 	  c_parser_declaration_or_fndef (parser, true, true, true, true, true,
-					 NULL, clauses);
+					 NULL, &clauses);
 	  break;
 	}
       error ("%<#pragma omp declare %s%> must be followed by "
@@ -20841,7 +20844,7 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
 
 static void
 c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
-			   vec<c_token> clauses)
+			   vec<c_token> &clauses)
 {
   /* Normally first token is CPP_NAME "simd" or "variant".  CPP_EOF there
      indicates error has been reported and CPP_PRAGMA that
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index a671a3eb740..ab6db3860f5 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -759,8 +759,9 @@ extern tree c_finish_omp_clauses (tree, enum c_omp_region_type);
 extern tree c_build_va_arg (location_t, tree, location_t, tree);
 extern tree c_finish_transaction (location_t, tree, int);
 extern bool c_tree_equal (tree, tree);
-extern tree c_build_function_call_vec (location_t, vec<location_t>, tree,
-				       vec<tree, va_gc> *, vec<tree, va_gc> *);
+extern tree c_build_function_call_vec (location_t, const vec<location_t>&,
+				       tree, vec<tree, va_gc> *,
+				       vec<tree, va_gc> *);
 extern tree c_omp_clause_copy_ctor (tree, tree, tree);
 
 /* Set to 0 at beginning of a function definition, set to 1 if
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index d079ce4b05b..efd4810b901 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3243,7 +3243,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
 /* Like build_function_call_vec, but call also resolve_overloaded_builtin.  */
 
 tree
-c_build_function_call_vec (location_t loc, vec<location_t> arg_loc,
+c_build_function_call_vec (location_t loc, const vec<location_t> &arg_loc,
 			   tree function, vec<tree, va_gc> *params,
 			   vec<tree, va_gc> *origtypes)
 {
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 5e699276c88..5c2b98db9e5 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -385,7 +385,7 @@ extern basic_block *get_loop_body_in_custom_order (const class loop *, void *,
 
 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 edge single_likely_exit (class loop *loop, const vec<edge> &);
 extern unsigned num_loop_branches (const class loop *);
 
 extern edge loop_preheader_edge (const class loop *);
diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c
index 2db46c81036..4cd73c29776 100644
--- a/gcc/cfgloopanal.c
+++ b/gcc/cfgloopanal.c
@@ -470,7 +470,7 @@ mark_loop_exit_edges (void)
    to noreturn call.  */
 
 edge
-single_likely_exit (class loop *loop, vec<edge> exits)
+single_likely_exit (class loop *loop, const vec<edge> &exits)
 {
   edge found = single_exit (loop);
   unsigned i;
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 9f4338fdf87..8c776d6f3a8 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -949,7 +949,7 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
   /* Create callgraph node clone with new declaration.  The actual body will be
      copied later at compilation stage.  The name of the new clone will be
      constructed from the name of the original node, SUFFIX and NUM_SUFFIX.  */
-  cgraph_node *create_virtual_clone (vec<cgraph_edge *> redirect_callers,
+  cgraph_node *create_virtual_clone (const vec<cgraph_edge *> &redirect_callers,
 				     vec<ipa_replace_map *, va_gc> *tree_map,
 				     ipa_param_adjustments *param_adjustments,
 				     const char * suffix, unsigned num_suffix);
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 9f86463b42d..125f1b92862 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -567,7 +567,7 @@ clone_function_name (tree decl, const char *suffix)
    bitmap interface.
    */
 cgraph_node *
-cgraph_node::create_virtual_clone (vec<cgraph_edge *> redirect_callers,
+cgraph_node::create_virtual_clone (const vec<cgraph_edge *> &redirect_callers,
 				   vec<ipa_replace_map *, va_gc> *tree_map,
 				   ipa_param_adjustments *param_adjustments,
 				   const char * suffix, unsigned num_suffix)
diff --git a/gcc/dominance.c b/gcc/dominance.c
index 6a262ce8283..cc63391a39a 100644
--- a/gcc/dominance.c
+++ b/gcc/dominance.c
@@ -1227,7 +1227,7 @@ recompute_dominator (enum cdi_direction dir, basic_block bb)
    from BBS.  */
 
 static void
-prune_bbs_to_update_dominators (vec<basic_block> bbs,
+prune_bbs_to_update_dominators (vec<basic_block> &bbs,
 				bool conservative)
 {
   unsigned i;
@@ -1379,7 +1379,7 @@ determine_dominators_for_sons (struct graph *g, vec<basic_block> bbs,
    a block of BBS in the current dominance tree dominate it.  */
 
 void
-iterate_fix_dominators (enum cdi_direction dir, vec<basic_block> bbs,
+iterate_fix_dominators (enum cdi_direction dir, vec<basic_block> &bbs,
 			bool conservative)
 {
   unsigned i;
diff --git a/gcc/dominance.h b/gcc/dominance.h
index 1a8c248ee98..970da02c594 100644
--- a/gcc/dominance.h
+++ b/gcc/dominance.h
@@ -78,7 +78,7 @@ checking_verify_dominators (cdi_direction dir)
 
 basic_block recompute_dominator (enum cdi_direction, basic_block);
 extern void iterate_fix_dominators (enum cdi_direction,
-				    vec<basic_block> , bool);
+				    vec<basic_block> &, bool);
 extern void add_to_dominance_info (enum cdi_direction, basic_block);
 extern void delete_from_dominance_info (enum cdi_direction, basic_block);
 extern basic_block first_dom_son (enum cdi_direction, basic_block);
diff --git a/gcc/genautomata.c b/gcc/genautomata.c
index 6bbfc684afa..e488c5f28ef 100644
--- a/gcc/genautomata.c
+++ b/gcc/genautomata.c
@@ -6137,7 +6137,7 @@ evaluate_equiv_classes (automaton_t automaton, vec<state_t> *equiv_classes)
 
 /* The function merges equivalent states of AUTOMATON.  */
 static void
-merge_states (automaton_t automaton, vec<state_t> equiv_classes)
+merge_states (automaton_t automaton, const vec<state_t> &equiv_classes)
 {
   state_t curr_state;
   state_t new_state;
diff --git a/gcc/genextract.c b/gcc/genextract.c
index 6fe4a2524fc..3ed2f6846c9 100644
--- a/gcc/genextract.c
+++ b/gcc/genextract.c
@@ -214,7 +214,7 @@ VEC_safe_set_locstr (md_rtx_info *info, vec<locstr> *vp,
 /* Another helper subroutine of walk_rtx: given a vec<char>, convert it
    to a NUL-terminated string in malloc memory.  */
 static char *
-VEC_char_to_string (vec<char> v)
+VEC_char_to_string (const vec<char> &v)
 {
   size_t n = v.length ();
   char *s = XNEWVEC (char, n + 1);
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index 4d476720c9e..dfd793d1f9b 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -1628,8 +1628,9 @@ public:
 
   void gen_kids (FILE *, int, bool, int);
   void gen_kids_1 (FILE *, int, bool, int,
-		   vec<dt_operand *>, vec<dt_operand *>, vec<dt_operand *>,
-		   vec<dt_operand *>, vec<dt_operand *>, vec<dt_node *>);
+		   const vec<dt_operand *> &, const vec<dt_operand *> &,
+		   const vec<dt_operand *> &, const vec<dt_operand *> &,
+		   const vec<dt_operand *> &, const vec<dt_node *> &);
 
   void analyze (sinfo_map_t &);
 };
@@ -2979,12 +2980,12 @@ dt_node::gen_kids (FILE *f, int indent, bool gimple, int depth)
 
 void
 dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
-		     vec<dt_operand *> gimple_exprs,
-		     vec<dt_operand *> generic_exprs,
-		     vec<dt_operand *> fns,
-		     vec<dt_operand *> generic_fns,
-		     vec<dt_operand *> preds,
-		     vec<dt_node *> others)
+		     const vec<dt_operand *> &gimple_exprs,
+		     const vec<dt_operand *> &generic_exprs,
+		     const vec<dt_operand *> &fns,
+		     const vec<dt_operand *> &generic_fns,
+		     const vec<dt_operand *> &preds,
+		     const vec<dt_node *> &others)
 {
   char buf[128];
   char *kid_opname = buf;
@@ -5027,7 +5028,7 @@ parser::parse_pattern ()
    recursively.  */
 
 static void
-walk_captures (operand *op, vec<vec<capture *> > cpts)
+walk_captures (operand *op, vec<vec<capture *> > &cpts)
 {
   if (! op)
     return;
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 632947950e4..02ce068d9cf 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -2654,7 +2654,8 @@ gather_bswap_load_refs (vec<tree> *refs, tree val)
    go after the = _5 store and thus change behavior.  */
 
 static bool
-check_no_overlap (vec<store_immediate_info *> m_store_info, unsigned int i,
+check_no_overlap (const vec<store_immediate_info *> &m_store_info,
+		  unsigned int i,
 		  bool all_integer_cst_p, unsigned int first_order,
 		  unsigned int last_order, unsigned HOST_WIDE_INT start,
 		  unsigned HOST_WIDE_INT end, unsigned int first_earlier,
diff --git a/gcc/gimple.c b/gcc/gimple.c
index f1044e9c630..108daeda43b 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -241,7 +241,7 @@ gimple_build_call_1 (tree fn, unsigned nargs)
    specified in vector ARGS.  */
 
 gcall *
-gimple_build_call_vec (tree fn, vec<tree> args)
+gimple_build_call_vec (tree fn, const vec<tree> &args)
 {
   unsigned i;
   unsigned nargs = args.length ();
@@ -338,7 +338,7 @@ gimple_build_call_internal (enum internal_fn fn, unsigned nargs, ...)
    specified in vector ARGS.  */
 
 gcall *
-gimple_build_call_internal_vec (enum internal_fn fn, vec<tree> args)
+gimple_build_call_internal_vec (enum internal_fn fn, const vec<tree> &args)
 {
   unsigned i, nargs;
   gcall *call;
@@ -802,7 +802,7 @@ gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label)
    ARGS is a vector of labels excluding the default.  */
 
 gswitch *
-gimple_build_switch (tree index, tree default_label, vec<tree> args)
+gimple_build_switch (tree index, tree default_label, const vec<tree> &args)
 {
   unsigned i, nlabels = args.length ();
 
@@ -3049,7 +3049,7 @@ compare_case_labels (const void *p1, const void *p2)
 /* Sort the case labels in LABEL_VEC in place in ascending order.  */
 
 void
-sort_case_labels (vec<tree> label_vec)
+sort_case_labels (vec<tree> &label_vec)
 {
   label_vec.qsort (compare_case_labels);
 }
@@ -3074,7 +3074,7 @@ sort_case_labels (vec<tree> label_vec)
    found or not.  */
 
 void
-preprocess_case_label_vec_for_gimple (vec<tree> labels,
+preprocess_case_label_vec_for_gimple (vec<tree> &labels,
 				      tree index_type,
 				      tree *default_casep)
 {
diff --git a/gcc/gimple.h b/gcc/gimple.h
index e7dc2a45a13..aabf68eaea0 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1516,11 +1516,11 @@ void gimple_init (gimple *g, enum gimple_code code, unsigned num_ops);
 gimple *gimple_alloc (enum gimple_code, unsigned CXX_MEM_STAT_INFO);
 greturn *gimple_build_return (tree);
 void gimple_call_reset_alias_info (gcall *);
-gcall *gimple_build_call_vec (tree, vec<tree> );
+gcall *gimple_build_call_vec (tree, const vec<tree> &);
 gcall *gimple_build_call (tree, unsigned, ...);
 gcall *gimple_build_call_valist (tree, unsigned, va_list);
 gcall *gimple_build_call_internal (enum internal_fn, unsigned, ...);
-gcall *gimple_build_call_internal_vec (enum internal_fn, vec<tree> );
+gcall *gimple_build_call_internal_vec (enum internal_fn, const vec<tree> &);
 gcall *gimple_build_call_from_tree (tree, tree);
 gassign *gimple_build_assign (tree, tree CXX_MEM_STAT_INFO);
 gassign *gimple_build_assign (tree, enum tree_code,
@@ -1547,7 +1547,7 @@ gtry *gimple_build_try (gimple_seq, gimple_seq,
 gimple *gimple_build_wce (gimple_seq);
 gresx *gimple_build_resx (int);
 gswitch *gimple_build_switch_nlabels (unsigned, tree, tree);
-gswitch *gimple_build_switch (tree, tree, vec<tree> );
+gswitch *gimple_build_switch (tree, tree, const vec<tree> &);
 geh_dispatch *gimple_build_eh_dispatch (int);
 gdebug *gimple_build_debug_bind (tree, tree, gimple * CXX_MEM_STAT_INFO);
 gdebug *gimple_build_debug_source_bind (tree, tree, gimple * CXX_MEM_STAT_INFO);
@@ -1626,8 +1626,8 @@ extern bool nonbarrier_call_p (gimple *);
 extern bool infer_nonnull_range (gimple *, tree);
 extern bool infer_nonnull_range_by_dereference (gimple *, tree);
 extern bool infer_nonnull_range_by_attribute (gimple *, tree);
-extern void sort_case_labels (vec<tree>);
-extern void preprocess_case_label_vec_for_gimple (vec<tree>, tree, tree *);
+extern void sort_case_labels (vec<tree> &);
+extern void preprocess_case_label_vec_for_gimple (vec<tree> &, tree, tree *);
 extern void gimple_seq_set_location (gimple_seq, location_t);
 extern void gimple_seq_discard (gimple_seq);
 extern void maybe_remove_unused_call_args (struct function *, gimple *);
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 9c88765d1fb..a166b706b8a 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -891,7 +891,7 @@ static void move_block_after_check (rtx_insn *);
 static void move_succs (vec<edge, va_gc> **, basic_block);
 static void sched_remove_insn (rtx_insn *);
 static void clear_priorities (rtx_insn *, rtx_vec_t *);
-static void calc_priorities (rtx_vec_t);
+static void calc_priorities (const rtx_vec_t &);
 static void add_jump_dependencies (rtx_insn *, rtx_insn *);
 
 #endif /* INSN_SCHEDULING */
@@ -7375,10 +7375,10 @@ haifa_sched_init (void)
     basic_block bb;
     FOR_EACH_BB_FN (bb, cfun)
       bbs.quick_push (bb);
-    sched_init_luids (bbs);
+    sched_init_luids (bbs.to_vec ());
     sched_deps_init (true);
     sched_extend_target ();
-    haifa_init_h_i_d (bbs);
+    haifa_init_h_i_d (bbs.to_vec ());
   }
 
   sched_init_only_bb = haifa_init_only_bb;
@@ -8923,7 +8923,7 @@ clear_priorities (rtx_insn *insn, rtx_vec_t *roots_ptr)
    changed.  ROOTS is a vector of instructions whose priority computation will
    trigger initialization of all cleared priorities.  */
 static void
-calc_priorities (rtx_vec_t roots)
+calc_priorities (const rtx_vec_t &roots)
 {
   int i;
   rtx_insn *insn;
@@ -8988,7 +8988,7 @@ sched_init_insn_luid (rtx_insn *insn)
    The hook common_sched_info->luid_for_non_insn () is used to determine
    if notes, labels, etc. need luids.  */
 void
-sched_init_luids (bb_vec_t bbs)
+sched_init_luids (const bb_vec_t &bbs)
 {
   int i;
   basic_block bb;
@@ -9062,7 +9062,7 @@ init_h_i_d (rtx_insn *insn)
 
 /* Initialize haifa_insn_data for BBS.  */
 void
-haifa_init_h_i_d (bb_vec_t bbs)
+haifa_init_h_i_d (const bb_vec_t &bbs)
 {
   int i;
   basic_block bb;
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 57c18af2bab..ce28ada19fe 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -2946,9 +2946,9 @@ propagate_constants_across_call (struct cgraph_edge *cs)
 
 static tree
 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
-				vec<tree> known_csts,
-				vec<ipa_polymorphic_call_context> known_contexts,
-				vec<ipa_agg_value_set> known_aggs,
+				const vec<tree> &known_csts,
+				const vec<ipa_polymorphic_call_context> &known_contexts,
+				const vec<ipa_agg_value_set> &known_aggs,
 				struct ipa_agg_replacement_value *agg_reps,
 				bool *speculative)
 {
@@ -2985,7 +2985,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
 	    }
 	  if (!t)
 	    {
-	      struct ipa_agg_value_set *agg;
+	      const ipa_agg_value_set *agg;
 	      if (known_aggs.length () > (unsigned int) param_index)
 		agg = &known_aggs[param_index];
 	      else
@@ -3045,7 +3045,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
   if (!t && known_aggs.length () > (unsigned int) param_index
       && !ie->indirect_info->by_ref)
     {
-      struct ipa_agg_value_set *agg = &known_aggs[param_index];
+      const ipa_agg_value_set *agg = &known_aggs[param_index];
       t = ipa_find_agg_cst_for_param (agg,
 				      (unsigned) param_index
 					 < known_csts.length ()
@@ -4267,7 +4267,7 @@ get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
    this kind of adjustment is possible.  */
 
 static bool
-adjust_callers_for_value_intersection (vec<cgraph_edge *> callers,
+adjust_callers_for_value_intersection (vec<cgraph_edge *> &callers,
 				       cgraph_node *node)
 {
   for (unsigned i = 0; i < callers.length (); i++)
@@ -4725,8 +4725,8 @@ self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc,
 
 static void
 find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
-					    vec<tree> known_csts,
-					    vec<cgraph_edge *> callers)
+					    vec<tree> &known_csts,
+					    const vec<cgraph_edge *> &callers)
 {
   ipa_node_params *info = ipa_node_params_sum->get (node);
   int i, count = ipa_get_param_count (info);
@@ -4818,7 +4818,7 @@ static void
 find_more_contexts_for_caller_subset (cgraph_node *node,
 				      vec<ipa_polymorphic_call_context>
 				      *known_contexts,
-				      vec<cgraph_edge *> callers)
+				      const vec<cgraph_edge *> &callers)
 {
   ipa_node_params *info = ipa_node_params_sum->get (node);
   int i, count = ipa_get_param_count (info);
@@ -5179,7 +5179,7 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
 
 static struct ipa_agg_replacement_value *
 find_aggregate_values_for_callers_subset (struct cgraph_node *node,
-					  vec<cgraph_edge *> callers)
+					  const vec<cgraph_edge *> &callers)
 {
   ipa_node_params *dest_info = ipa_node_params_sum->get (node);
   struct ipa_agg_replacement_value *res;
@@ -5413,7 +5413,7 @@ known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts)
 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL.  */
 
 static vec<ipa_polymorphic_call_context>
-copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts)
+copy_useful_known_contexts (const vec<ipa_polymorphic_call_context> &known_contexts)
 {
   if (known_contexts_useful_p (known_contexts))
     return known_contexts.copy ();
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index 95d28757f95..cf80ce3c040 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -3967,8 +3967,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
 		      class ipa_fn_summary *info,
 		      class ipa_node_params *params_summary,
 		      class ipa_fn_summary *callee_info,
-		      vec<int> operand_map,
-		      vec<HOST_WIDE_INT> offset_map,
+		      const vec<int> &operand_map,
+		      const vec<HOST_WIDE_INT> &offset_map,
 		      clause_t possible_truths,
 		      predicate *toplev_predicate)
 {
@@ -4028,8 +4028,8 @@ remap_freqcounting_predicate (class ipa_fn_summary *info,
 			      class ipa_node_params *params_summary,
 			      class ipa_fn_summary *callee_info,
 			      vec<ipa_freqcounting_predicate, va_gc> *v,
-			      vec<int> operand_map,
-			      vec<HOST_WIDE_INT> offset_map,
+			      const vec<int> &operand_map,
+			      const vec<HOST_WIDE_INT> &offset_map,
 			      clause_t possible_truths,
 			      predicate *toplev_predicate)
 
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 9d896beb2ac..413446bcc46 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -1774,7 +1774,7 @@ compute_max_insns (cgraph_node *node, int insns)
 /* Compute badness of all edges in NEW_EDGES and add them to the HEAP.  */
 
 static void
-add_new_edges_to_heap (edge_heap_t *heap, vec<cgraph_edge *> new_edges)
+add_new_edges_to_heap (edge_heap_t *heap, vec<cgraph_edge *> &new_edges)
 {
   while (new_edges.length () > 0)
     {
diff --git a/gcc/ipa-predicate.c b/gcc/ipa-predicate.c
index 6dd749b8ffa..e4b11ec3ae3 100644
--- a/gcc/ipa-predicate.c
+++ b/gcc/ipa-predicate.c
@@ -507,8 +507,8 @@ predicate
 predicate::remap_after_inlining (class ipa_fn_summary *info,
 				 class ipa_node_params *params_summary,
 				 class ipa_fn_summary *callee_info,
-				 vec<int> operand_map,
-				 vec<HOST_WIDE_INT> offset_map,
+				 const vec<int> &operand_map,
+				 const vec<HOST_WIDE_INT> &offset_map,
 				 clause_t possible_truths,
 				 const predicate &toplev_predicate)
 {
diff --git a/gcc/ipa-predicate.h b/gcc/ipa-predicate.h
index 3ed71046c0c..ac52b54aa36 100644
--- a/gcc/ipa-predicate.h
+++ b/gcc/ipa-predicate.h
@@ -243,7 +243,7 @@ public:
   predicate remap_after_inlining (class ipa_fn_summary *,
 		  		  class ipa_node_params *params_summary,
 			          class ipa_fn_summary *,
-				  vec<int>, vec<HOST_WIDE_INT>,
+				  const vec<int> &, const vec<HOST_WIDE_INT> &,
 				  clause_t, const predicate &);
 
   void stream_in (class lto_input_block *);
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index f74d2e17b69..43f46a578c6 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -3562,7 +3562,7 @@ ipa_find_agg_cst_from_init (tree scalar, HOST_WIDE_INT offset, bool by_ref)
    initializer of a constant.  */
 
 tree
-ipa_find_agg_cst_for_param (struct ipa_agg_value_set *agg, tree scalar,
+ipa_find_agg_cst_for_param (const ipa_agg_value_set *agg, tree scalar,
 			    HOST_WIDE_INT offset, bool by_ref,
 			    bool *from_global_constant)
 {
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 3d28a6e8640..d1cd42263f5 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -499,10 +499,10 @@ public:
      get reallocated, the member vectors and the underlying auto_vecs would get
      out of sync.  */
   ipa_call_arg_values (ipa_auto_call_arg_values *aavals)
-    : m_known_vals (aavals->m_known_vals),
-      m_known_contexts (aavals->m_known_contexts),
-      m_known_aggs (aavals->m_known_aggs),
-      m_known_value_ranges (aavals->m_known_value_ranges)
+    : m_known_vals (aavals->m_known_vals.to_vec ()),
+      m_known_contexts (aavals->m_known_contexts.to_vec ()),
+      m_known_aggs (aavals->m_known_aggs.to_vec ()),
+      m_known_value_ranges (aavals->m_known_value_ranges.to_vec ())
   {}
 
   /* If m_known_vals (vector of known "scalar" values) is sufficiantly long,
@@ -1092,7 +1092,7 @@ ipa_bits *ipa_get_ipa_bits_for_value (const widest_int &value,
 void ipa_analyze_node (struct cgraph_node *);
 
 /* Aggregate jump function related functions.  */
-tree ipa_find_agg_cst_for_param (struct ipa_agg_value_set *agg, tree scalar,
+tree ipa_find_agg_cst_for_param (const ipa_agg_value_set *agg, tree scalar,
 				 HOST_WIDE_INT offset, bool by_ref,
 				 bool *from_global_constant = NULL);
 bool ipa_load_from_parm_agg (struct ipa_func_body_info *fbi,
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 4031ce18287..42120656366 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -1672,7 +1672,7 @@ finish_cost_vectors (void)
 
 static vec<ira_loop_tree_node_t>
 ira_loop_tree_body_rev_postorder (ira_loop_tree_node_t loop_node ATTRIBUTE_UNUSED,
-				  vec<ira_loop_tree_node_t> loop_preorder)
+				  const vec<ira_loop_tree_node_t> &loop_preorder)
 {
   vec<ira_loop_tree_node_t> topsort_nodes = vNULL;
   unsigned int n_loop_preorder;
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index 925402877ec..c6dfed80e04 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -835,7 +835,7 @@ md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
    gives the iterator associated with argument I of ONAME.  */
 
 static void
-add_overload_instance (overloaded_name *oname, vec<mapping *> iterators, rtx x)
+add_overload_instance (overloaded_name *oname, vec<mapping *> &iterators, rtx x)
 {
   /* Create the instance.  */
   overloaded_instance *instance = new overloaded_instance;
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 5ed0d6dd6fa..2faf4ac4f97 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2416,9 +2416,9 @@ extern void get_full_rtx_cost (rtx, machine_mode, enum rtx_code, int,
 			       struct full_rtx_costs *);
 extern bool native_encode_rtx (machine_mode, rtx, vec<target_unit> &,
 			       unsigned int, unsigned int);
-extern rtx native_decode_rtx (machine_mode, vec<target_unit>,
+extern rtx native_decode_rtx (machine_mode, const vec<target_unit> &,
 			      unsigned int);
-extern rtx native_decode_vector_rtx (machine_mode, vec<target_unit>,
+extern rtx native_decode_vector_rtx (machine_mode, const vec<target_unit> &,
 				     unsigned int, unsigned int, unsigned int);
 extern poly_uint64 subreg_lsb (const_rtx);
 extern poly_uint64 subreg_size_lsb (poly_uint64, poly_uint64, poly_uint64);
diff --git a/gcc/sched-int.h b/gcc/sched-int.h
index 4727ab28920..868f1eb6c89 100644
--- a/gcc/sched-int.h
+++ b/gcc/sched-int.h
@@ -43,12 +43,12 @@ extern void sched_init_bbs (void);
 
 extern void sched_extend_luids (void);
 extern void sched_init_insn_luid (rtx_insn *);
-extern void sched_init_luids (bb_vec_t);
+extern void sched_init_luids (const bb_vec_t &);
 extern void sched_finish_luids (void);
 
 extern void sched_extend_target (void);
 
-extern void haifa_init_h_i_d (bb_vec_t);
+extern void haifa_init_h_i_d (const bb_vec_t &);
 extern void haifa_finish_h_i_d (void);
 
 /* Hooks that are common to all the schedulers.  */
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index c82101c73a4..113991ddff4 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -6742,7 +6742,7 @@ native_encode_rtx (machine_mode mode, rtx x, vec<target_unit> &bytes,
    Return the vector on success, otherwise return NULL_RTX.  */
 
 rtx
-native_decode_vector_rtx (machine_mode mode, vec<target_unit> bytes,
+native_decode_vector_rtx (machine_mode mode, const vec<target_unit> &bytes,
 			  unsigned int first_byte, unsigned int npatterns,
 			  unsigned int nelts_per_pattern)
 {
@@ -6787,7 +6787,7 @@ native_decode_vector_rtx (machine_mode mode, vec<target_unit> bytes,
    Return the rtx on success, otherwise return NULL_RTX.  */
 
 rtx
-native_decode_rtx (machine_mode mode, vec<target_unit> bytes,
+native_decode_rtx (machine_mode mode, const vec<target_unit> &bytes,
 		   unsigned int first_byte)
 {
   if (VECTOR_MODE_P (mode))
diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
index 666839755d0..d9b9b4c6e84 100644
--- a/gcc/tree-call-cdce.c
+++ b/gcc/tree-call-cdce.c
@@ -761,7 +761,7 @@ get_no_error_domain (enum built_in_function fnc)
    condition are separated by NULL tree in the vector.  */
 
 static void
-gen_shrink_wrap_conditions (gcall *bi_call, vec<gimple *> conds,
+gen_shrink_wrap_conditions (gcall *bi_call, const vec<gimple *> &conds,
                             unsigned int *nconds)
 {
   gcall *call;
@@ -797,7 +797,8 @@ gen_shrink_wrap_conditions (gcall *bi_call, vec<gimple *> conds,
    when it is non-null, it is called while all of the CONDS are true.  */
 
 static void
-shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
+shrink_wrap_one_built_in_call_with_conds (gcall *bi_call,
+					  const vec <gimple *> &conds,
 					  unsigned int nconds,
 					  gcall *bi_newcall = NULL)
 {
@@ -1132,7 +1133,7 @@ use_internal_fn (gcall *call)
    wrapping transformation.  */
 
 static void
-shrink_wrap_conditional_dead_built_in_calls (vec<gcall *> calls)
+shrink_wrap_conditional_dead_built_in_calls (const vec<gcall *> &calls)
 {
   unsigned i = 0;
 
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index b6abd8b8de7..210ac2851a5 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -2643,7 +2643,7 @@ create_intersect_range_checks (class loop *loop, tree *cond_expr,
 
 void
 create_runtime_alias_checks (class loop *loop,
-			     vec<dr_with_seg_len_pair_t> *alias_pairs,
+			     const vec<dr_with_seg_len_pair_t> *alias_pairs,
 			     tree * cond_expr)
 {
   tree part_cond_expr;
@@ -5635,9 +5635,9 @@ compute_affine_dependence (struct data_dependence_relation *ddr,
    is small enough to be handled.  */
 
 bool
-compute_all_dependences (vec<data_reference_p> datarefs,
+compute_all_dependences (const vec<data_reference_p> &datarefs,
 			 vec<ddr_p> *dependence_relations,
-			 vec<loop_p> loop_nest,
+			 const vec<loop_p> &loop_nest,
 			 bool compute_self_and_rr)
 {
   struct data_dependence_relation *ddr;
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index 8001cc54f51..a0ff2a80263 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -551,9 +551,9 @@ extern struct data_dependence_relation *initialize_data_dependence_relation
 extern void compute_affine_dependence (struct data_dependence_relation *,
 				       loop_p);
 extern void compute_self_dependence (struct data_dependence_relation *);
-extern bool compute_all_dependences (vec<data_reference_p> ,
+extern bool compute_all_dependences (const vec<data_reference_p> &,
 				     vec<ddr_p> *,
-				     vec<loop_p>, bool);
+				     const vec<loop_p> &, bool);
 extern tree find_data_references_in_bb (class loop *, basic_block,
                                         vec<data_reference_p> *);
 extern unsigned int dr_alignment (innermost_loop_behavior *);
@@ -578,7 +578,8 @@ extern int data_ref_compare_tree (tree, tree);
 extern void prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *,
 					   poly_uint64);
 extern void create_runtime_alias_checks (class loop *,
-					 vec<dr_with_seg_len_pair_t> *, tree*);
+					 const vec<dr_with_seg_len_pair_t> *,
+					 tree*);
 extern tree dr_direction_indicator (struct data_reference *);
 extern tree dr_zero_step_indicator (struct data_reference *);
 extern bool dr_known_forward_stride_p (struct data_reference *);
@@ -666,7 +667,7 @@ ddr_dependence_level (ddr_p ddr)
 /* Return the index of the variable VAR in the LOOP_NEST array.  */
 
 static inline int
-index_in_loop_nest (int var, vec<loop_p> loop_nest)
+index_in_loop_nest (int var, const vec<loop_p> &loop_nest)
 {
   class loop *loopi;
   int var_index;
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 345488e2a19..49e89cffa1a 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -2208,7 +2208,7 @@ insert_gimplified_predicates (loop_p loop)
    mask if it was created for given SIZE and -1 otherwise.  */
 
 static int
-mask_exists (int size, vec<int> vec)
+mask_exists (int size, const vec<int> &vec)
 {
   unsigned int ix;
   int v;
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 65aa1df4aba..7b715d684f5 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -527,7 +527,7 @@ class loop_distribution
 
   /* Build the vertices of the reduced dependence graph RDG.  Return false
      if that failed.  */
-  bool create_rdg_vertices (struct graph *rdg, vec<gimple *> stmts, loop_p loop);
+  bool create_rdg_vertices (struct graph *rdg, vec<gimple *> &stmts, loop_p loop);
 
   /* Initialize STMTS with all the statements of LOOP.  We use topological
      order to discover all statements.  The order is important because
@@ -646,7 +646,7 @@ class loop_distribution
      statements from STMTS into separate loops.  Returns the number of
      distributed loops.  Set NB_CALLS to number of generated builtin calls.
      Set *DESTROY_P to whether LOOP needs to be destroyed.  */
-  int distribute_loop (class loop *loop, vec<gimple *> stmts,
+  int distribute_loop (class loop *loop, const vec<gimple *> &stmts,
 		       control_dependences *cd, int *nb_calls, bool *destroy_p,
 		       bool only_patterns_p);
 
@@ -699,7 +699,7 @@ bb_top_order_cmp_r (const void *x, const void *y, void *loop)
 }
 
 bool
-loop_distribution::create_rdg_vertices (struct graph *rdg, vec<gimple *> stmts,
+loop_distribution::create_rdg_vertices (struct graph *rdg, vec<gimple *> &stmts,
 					loop_p loop)
 {
   int i;
@@ -1953,7 +1953,7 @@ loop_distribution::rdg_build_partitions (struct graph *rdg,
 /* Dump to FILE the PARTITIONS.  */
 
 static void
-dump_rdg_partitions (FILE *file, vec<partition *> partitions)
+dump_rdg_partitions (FILE *file, const vec<partition *> &partitions)
 {
   int i;
   partition *partition;
@@ -1963,10 +1963,10 @@ dump_rdg_partitions (FILE *file, vec<partition *> partitions)
 }
 
 /* Debug PARTITIONS.  */
-extern void debug_rdg_partitions (vec<partition *> );
+extern void debug_rdg_partitions (const vec<partition *> &);
 
 DEBUG_FUNCTION void
-debug_rdg_partitions (vec<partition *> partitions)
+debug_rdg_partitions (const vec<partition *> &partitions)
 {
   dump_rdg_partitions (stderr, partitions);
 }
@@ -2017,7 +2017,7 @@ number_of_rw_in_partition (struct graph *rdg, partition *partition)
 
 static bool
 partition_contains_all_rw (struct graph *rdg,
-			   vec<partition *> partitions)
+			   const vec<partition *> &partitions)
 {
   int i;
   partition *partition;
@@ -2921,7 +2921,8 @@ loop_distribution::finalize_partitions (class loop *loop,
    Set *DESTROY_P to whether LOOP needs to be destroyed.  */
 
 int
-loop_distribution::distribute_loop (class loop *loop, vec<gimple *> stmts,
+loop_distribution::distribute_loop (class loop *loop,
+		 const vec<gimple *> &stmts,
 		 control_dependences *cd, int *nb_calls, bool *destroy_p,
 		 bool only_patterns_p)
 {
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index fe1baef32a7..bb547572653 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -3713,7 +3713,7 @@ ref_conflicts_with_region (gimple_stmt_iterator gsi, ao_ref *ref,
    reduction results in REDUCTION_STORES.  */
 
 static bool
-oacc_entry_exit_ok_1 (bitmap in_loop_bbs, vec<basic_block> region_bbs,
+oacc_entry_exit_ok_1 (bitmap in_loop_bbs, const vec<basic_block> &region_bbs,
 		      reduction_info_table_type *reduction_list,
 		      bitmap reduction_stores)
 {
@@ -3828,7 +3828,8 @@ oacc_entry_exit_ok_1 (bitmap in_loop_bbs, vec<basic_block> region_bbs,
    if any changes were made.  */
 
 static bool
-oacc_entry_exit_single_gang (bitmap in_loop_bbs, vec<basic_block> region_bbs,
+oacc_entry_exit_single_gang (bitmap in_loop_bbs,
+			     const vec<basic_block> &region_bbs,
 			     bitmap reduction_stores)
 {
   tree gang_pos = NULL_TREE;
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 7de47edbcb3..c778f7e87fd 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -2511,7 +2511,7 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
 
 static void
 hoist_memory_references (class loop *loop, bitmap mem_refs,
-			 vec<edge> exits)
+			 const vec<edge> &exits)
 {
   im_mem_ref *ref;
   unsigned  i;
@@ -2906,7 +2906,7 @@ find_refs_for_sm (class loop *loop, bitmap sm_executed, bitmap refs_to_sm)
 
 static bool
 loop_suitable_for_sm (class loop *loop ATTRIBUTE_UNUSED,
-		      vec<edge> exits)
+		      const vec<edge> &exits)
 {
   unsigned i;
   edge ex;
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index b5add827018..3f9954c88a3 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -3929,7 +3929,7 @@ wide_int_cmp (const void *p1, const void *p2)
    Lookup by binary search.  */
 
 static int
-bound_index (vec<widest_int> bounds, const widest_int &bound)
+bound_index (const vec<widest_int> &bounds, const widest_int &bound)
 {
   unsigned int end = bounds.length ();
   unsigned int begin = 0;
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index d86fe26bd07..a715cddc13d 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3100,7 +3100,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
 
 static bool
 insert_into_preds_of_block (basic_block block, unsigned int exprnum,
-			    vec<pre_expr> avail)
+			    vec<pre_expr> &avail)
 {
   pre_expr expr = expression_for_id (exprnum);
   pre_expr newphi;
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 2dd4435b981..8498cfc7aa8 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -4486,7 +4486,7 @@ get_ops (tree var, enum tree_code code, vec<operand_entry *> *ops,
    stmts.  */
 
 static tree
-update_ops (tree var, enum tree_code code, vec<operand_entry *> ops,
+update_ops (tree var, enum tree_code code, const vec<operand_entry *> &ops,
 	    unsigned int *pidx, class loop *loop)
 {
   gimple *stmt = SSA_NAME_DEF_STMT (var);
@@ -5033,7 +5033,7 @@ remove_visited_stmt_chain (tree var)
    cases, but it is unlikely to be worth it.  */
 
 static void
-swap_ops_for_binary_stmt (vec<operand_entry *> ops,
+swap_ops_for_binary_stmt (const vec<operand_entry *> &ops,
 			  unsigned int opindex, gimple *stmt)
 {
   operand_entry *oe1, *oe2, *oe3;
@@ -5104,7 +5104,8 @@ insert_stmt_before_use (gimple *stmt, gimple *stmt_to_insert)
 
 static tree
 rewrite_expr_tree (gimple *stmt, enum tree_code rhs_code, unsigned int opindex,
-		   vec<operand_entry *> ops, bool changed, bool next_changed)
+		   const vec<operand_entry *> &ops, bool changed,
+		   bool next_changed)
 {
   tree rhs1 = gimple_assign_rhs1 (stmt);
   tree rhs2 = gimple_assign_rhs2 (stmt);
@@ -5326,7 +5327,7 @@ get_reassociation_width (int ops_num, enum tree_code opc,
 
 static void
 rewrite_expr_tree_parallel (gassign *stmt, int width,
-			    vec<operand_entry *> ops)
+			    const vec<operand_entry *> &ops)
 {
   enum tree_code opcode = gimple_assign_rhs_code (stmt);
   int op_num = ops.length ();
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 64e3a707f5c..3451ff1f157 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1040,9 +1040,8 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result)
 bool
 ao_ref_init_from_vn_reference (ao_ref *ref,
 			       alias_set_type set, alias_set_type base_set,
-			       tree type, vec<vn_reference_op_s> ops)
+			       tree type, const vec<vn_reference_op_s> &ops)
 {
-  vn_reference_op_t op;
   unsigned i;
   tree base = NULL_TREE;
   tree *op0_p = &base;
@@ -1061,7 +1060,10 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
     size = wi::to_poly_offset (size_tree);
 
   /* Lower the final access size from the outermost expression.  */
-  op = &ops[0];
+  const_vn_reference_op_t cst_op = &ops[0];
+  /* Cast away constness for the sake of the const-unsafe
+     FOR_EACH_VEC_ELT().  */
+  vn_reference_op_t op = const_cast<vn_reference_op_t>(cst_op);
   size_tree = NULL_TREE;
   if (op->opcode == COMPONENT_REF)
     size_tree = DECL_SIZE (op->op0);
@@ -1092,7 +1094,7 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
 	      && op->op0
 	      && DECL_P (TREE_OPERAND (op->op0, 0)))
 	    {
-	      vn_reference_op_t pop = &ops[i-1];
+	      const_vn_reference_op_t pop = &ops[i-1];
 	      base = TREE_OPERAND (op->op0, 0);
 	      if (known_eq (pop->off, -1))
 		{
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index 6df526c269b..96100596d2e 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -254,7 +254,7 @@ tree vn_nary_op_lookup_pieces (unsigned int, enum tree_code,
 vn_nary_op_t vn_nary_op_insert_pieces (unsigned int, enum tree_code,
 				       tree, tree *, tree, unsigned int);
 bool ao_ref_init_from_vn_reference (ao_ref *, alias_set_type, alias_set_type,
-				    tree, vec<vn_reference_op_s> );
+				    tree, const vec<vn_reference_op_s> &);
 vec<vn_reference_op_s> vn_reference_operands_for_lookup (tree);
 tree vn_reference_lookup_pieces (tree, alias_set_type, alias_set_type, tree,
 				 vec<vn_reference_op_s> ,
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 7163438e23d..e8e35362062 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -3713,8 +3713,8 @@ get_constraint_for_rhs (tree t, vec<ce_s> *results)
    entries in *LHSC.  */
 
 static void
-process_all_all_constraints (vec<ce_s> lhsc,
-			     vec<ce_s> rhsc)
+process_all_all_constraints (const vec<ce_s> &lhsc,
+			     const vec<ce_s> &rhsc)
 {
   struct constraint_expr *lhsp, *rhsp;
   unsigned i, j;
@@ -3814,7 +3814,7 @@ do_structure_copy (tree lhsop, tree rhsop)
 /* Create constraints ID = { rhsc }.  */
 
 static void
-make_constraints_to (unsigned id, vec<ce_s> rhsc)
+make_constraints_to (unsigned id, const vec<ce_s> &rhsc)
 {
   struct constraint_expr *c;
   struct constraint_expr includes;
@@ -4158,7 +4158,7 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
    the LHS point to global and escaped variables.  */
 
 static void
-handle_lhs_call (gcall *stmt, tree lhs, int flags, vec<ce_s> rhsc,
+handle_lhs_call (gcall *stmt, tree lhs, int flags, vec<ce_s> &rhsc,
 		 tree fndecl)
 {
   auto_vec<ce_s> lhsc;
@@ -4609,9 +4609,10 @@ find_func_aliases_for_builtin_call (struct function *fn, gcall *t)
       case BUILT_IN_REALLOC:
 	if (gimple_call_lhs (t))
 	  {
+	    auto_vec<ce_s> rhsc;
 	    handle_lhs_call (t, gimple_call_lhs (t),
 			     gimple_call_return_flags (t) | ERF_NOALIAS,
-			     vNULL, fndecl);
+			     rhsc, fndecl);
 	    get_constraint_for_ptr_offset (gimple_call_lhs (t),
 					   NULL_TREE, &lhsc);
 	    get_constraint_for_ptr_offset (gimple_call_arg (t, 0),
@@ -5682,7 +5683,7 @@ fieldoff_compare (const void *pa, const void *pb)
 
 /* Sort a fieldstack according to the field offset and sizes.  */
 static void
-sort_fieldstack (vec<fieldoff_s> fieldstack)
+sort_fieldstack (vec<fieldoff_s> &fieldstack)
 {
   fieldstack.qsort (fieldoff_compare);
 }
@@ -6092,7 +6093,7 @@ create_function_info_for (tree decl, const char *name, bool add_id,
    FIELDSTACK is assumed to be sorted by offset.  */
 
 static bool
-check_for_overlaps (vec<fieldoff_s> fieldstack)
+check_for_overlaps (const vec<fieldoff_s> &fieldstack)
 {
   fieldoff_s *fo = NULL;
   unsigned int i;
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 579149dfd61..1e929fa002c 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -208,7 +208,7 @@ vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo)
 static void
 vect_check_nonzero_value (loop_vec_info loop_vinfo, tree value)
 {
-  vec<tree> checks = LOOP_VINFO_CHECK_NONZERO (loop_vinfo);
+  vec<tree> checks = LOOP_VINFO_CHECK_NONZERO (loop_vinfo).to_vec ();
   for (unsigned int i = 0; i < checks.length(); ++i)
     if (checks[i] == value)
       return;
@@ -2346,7 +2346,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
   if (do_versioning)
     {
       vec<stmt_vec_info> may_misalign_stmts
-        = LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
+	= LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).to_vec ();
       stmt_vec_info stmt_info;
 
       /* It can now be assumed that the data references in the statements
@@ -3360,7 +3360,8 @@ static void
 vect_check_lower_bound (loop_vec_info loop_vinfo, tree expr, bool unsigned_p,
 			poly_uint64 min_value)
 {
-  vec<vec_lower_bound> lower_bounds = LOOP_VINFO_LOWER_BOUNDS (loop_vinfo);
+  vec<vec_lower_bound> lower_bounds
+    = LOOP_VINFO_LOWER_BOUNDS (loop_vinfo).to_vec ();
   for (unsigned int i = 0; i < lower_bounds.length (); ++i)
     if (operand_equal_p (lower_bounds[i].expr, expr, 0))
       {
@@ -3462,7 +3463,7 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
   typedef pair_hash <tree_operand_hash, tree_operand_hash> tree_pair_hash;
   hash_set <tree_pair_hash> compared_objects;
 
-  vec<ddr_p> may_alias_ddrs = LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
+  vec<ddr_p> may_alias_ddrs = LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo).to_vec ();
   vec<dr_with_seg_len_pair_t> &comp_alias_ddrs
     = LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo);
   vec<vec_object_pair> &check_unequal_addrs
@@ -5335,7 +5336,7 @@ vect_store_lanes_supported (tree vectype, unsigned HOST_WIDE_INT count,
    I4:  6 14 22 30  7 15 23 31.  */
 
 void
-vect_permute_store_chain (vec_info *vinfo, vec<tree> dr_chain,
+vect_permute_store_chain (vec_info *vinfo, vec<tree> &dr_chain,
 			  unsigned int length,
 			  stmt_vec_info stmt_info,
 			  gimple_stmt_iterator *gsi,
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index 012f48bd487..9ff48fec729 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -3168,7 +3168,7 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
                                    tree *cond_expr,
 				   gimple_seq *cond_expr_stmt_list)
 {
-  vec<stmt_vec_info> may_misalign_stmts
+  const vec<stmt_vec_info> &may_misalign_stmts
     = LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
   stmt_vec_info stmt_info;
   int mask = LOOP_VINFO_PTR_MASK (loop_vinfo);
@@ -3259,7 +3259,8 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
 static void
 vect_create_cond_for_unequal_addrs (loop_vec_info loop_vinfo, tree *cond_expr)
 {
-  vec<vec_object_pair> pairs = LOOP_VINFO_CHECK_UNEQUAL_ADDRS (loop_vinfo);
+  const vec<vec_object_pair> &pairs
+    = LOOP_VINFO_CHECK_UNEQUAL_ADDRS (loop_vinfo);
   unsigned int i;
   vec_object_pair *pair;
   FOR_EACH_VEC_ELT (pairs, i, pair)
@@ -3278,7 +3279,8 @@ vect_create_cond_for_unequal_addrs (loop_vec_info loop_vinfo, tree *cond_expr)
 static void
 vect_create_cond_for_lower_bounds (loop_vec_info loop_vinfo, tree *cond_expr)
 {
-  vec<vec_lower_bound> lower_bounds = LOOP_VINFO_LOWER_BOUNDS (loop_vinfo);
+  const vec<vec_lower_bound> &lower_bounds
+    = LOOP_VINFO_LOWER_BOUNDS (loop_vinfo);
   for (unsigned int i = 0; i < lower_bounds.length (); ++i)
     {
       tree expr = lower_bounds[i].expr;
@@ -3320,7 +3322,7 @@ vect_create_cond_for_lower_bounds (loop_vec_info loop_vinfo, tree *cond_expr)
 void
 vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
 {
-  vec<dr_with_seg_len_pair_t> comp_alias_ddrs =
+  const vec<dr_with_seg_len_pair_t> &comp_alias_ddrs =
     LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo);
 
   if (comp_alias_ddrs.is_empty ())
diff --git a/gcc/tree-vect-slp-patterns.c b/gcc/tree-vect-slp-patterns.c
index d536494a1bd..571b29322c5 100644
--- a/gcc/tree-vect-slp-patterns.c
+++ b/gcc/tree-vect-slp-patterns.c
@@ -746,7 +746,7 @@ vect_match_call_complex_mla (slp_tree node, unsigned child,
    of the negate node.  */
 
 static inline bool
-vect_normalize_conj_loc (vec<slp_tree> args, bool *neg_first_p = NULL)
+vect_normalize_conj_loc (vec<slp_tree> &args, bool *neg_first_p = NULL)
 {
   gcc_assert (args.length () == 2);
   bool neg_found = false;
@@ -790,7 +790,8 @@ is_eq_or_top (complex_perm_kinds_t perm, complex_perm_kinds_t kind)
 
 static inline bool
 vect_validate_multiplication (slp_tree_to_load_perm_map_t *perm_cache,
-			     vec<slp_tree> left_op, vec<slp_tree> right_op,
+			      const vec<slp_tree> &left_op,
+			      const vec<slp_tree> &right_op,
 			     bool neg_first, bool *conj_first_operand,
 			     bool fms)
 {
@@ -862,7 +863,8 @@ vect_validate_multiplication (slp_tree_to_load_perm_map_t *perm_cache,
 
 static inline bool
 vect_validate_multiplication (slp_tree_to_load_perm_map_t *perm_cache,
-			     vec<slp_tree> op, complex_perm_kinds_t permKind)
+			      const vec<slp_tree> &op,
+			      complex_perm_kinds_t permKind)
 {
   /* The left node is the more common case, test it first.  */
   if (!is_eq_or_top (linear_loads_p (perm_cache, op[0]), permKind))
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 227d6aa3ee8..9aee024cbf7 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -3316,7 +3316,8 @@ vect_analyze_slp_instance (vec_info *vinfo,
   else if (kind == slp_inst_kind_reduc_group)
     {
       /* Collect reduction statements.  */
-      vec<stmt_vec_info> reductions = as_a <loop_vec_info> (vinfo)->reductions;
+      const vec<stmt_vec_info> &reductions
+	= as_a <loop_vec_info> (vinfo)->reductions;
       scalar_stmts.create (reductions.length ());
       for (i = 0; reductions.iterate (i, &next_info); i++)
 	if (STMT_VINFO_RELEVANT_P (next_info)
@@ -4047,7 +4048,8 @@ vect_make_slp_decision (loop_vec_info loop_vinfo)
 {
   unsigned int i;
   poly_uint64 unrolling_factor = 1;
-  vec<slp_instance> slp_instances = LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
+  const vec<slp_instance> &slp_instances
+    = LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
   slp_instance instance;
   int decided_to_slp = 0;
 
@@ -5814,7 +5816,7 @@ vect_slp_region (vec<basic_block> bbs, vec<data_reference_p> datarefs,
    true if anything in the basic-block was vectorized.  */
 
 static bool
-vect_slp_bbs (vec<basic_block> bbs)
+vect_slp_bbs (const vec<basic_block> &bbs)
 {
   vec<data_reference_p> datarefs = vNULL;
   auto_vec<int> dataref_groups;
@@ -5959,7 +5961,7 @@ vect_slp_function (function *fun)
 
 void
 duplicate_and_interleave (vec_info *vinfo, gimple_seq *seq, tree vector_type,
-			  vec<tree> elts, unsigned int nresults,
+			  vec<tree> &elts, unsigned int nresults,
 			  vec<tree> &results)
 {
   unsigned int nelts = elts.length ();
@@ -6315,7 +6317,7 @@ vect_get_slp_defs (vec_info *,
 
 bool
 vect_transform_slp_perm_load (vec_info *vinfo,
-			      slp_tree node, vec<tree> dr_chain,
+			      slp_tree node, const vec<tree> &dr_chain,
 			      gimple_stmt_iterator *gsi, poly_uint64 vf,
 			      bool analyze_only, unsigned *n_perms,
 			      unsigned int *n_loads, bool dce_chain)
@@ -7329,7 +7331,7 @@ vect_schedule_scc (vec_info *vinfo, slp_tree node, slp_instance instance,
 /* Generate vector code for SLP_INSTANCES in the loop/basic block.  */
 
 void
-vect_schedule_slp (vec_info *vinfo, vec<slp_instance> slp_instances)
+vect_schedule_slp (vec_info *vinfo, const vec<slp_instance> &slp_instances)
 {
   slp_instance instance;
   unsigned int i;
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 4ee11b2041a..7d99199b968 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -4437,7 +4437,7 @@ static void
 vect_create_vectorized_demotion_stmts (vec_info *vinfo, vec<tree> *vec_oprnds,
 				       int multi_step_cvt,
 				       stmt_vec_info stmt_info,
-				       vec<tree> vec_dsts,
+				       vec<tree> &vec_dsts,
 				       gimple_stmt_iterator *gsi,
 				       slp_tree slp_node, enum tree_code code)
 {
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index fa28336d429..688bdaffcb5 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1927,8 +1927,8 @@ extern bool vect_grouped_store_supported (tree, unsigned HOST_WIDE_INT);
 extern bool vect_store_lanes_supported (tree, unsigned HOST_WIDE_INT, bool);
 extern bool vect_grouped_load_supported (tree, bool, unsigned HOST_WIDE_INT);
 extern bool vect_load_lanes_supported (tree, unsigned HOST_WIDE_INT, bool);
-extern void vect_permute_store_chain (vec_info *,
-				      vec<tree> ,unsigned int, stmt_vec_info,
+extern void vect_permute_store_chain (vec_info *, vec<tree> &,
+				      unsigned int, stmt_vec_info,
 				      gimple_stmt_iterator *, vec<tree> *);
 extern tree vect_setup_realignment (vec_info *,
 				    stmt_vec_info, gimple_stmt_iterator *,
@@ -2009,12 +2009,12 @@ extern tree cse_and_gimplify_to_preheader (loop_vec_info, tree);
 extern void vect_slp_init (void);
 extern void vect_slp_fini (void);
 extern void vect_free_slp_instance (slp_instance);
-extern bool vect_transform_slp_perm_load (vec_info *, slp_tree, vec<tree>,
+extern bool vect_transform_slp_perm_load (vec_info *, slp_tree, const vec<tree> &,
 					  gimple_stmt_iterator *, poly_uint64,
 					  bool, unsigned *,
 					  unsigned * = nullptr, bool = false);
 extern bool vect_slp_analyze_operations (vec_info *);
-extern void vect_schedule_slp (vec_info *, vec<slp_instance>);
+extern void vect_schedule_slp (vec_info *, const vec<slp_instance> &);
 extern opt_result vect_analyze_slp (vec_info *, unsigned);
 extern bool vect_make_slp_decision (loop_vec_info);
 extern void vect_detect_hybrid_slp (loop_vec_info);
@@ -2032,7 +2032,7 @@ extern bool can_duplicate_and_interleave_p (vec_info *, unsigned int, tree,
 					    unsigned int * = NULL,
 					    tree * = NULL, tree * = NULL);
 extern void duplicate_and_interleave (vec_info *, gimple_seq *, tree,
-				      vec<tree>, unsigned int, vec<tree> &);
+				      vec<tree> &, unsigned int, vec<tree> &);
 extern int vect_get_place_in_interleaving_chain (stmt_vec_info, stmt_vec_info);
 extern bool vect_update_shared_vectype (stmt_vec_info, tree);
 extern slp_tree vect_create_new_slp_node (unsigned, tree_code);
diff --git a/gcc/tree.c b/gcc/tree.c
index 1aa6e557a04..bead1ac134c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2047,7 +2047,7 @@ make_vector (unsigned log2_npatterns,
    are extracted from V, a vector of CONSTRUCTOR_ELT.  */
 
 tree
-build_vector_from_ctor (tree type, vec<constructor_elt, va_gc> *v)
+build_vector_from_ctor (tree type, const vec<constructor_elt, va_gc> *v)
 {
   if (vec_safe_length (v) == 0)
     return build_zero_cst (type);
@@ -14428,7 +14428,7 @@ test_labels ()
    are given by VALS.  */
 
 static tree
-build_vector (tree type, vec<tree> vals MEM_STAT_DECL)
+build_vector (tree type, const vec<tree> &vals MEM_STAT_DECL)
 {
   gcc_assert (known_eq (vals.length (), TYPE_VECTOR_SUBPARTS (type)));
   tree_vector_builder builder (type, vals.length (), 1);
@@ -14439,7 +14439,7 @@ build_vector (tree type, vec<tree> vals MEM_STAT_DECL)
 /* Check that VECTOR_CST ACTUAL contains the elements in EXPECTED.  */
 
 static void
-check_vector_cst (vec<tree> expected, tree actual)
+check_vector_cst (const vec<tree> &expected, tree actual)
 {
   ASSERT_KNOWN_EQ (expected.length (),
 		   TYPE_VECTOR_SUBPARTS (TREE_TYPE (actual)));
@@ -14452,7 +14452,7 @@ check_vector_cst (vec<tree> expected, tree actual)
    and that its elements match EXPECTED.  */
 
 static void
-check_vector_cst_duplicate (vec<tree> expected, tree actual,
+check_vector_cst_duplicate (const vec<tree> &expected, tree actual,
 			    unsigned int npatterns)
 {
   ASSERT_EQ (npatterns, VECTOR_CST_NPATTERNS (actual));
@@ -14468,7 +14468,7 @@ check_vector_cst_duplicate (vec<tree> expected, tree actual,
    EXPECTED.  */
 
 static void
-check_vector_cst_fill (vec<tree> expected, tree actual,
+check_vector_cst_fill (const vec<tree> &expected, tree actual,
 		       unsigned int npatterns)
 {
   ASSERT_EQ (npatterns, VECTOR_CST_NPATTERNS (actual));
@@ -14483,7 +14483,7 @@ check_vector_cst_fill (vec<tree> expected, tree actual,
    and that its elements match EXPECTED.  */
 
 static void
-check_vector_cst_stepped (vec<tree> expected, tree actual,
+check_vector_cst_stepped (const vec<tree> &expected, tree actual,
 			  unsigned int npatterns)
 {
   ASSERT_EQ (npatterns, VECTOR_CST_NPATTERNS (actual));
diff --git a/gcc/tree.h b/gcc/tree.h
index 060ddee09dd..7043ae2cddc 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4474,7 +4474,7 @@ extern tree build_int_cst (tree, poly_int64);
 extern tree build_int_cstu (tree type, poly_uint64);
 extern tree build_int_cst_type (tree, poly_int64);
 extern tree make_vector (unsigned, unsigned CXX_MEM_STAT_INFO);
-extern tree build_vector_from_ctor (tree, vec<constructor_elt, va_gc> *);
+extern tree build_vector_from_ctor (tree, const vec<constructor_elt, va_gc> *);
 extern tree build_vector_from_val (tree, tree);
 extern tree build_uniform_cst (tree, tree);
 extern tree build_vec_series (tree, tree, tree);
diff --git a/gcc/vec.c b/gcc/vec.c
index f9dbb2cac31..6d767cc12c1 100644
--- a/gcc/vec.c
+++ b/gcc/vec.c
@@ -38,16 +38,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h"
 #endif
 
-/* vNULL is an empty type with a template cast operation that returns
-   a zero-initialized vec<T, A, L> instance.  Use this when you want
-   to assign nil values to new vec instances or pass a nil vector as
-   a function call argument.
-
-   We use this technique because vec<T, A, L> must be PODs (they are
-   stored in unions and passed in vararg functions), this means that
-   they cannot have ctors/dtors.  */
-vnull vNULL;
-
 /* Vector memory usage.  */
 class vec_usage: public mem_usage
 {
@@ -282,6 +272,42 @@ safe_push_range (vec <int>&v, int start, int limit)
     v.safe_push (i);
 }
 
+/* Verify forms of initialization.  */
+
+static void
+test_init ()
+{
+  {
+    vec<int> v1{ };
+    ASSERT_EQ (0, v1.length ());
+
+    vec<int> v2 (v1);
+    ASSERT_EQ (0, v2.length ());
+  }
+
+  {
+    vec<int> v1 = vec<int>();
+    ASSERT_EQ (0, v1.length ());
+
+    vec<int> v2 = v1;
+    ASSERT_EQ (0, v2.length ());
+  }
+
+  {
+    vec<int> v1 (vNULL);
+    ASSERT_EQ (0, v1.length ());
+    v1.safe_push (1);
+
+    vec<int> v2 (v1);
+    ASSERT_EQ (1, v1.length ());
+    v2.safe_push (1);
+
+    ASSERT_EQ (2, v1.length ());
+    ASSERT_EQ (2, v2.length ());
+    v1.release ();
+  }
+}
+
 /* Verify that vec::quick_push works correctly.  */
 
 static void
@@ -547,6 +573,7 @@ test_auto_delete_vec ()
 void
 vec_c_tests ()
 {
+  test_init ();
   test_quick_push ();
   test_safe_push ();
   test_truncate ();
diff --git a/gcc/vec.h b/gcc/vec.h
index 30ef9a69473..fef3dda6a38 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -541,18 +541,16 @@ vec_copy_construct (T *dst, const T *src, unsigned n)
     ::new (static_cast<void*>(dst)) T (*src);
 }
 
-/* Type to provide NULL values for vec<T, A, L>.  This is used to
-   provide nil initializers for vec instances.  Since vec must be
-   a POD, we cannot have proper ctor/dtor for it.  To initialize
-   a vec instance, you can assign it the value vNULL.  This isn't
-   needed for file-scope and function-local static vectors, which
-   are zero-initialized by default.  */
-struct vnull
-{
-  template <typename T, typename A, typename L>
-  CONSTEXPR operator vec<T, A, L> () const { return vec<T, A, L>(); }
-};
-extern vnull vNULL;
+/* Type to provide zero-initialized values for vec<T, A, L>.  This is
+   used to  provide nil initializers for vec instances.  Since vec must
+   be a trivially copyable type that can be copied by memcpy and zeroed
+   out by memset, it must have defaulted default and copy ctor and copy
+   assignment.  To initialize a vec either use value initialization
+   (e.g., vec() or vec v{ };) or assign it the value vNULL.  This isn't
+   needed for file-scope and function-local static vectors, which are
+   zero-initialized by default.  */
+struct vnull { };
+static constexpr vnull vNULL{ };
 
 
 /* Embeddable vector.  These vectors are suitable to be embedded
@@ -1431,10 +1429,34 @@ gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
    As long as we use C++03, we cannot have constructors nor
    destructors in classes that are stored in unions.  */
 
+template<typename T, size_t N = 0>
+class auto_vec;
+
 template<typename T>
 struct vec<T, va_heap, vl_ptr>
 {
 public:
+  /* Default ctors to ensure triviality.  Use value-initialization
+     (e.g., vec() or vec v{ };) or vNULL to create a zero-initialized
+     instance.  */
+  vec () = default;
+  vec (const vec &) = default;
+  /* Initialization from the generic vNULL.  */
+  vec (vnull): m_vec () { }
+  /* Same as default ctor: vec storage must be released manually.  */
+  ~vec () = default;
+
+  /* Defaulted same as copy ctor.  */
+  vec& operator= (const vec &) = default;
+
+  /* Prevent implicit conversion from auto_vec.  Use auto_vec::to_vec()
+     instead.  */
+  template <size_t N>
+  vec (auto_vec<T, N> &) = delete;
+
+  template <size_t N>
+  void operator= (auto_vec<T, N> &) = delete;
+
   /* Memory allocation and deallocation for the embedded vector.
      Needed because we cannot have proper ctors/dtors defined.  */
   void create (unsigned nelems CXX_MEM_STAT_INFO);
@@ -1522,7 +1544,7 @@ public:
    want to ask for internal storage for vectors on the stack because if the
    size of the vector is larger than the internal storage that space is wasted.
    */
-template<typename T, size_t N = 0>
+template<typename T, size_t N /* = 0 */>
 class auto_vec : public vec<T, va_heap>
 {
 public:
@@ -1549,6 +1571,13 @@ public:
     this->release ();
   }
 
+  /* Explicitly convert to the base class.  There is no conversion
+     from a const auto_vec because a copy of the returned vec can
+     be used to modify *THIS.  */
+  vec<T, va_heap> to_vec () {
+    return *static_cast<vec<T, va_heap> *>(this);
+  }
+
 private:
   vec<T, va_heap, vl_embed> m_auto;
   T m_data[MAX (N - 1, 1)];
@@ -1602,6 +1631,13 @@ public:
       return *this;
     }
 
+  /* Explicitly convert to the base class.  There is no conversion
+     from a const auto_vec because a copy of the returned vec can
+     be used to modify *THIS.  */
+  vec<T, va_heap> to_vec () {
+    return *static_cast<vec<T, va_heap> *>(this);
+  }
+
   // You probably don't want to copy a vector, so these are deleted to prevent
   // unintentional use.  If you really need a copy of the vectors contents you
   // can use copy ().
@@ -1781,7 +1817,7 @@ template<typename T>
 inline vec<T, va_heap, vl_ptr>
 vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
 {
-  vec<T, va_heap, vl_ptr> new_vec = vNULL;
+  vec<T, va_heap, vl_ptr> new_vec{ };
   if (length ())
     new_vec.m_vec = m_vec->copy (ALONE_PASS_MEM_STAT);
   return new_vec;

  reply	other threads:[~2021-07-07 14:37 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-26 23:30 [PATCH] " Martin Sebor
2021-04-27  7:58 ` Richard Biener
2021-04-27 13:58   ` Martin Sebor
2021-04-27 14:04     ` Richard Biener
2021-04-27 15:52       ` Martin Sebor
2021-05-03 21:50         ` [PING][PATCH] " Martin Sebor
2021-05-11 20:02           ` [PING 2][PATCH] " Martin Sebor
2021-05-27 19:33             ` [PING 3][PATCH] " Martin Sebor
2021-05-27 20:53         ` [PATCH] " Jason Merrill
2021-06-01 19:56           ` Martin Sebor
2021-06-01 21:38             ` Jason Merrill
2021-06-25 20:51               ` Martin Sebor
2021-06-25 22:11                 ` Jason Merrill
2021-06-25 22:36                   ` Martin Sebor
2021-06-28  8:07                     ` Richard Biener
2021-06-28 18:07                       ` Martin Sebor
2021-06-29 10:58                         ` Richard Biener
2021-06-29 11:34                           ` Martin Jambor
2021-06-30  1:46                           ` Martin Sebor
2021-06-30  8:48                             ` Richard Biener
2021-06-30  9:29                               ` Martin Jambor
2021-07-06 15:06                             ` [PING][PATCH] " Martin Sebor
2021-07-07  7:28                               ` Richard Biener
2021-07-07 14:37                                 ` Martin Sebor [this message]
2021-07-12 11:02                                   ` Richard Biener
2021-07-13 14:08                                     ` Jonathan Wakely
2021-07-13 18:37                                       ` Jason Merrill
2021-07-13 20:02                                         ` Martin Sebor
2021-07-14  3:39                                           ` Jason Merrill
2021-07-14 10:47                                             ` Jonathan Wakely
2021-07-14 14:46                                             ` Martin Sebor
2021-07-14 16:23                                               ` Jason Merrill
2021-07-20 18:34                                                 ` Martin Sebor
2021-07-20 20:08                                                   ` Jason Merrill
2021-07-20 21:52                                                     ` Martin Sebor
2021-07-27 18:56                                                   ` Martin Sebor
2021-07-30 15:06                                                     ` Jason Merrill
2021-08-06  2:07                                                       ` Martin Sebor
2021-08-06  7:52                                                         ` Christophe Lyon
2021-08-06 12:17                                                           ` Christophe Lyon
2021-07-14 14:44                                     ` Martin Sebor
2021-06-29 14:43                         ` [PATCH] " Jason Merrill
2021-06-29 17:18                           ` Martin Sebor
2021-06-30  8:40                             ` Richard Biener
2021-06-30  9:00                               ` Richard Sandiford
2021-06-30 12:01                                 ` Richard Biener
2021-06-28  8:05                 ` Richard Biener
2021-06-29 12:30                 ` Trevor Saunders
2021-06-02  6:55             ` Richard Biener
2021-06-02 16:04               ` Martin Sebor
2021-06-03  8:29                 ` Trevor Saunders
2021-06-07  8:51                   ` Richard Biener
2021-06-07 10:33                     ` Trevor Saunders
2021-06-07 13:33                       ` Richard Biener
2021-06-07 20:34                     ` Martin Sebor
2021-06-08  3:26                       ` Trevor Saunders
2021-06-08  7:19                         ` Richard Biener
2021-06-07 22:17                   ` Martin Sebor
2021-06-08  2:41                     ` Trevor Saunders

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d4dc05d2-af46-876a-a3c3-fb76a0d1d5c0@gmail.com \
    --to=msebor@gmail.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jason@redhat.com \
    --cc=jwakely@redhat.com \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).