Fix handling of static chain in modref

Jan Hubicka hubicka@kam.mff.cuni.cz
Wed Nov 24 21:30:47 GMT 2021


Hi,
this patch fixes wrong code issue where modref did not propagate flags
for static chain in ipa_merge_modref_summary_after_inlininig.  It is a
place I missed to update in original patch extending return slot
tracking to static chain.  Unlike return slot we need to propagate flags
here (return slot is write only parameter and does not need it)

Bootstrapped/regtested x86_64-linux, comitted.
gcc/ChangeLog:

2021-11-24  Jan Hubicka  <hubicka@ucw.cz>

	* ipa-modref.c (implicit_eaf_flags_for_edge_and_arg): Break out from...
	(modref_merge_call_site_flags): ... here.
	(ipa_merge_modref_summary_after_inlining): Use it.

gcc/testsuite/ChangeLog:

2021-11-24  Jan Hubicka  <hubicka@ucw.cz>

	* gcc.c-torture/execute/pr103405.c: New test.

diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
index 923ae6c1dd3..c2edc0d28a6 100644
--- a/gcc/ipa-modref.c
+++ b/gcc/ipa-modref.c
@@ -4827,6 +4827,30 @@ modref_propagate_dump_scc (cgraph_node *component_node)
       }
 }
 
+/* Determine EAF flags know for call E with CALLEE_ECF_FLAGS and ARG.  */
+
+int
+implicit_eaf_flags_for_edge_and_arg (cgraph_edge *e, int callee_ecf_flags,
+				     bool ignore_stores, int arg)
+{
+  /* Returning the value is already accounted to at local propagation.  */
+  int implicit_flags = EAF_NOT_RETURNED_DIRECTLY
+		       | EAF_NOT_RETURNED_INDIRECTLY;
+  if (ignore_stores)
+     implicit_flags |= ignore_stores_eaf_flags;
+  if (callee_ecf_flags & ECF_PURE)
+    implicit_flags |= implicit_pure_eaf_flags;
+  if (callee_ecf_flags & (ECF_CONST | ECF_NOVOPS))
+    implicit_flags |= implicit_const_eaf_flags;
+  class fnspec_summary *fnspec_sum = fnspec_summaries->get (e);
+  if (fnspec_sum)
+    {
+      attr_fnspec fnspec (fnspec_sum->fnspec);
+      implicit_flags |= fnspec.arg_eaf_flags (arg);
+    }
+  return implicit_flags;
+}
+
 /* Process escapes in SUM and merge SUMMARY to CUR_SUMMARY
    and SUMMARY_LTO to CUR_SUMMARY_LTO.
    Return true if something changed.  */
