=== modified file 'gcc/tree-ssa-sccvn.c'
--- gcc/tree-ssa-sccvn.c	2012-08-16 14:27:51 +0000
+++ gcc/tree-ssa-sccvn.c	2012-08-18 16:43:02 +0000
@@ -105,6 +105,7 @@ typedef struct vn_tables_s
   htab_t phis;
   htab_t references;
   struct obstack nary_obstack;
+  long *obstack_start;
   alloc_pool phis_pool;
   alloc_pool references_pool;
 } *vn_tables_t;
@@ -973,16 +974,21 @@ copy_reference_ops_from_call (gimple cal
     }
 }
 
+/* Preallocated vector with sufficient space - see free_scc_vn(). Helps to
+   avoid reallocations and space, since when we VEC_copy() it, only its exact
+   length is duplicated.  */
+
+static VEC(vn_reference_op_s, heap) *prealloc_ref_ops_vec;
+
 /* Create a vector of vn_reference_op_s structures from REF, a
-   REFERENCE_CLASS_P tree.  The vector is not shared. */
+   REFERENCE_CLASS_P tree.  The vector is not shared.  */
 
 static VEC(vn_reference_op_s, heap) *
 create_reference_ops_from_ref (tree ref)
 {
-  VEC (vn_reference_op_s, heap) *result = NULL;
-
-  copy_reference_ops_from_ref (ref, &result);
-  return result;
+  VEC_truncate (vn_reference_op_s, prealloc_ref_ops_vec, 0);
+  copy_reference_ops_from_ref (ref, &prealloc_ref_ops_vec);
+  return VEC_copy (vn_reference_op_s, heap, prealloc_ref_ops_vec);
 }
 
 /* Create a vector of vn_reference_op_s structures from CALL, a
@@ -991,10 +997,9 @@ create_reference_ops_from_ref (tree ref)
 static VEC(vn_reference_op_s, heap) *
 create_reference_ops_from_call (gimple call)
 {
-  VEC (vn_reference_op_s, heap) *result = NULL;
-
-  copy_reference_ops_from_call (call, &result);
-  return result;
+  VEC_truncate (vn_reference_op_s, prealloc_ref_ops_vec, 0);
+  copy_reference_ops_from_call (call, &prealloc_ref_ops_vec);
+  return VEC_copy (vn_reference_op_s, heap, prealloc_ref_ops_vec);
 }
 
 /* Fold *& at position *I_P in a vn_reference_op_s vector *OPS.  Updates
@@ -3610,8 +3615,9 @@ process_scc (VEC (tree, heap) *scc)
       htab_empty (optimistic_info->nary);
       htab_empty (optimistic_info->phis);
       htab_empty (optimistic_info->references);
-      obstack_free (&optimistic_info->nary_obstack, NULL);
-      gcc_obstack_init (&optimistic_info->nary_obstack);
+      /* Quick way to empty the obstack but keep it ready for reuse.  */
+      obstack_free (&optimistic_info->nary_obstack,
+		    optimistic_info->obstack_start);
       empty_alloc_pool (optimistic_info->phis_pool);
       empty_alloc_pool (optimistic_info->references_pool);
       FOR_EACH_VEC_ELT (tree, scc, i, var)
@@ -3796,6 +3802,7 @@ allocate_vn_table (vn_tables_t table)
 				   free_reference);
 
   gcc_obstack_init (&table->nary_obstack);
+  table->obstack_start = XOBNEW (&table->nary_obstack, long);
   table->phis_pool = create_alloc_pool ("VN phis",
 					sizeof (struct vn_phi_s),
 					30);
@@ -3842,7 +3849,6 @@ init_scc_vn (void)
   gcc_obstack_init (&vn_ssa_aux_obstack);
 
   shared_lookup_phiargs = NULL;
-  shared_lookup_references = NULL;
   rpo_numbers = XNEWVEC (int, last_basic_block);
   rpo_numbers_temp = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
   pre_and_rev_post_order_compute (NULL, rpo_numbers_temp, false);
@@ -3887,9 +3893,19 @@ free_scc_vn (void)
   htab_delete (constant_to_value_id);
   BITMAP_FREE (constant_value_ids);
   VEC_free (tree, heap, shared_lookup_phiargs);
-  VEC_free (vn_reference_op_s, heap, shared_lookup_references);
   XDELETEVEC (rpo_numbers);
 
+  /* Keep the shared_lookup_references and prealloc_ref_ops_vec vectors with
+     at most 16 slots.  */
+  VEC_truncate (vn_reference_op_s, shared_lookup_references, 0);
+  if (VEC_space (vn_reference_op_s, shared_lookup_references, 17))
+    VEC_reserve_exact (vn_reference_op_s, heap,
+		       shared_lookup_references, 16);
+  VEC_truncate (vn_reference_op_s, prealloc_ref_ops_vec, 0);
+  if (VEC_space (vn_reference_op_s, prealloc_ref_ops_vec, 17))
+    VEC_reserve_exact (vn_reference_op_s, heap,
+		       prealloc_ref_ops_vec, 16);
+
   for (i = 0; i < num_ssa_names; i++)
     {
       tree name = ssa_name (i);
