diff mbox series

Avoid carrying around jump functions with no information

Message ID ri6bm5flsz8.fsf@suse.cz
State New
Headers show
Series Avoid carrying around jump functions with no information | expand

Commit Message

Martin Jambor Dec. 20, 2018, 10:43 p.m. UTC
Hi Honza,

the patch below avoids keeping jump functions that do not hold any
interesting value.  For all users such dropped jump function vectors
will then appear as empty ones, which they should handle gracefully
because they already can deal with parameter count mismatches
(especially during LTO).

It also changes the vector allocation to use vec_safe_reserve_exact,
which could save a few bytes here and there too.

I have bootstrapped and tested it on x86-64-linux, LTO bootstrap is in
progress.  If you like it and if it helps with memory use, feel free to
commit it to trunk.

Martin


2018-12-20  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.c (determine_locally_known_aggregate_parts): Return
	true iff any aggregate value has been discovered.
	(ipa_compute_jump_functions_for_edge): Assert that jump_functions
	have not been already calculated, use vec_safe_reserve_exact to
	allocate vectors, only store them if there is a useful value.
---
 gcc/ipa-prop.c | 98 +++++++++++++++++++++++++++++++++++---------------
 1 file changed, 69 insertions(+), 29 deletions(-)
diff mbox series

Patch

diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 05e666e0588..402f8cbd969 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -1541,9 +1541,10 @@  build_agg_jump_func_from_list (struct ipa_known_agg_contents_list *list,
    in ARG is filled in with constant values.  ARG can either be an aggregate
    expression or a pointer to an aggregate.  ARG_TYPE is the type of the
    aggregate.  JFUNC is the jump function into which the constants are
-   subsequently stored.  */
+   subsequently stored.  Return true if any known aggregate value has been
+   discovered.  */
 
-static void
+static bool
 determine_locally_known_aggregate_parts (gcall *call, tree arg,
 					 tree arg_type,
 					 struct ipa_jump_func *jfunc)
@@ -1557,7 +1558,7 @@  determine_locally_known_aggregate_parts (gcall *call, tree arg,
   ao_ref r;
 
   if (PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS) == 0)
-    return;
+    return false;
 
   /* The function operates in three stages.  First, we prepare check_ref, r,
      arg_base and arg_offset based on what is actually passed as an actual
@@ -1571,7 +1572,7 @@  determine_locally_known_aggregate_parts (gcall *call, tree arg,
 	  tree type_size;
           if (!tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (arg_type)))
 	      || !POINTER_TYPE_P (TREE_TYPE (arg)))
-            return;
+            return false;
 	  check_ref = true;
 	  arg_base = arg;
 	  arg_offset = 0;
@@ -1587,17 +1588,17 @@  determine_locally_known_aggregate_parts (gcall *call, tree arg,
 	  arg_base = get_ref_base_and_extent_hwi (arg, &arg_offset,
 						  &arg_size, &reverse);
 	  if (!arg_base)
-	    return;
+	    return false;
 	  if (DECL_P (arg_base))
 	    {
 	      check_ref = false;
 	      ao_ref_init (&r, arg_base);
 	    }
 	  else
-	    return;
+	    return false;
 	}
       else
-	return;
+	return false;
     }
   else
     {
@@ -1610,7 +1611,7 @@  determine_locally_known_aggregate_parts (gcall *call, tree arg,
       arg_base = get_ref_base_and_extent_hwi (arg, &arg_offset,
 					      &arg_size, &reverse);
       if (!arg_base)
-	return;
+	return false;
 
       ao_ref_init (&r, arg);
     }
@@ -1697,7 +1698,9 @@  determine_locally_known_aggregate_parts (gcall *call, tree arg,
     {
       jfunc->agg.by_ref = by_ref;
       build_agg_jump_func_from_list (list, const_count, arg_offset, jfunc);
+      return true;
     }
+  return false;
 }
 
 /* Return the Ith param type of callee associated with call graph
@@ -1827,18 +1830,24 @@  ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
   struct ipa_edge_args *args = IPA_EDGE_REF (cs);
   gcall *call = cs->call_stmt;
   int n, arg_num = gimple_call_num_args (call);
+  bool useful_value = false;
   bool useful_context = false;
 
-  if (arg_num == 0 || args->jump_functions)
+  if (arg_num == 0
+      || gimple_call_internal_p (call)
+      || ipa_func_spec_opts_forbid_analysis_p (cs->caller))
     return;
-  vec_safe_grow_cleared (args->jump_functions, arg_num);
-  if (flag_devirtualize)
-    vec_safe_grow_cleared (args->polymorphic_call_contexts, arg_num);
+  gcc_checking_assert (!args->jump_functions
+		       && !args->polymorphic_call_contexts);
 
-  if (gimple_call_internal_p (call))
-    return;
-  if (ipa_func_spec_opts_forbid_analysis_p (cs->caller))
-    return;
+  vec_safe_reserve_exact (args->jump_functions, arg_num);
+  args->jump_functions->quick_grow_cleared (arg_num);
+
+  if (flag_devirtualize)
+    {
+      vec_safe_reserve_exact (args->polymorphic_call_contexts, arg_num);
+      vec_safe_grow_cleared (args->polymorphic_call_contexts, arg_num);
+    }
 
   for (n = 0; n < arg_num; n++)
     {
@@ -1873,6 +1882,7 @@  ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
 	    {
 	      tree z = build_int_cst (TREE_TYPE (arg), 0);
 	      ipa_set_jfunc_vr (jfunc, VR_ANTI_RANGE, z, z);
+	      useful_value = true;
 	    }
 	  else
 	    gcc_assert (!jfunc->m_vr);
@@ -1893,7 +1903,10 @@  ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
 	      extract_range_from_unary_expr (&resvr, NOP_EXPR, param_type,
 					     &tmpvr, TREE_TYPE (arg));
 	      if (!resvr.undefined_p () && !resvr.varying_p ())
-		ipa_set_jfunc_vr (jfunc, &resvr);
+		{
+		  ipa_set_jfunc_vr (jfunc, &resvr);
+		  useful_value = true;
+		}
 	      else
 		gcc_assert (!jfunc->m_vr);
 	    }
@@ -1905,11 +1918,20 @@  ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
 	  && (TREE_CODE (arg) == SSA_NAME || TREE_CODE (arg) == INTEGER_CST))
 	{
 	  if (TREE_CODE (arg) == SSA_NAME)
-	    ipa_set_jfunc_bits (jfunc, 0,
-				widest_int::from (get_nonzero_bits (arg),
-						  TYPE_SIGN (TREE_TYPE (arg))));
+	    {
+	      widest_int nonzero_bits
+		= widest_int::from (get_nonzero_bits (arg),
+				    TYPE_SIGN (TREE_TYPE (arg)));
+	      ipa_set_jfunc_bits (jfunc, 0, nonzero_bits);
+	      if (SSA_NAME_RANGE_INFO (arg)
+		  && nonzero_bits != -1)
+		useful_value = true;
+	    }
 	  else
-	    ipa_set_jfunc_bits (jfunc, wi::to_widest (arg), 0);
+	    {
+	      ipa_set_jfunc_bits (jfunc, wi::to_widest (arg), 0);
+	      useful_value = true;
+	    }
 	}
       else if (POINTER_TYPE_P (TREE_TYPE (arg)))
 	{
@@ -1917,6 +1939,8 @@  ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
 	  unsigned align;
 
 	  get_pointer_alignment_1 (arg, &align, &bitpos);
+	  if (align != BITS_PER_UNIT)
+	    useful_value = true;
 	  widest_int mask = wi::bit_and_not
 	    (wi::mask<widest_int> (TYPE_PRECISION (TREE_TYPE (arg)), false),
 	     align / BITS_PER_UNIT - 1);
@@ -1930,7 +1954,10 @@  ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
 	  || (VAR_P (arg)
 	      && is_global_var (arg)
 	      && TREE_READONLY (arg)))
-	ipa_set_jf_constant (jfunc, arg, cs);
+	{
+	  ipa_set_jf_constant (jfunc, arg, cs);
+	  useful_value = true;
+	}
       else if (!is_gimple_reg_type (TREE_TYPE (arg))
 	       && TREE_CODE (arg) == PARM_DECL)
 	{
@@ -1943,6 +1970,7 @@  ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
 	  if (parm_preserved_before_stmt_p (fbi, index, call, arg))
 	    {
 	      ipa_set_jf_simple_pass_through (jfunc, index, false);
+	      useful_value = true;
 	      continue;
 	    }
 	}
@@ -1956,6 +1984,7 @@  ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
 		  bool agg_p;
 		  agg_p = parm_ref_data_pass_through_p (fbi, index, call, arg);
 		  ipa_set_jf_simple_pass_through (jfunc, index, agg_p);
+		  useful_value = true;
 		}
 	    }
 	  else
@@ -1969,14 +1998,17 @@  ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
 						    call,
 						    as_a <gphi *> (stmt));
 	    }
+	  if (jfunc->type != IPA_JF_UNKNOWN)
+	    useful_value = true;
 	}
 
-      /* If ARG is pointer, we can not use its type to determine the type of aggregate
-	 passed (because type conversions are ignored in gimple).  Usually we can
-	 safely get type from function declaration, but in case of K&R prototypes or
-	 variadic functions we can try our luck with type of the pointer passed.
-	 TODO: Since we look for actual initialization of the memory object, we may better
-	 work out the type based on the memory stores we find.  */
+      /* If ARG is pointer, we can not use its type to determine the type of
+	 aggregate passed (because type conversions are ignored in gimple).
+	 Usually we can safely get type from function declaration, but in case
+	 of K&R prototypes or variadic functions we can try our luck with type
+	 of the pointer passed.
+	 TODO: Since we look for actual initialization of the memory object, we
+	 may better work out the type based on the memory stores we find.  */
       if (!param_type)
 	param_type = TREE_TYPE (arg);
 
@@ -1986,8 +2018,16 @@  ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
 	      || !ipa_get_jf_ancestor_agg_preserved (jfunc))
 	  && (AGGREGATE_TYPE_P (TREE_TYPE (arg))
 	      || POINTER_TYPE_P (param_type)))
-	determine_locally_known_aggregate_parts (call, arg, param_type, jfunc);
+	{
+	  if (determine_locally_known_aggregate_parts (call, arg, param_type,
+						       jfunc))
+	    useful_value = true;
+	}
     }
+
+  if (!useful_value)
+    vec_free (args->jump_functions);
+
   if (!useful_context)
     vec_free (args->polymorphic_call_contexts);
 }