@@ -4857,9 +4881,8 @@ modref_merge_call_site_flags (escape_summary *sum,
     {
       int flags = 0;
       int flags_lto = 0;
-      /* Returning the value is already accounted to at local propagation.  */
-      int implicit_flags = EAF_NOT_RETURNED_DIRECTLY
-			   | EAF_NOT_RETURNED_INDIRECTLY;
+      int implicit_flags = implicit_eaf_flags_for_edge_and_arg
+				(e, callee_ecf_flags, ignore_stores, ee->arg);
 
       if (summary && ee->arg < summary->arg_flags.length ())
 	flags = summary->arg_flags[ee->arg];
@@ -4995,6 +5018,7 @@ modref_propagate_flags_in_scc (cgraph_node *component_node)
 	      if (ecf_flags & (ECF_CONST | ECF_NOVOPS)
 		  || !callee_edge->inline_failed)
 		continue;
+
 	      /* Get the callee and its summary.  */
 	      enum availability avail;
 	      callee = callee_edge->callee->function_or_virtual_thunk_symbol
@@ -5081,6 +5105,9 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
   class modref_summary_lto *callee_info_lto
 		 = summaries_lto ? summaries_lto->get (edge->callee) : NULL;
   int flags = flags_from_decl_or_type (edge->callee->decl);
+  /* Combine in outer flags.  */
+  for (cgraph_node *n = edge->caller; n->inlined_to; n = n->callers->caller)
+    flags |= flags_from_decl_or_type (edge->callee->decl);
   bool ignore_stores = ignore_stores_p (edge->caller->decl, flags);
 
   if (!callee_info && to_info)
@@ -5148,10 +5175,11 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
     FOR_EACH_VEC_ELT (sum->esc, i, ee)
       {
 	bool needed = false;
-	/* TODO: We do not have jump functions for return slots, so we
-	   never propagate them to outer function.  */
-	if (ee->parm_index < 0)
-	  continue;
+	int implicit_flags = implicit_eaf_flags_for_edge_and_arg
+				(edge, flags, ignore_stores,
+				 ee->arg);
+	if (!ee->direct)
+	  implicit_flags = deref_flags (implicit_flags, ignore_stores);
 	if (to_info && (int)to_info->arg_flags.length () > ee->parm_index)
 	  {
 	    int flags = callee_info
@@ -5159,11 +5187,14 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
 			? callee_info->arg_flags[ee->arg] : 0;
 	    if (!ee->direct)
 	      flags = deref_flags (flags, ignore_stores);
-	    else if (ignore_stores)
-	      flags |= ignore_stores_eaf_flags;
-	    flags |= ee->min_flags;
-	    to_info->arg_flags[ee->parm_index] &= flags;
-	    if (to_info->arg_flags[ee->parm_index])
+	    flags |= ee->min_flags | implicit_flags;
+	    eaf_flags_t &f = ee->parm_index == MODREF_RETSLOT_PARM
+			     ? to_info->retslot_flags
+			     : ee->parm_index == MODREF_STATIC_CHAIN_PARM
+			     ? to_info->static_chain_flags
+			     : to_info->arg_flags[ee->parm_index];
+	    f &= flags;
+	    if (f)
 	      needed = true;
 	  }
 	if (to_info_lto
@@ -5174,11 +5205,14 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
 			? callee_info_lto->arg_flags[ee->arg] : 0;
 	    if (!ee->direct)
 	      flags = deref_flags (flags, ignore_stores);
-	    else if (ignore_stores)
-	      flags |= ignore_stores_eaf_flags;
-	    flags |= ee->min_flags;
-	    to_info_lto->arg_flags[ee->parm_index] &= flags;
-	    if (to_info_lto->arg_flags[ee->parm_index])
+	    flags |= ee->min_flags | implicit_flags;
+	    eaf_flags_t &f = ee->parm_index == MODREF_RETSLOT_PARM
+			     ? to_info_lto->retslot_flags
+			     : ee->parm_index == MODREF_STATIC_CHAIN_PARM
+			     ? to_info_lto->static_chain_flags
+			     : to_info_lto->arg_flags[ee->parm_index];
+	    f &= flags;
+	    if (f)
 	      needed = true;
 	  }
 	struct escape_map entry = {ee->parm_index, ee->direct};
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr103405.c b/gcc/testsuite/gcc.c-torture/execute/pr103405.c
new file mode 100644
index 00000000000..f6005dc2983
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr103405.c
@@ -0,0 +1,37 @@
+typedef __SIZE_TYPE__ size_t;
+void *malloc(size_t);
+
+static inline int *starter(int a)
+{
+    int *b = malloc(sizeof(int));
+    *b = a;
+    return b;
+}
+
+static inline _Bool equal(int *l, int *r)
+{
+    if (l == 0)
+      __builtin_abort();
+    if (r == 0)
+      __builtin_abort();
+    return *r == *l;
+}
+
+int main(void)
+{
+  int *i;
+  int *j;
+  void check(_Bool a)
+  {
+    _Bool t = equal(i, j);
+    if (a && t) __builtin_abort ();
+    _Bool t1 = equal(i, j);
+    if (!a && !t1) __builtin_abort ();
+  }
+  i = starter(1);
+  j = starter(0);
+  check(1);
+  i = starter(0);
+  check(0);
+
+}


More information about the Gcc-patches mailing list