diff mbox

[PR67742] Handle restrict struct fields recursively

Message ID 562F26E2.40906@mentor.com
State New
Headers show

Commit Message

Tom de Vries Oct. 27, 2015, 7:25 a.m. UTC
[ was: Re: [PATCH, 1/2] Add handle_param parameter to 
create_variable_info_for_1 ]

On 26/10/15 17:23, Tom de Vries wrote:
>>  Why does create_variable_info_for_1 only handle
>> the single-field case?  That is, I expected this to be handled by
>> c_v_r_f_1
>> fully.
>>
>
> Yep, that's the goal of PR67742. I've written a patch in an earlier
> version of the patch series that implements that, I'm currently porting
> that patch to this patch series. I'll post asap.

This is the follow-up patch that handles restrict parameters 
recursively, also in struct fields.

Bootstrapped and reg-tested on x86_64.

OK for trunk?

Thanks,
- Tom

Comments

Tom de Vries Oct. 27, 2015, 12:24 p.m. UTC | #1
On 27/10/15 08:25, Tom de Vries wrote:
> @@ -5968,7 +5990,16 @@ intra_create_variable_infos (struct function *fn)
>   	  for (; p; p = vi_next (p))
>   	    {
>   	      if (p->only_restrict_pointers)
> -		make_constraint_from_global_restrict (p, "PARM_RESTRICT");
> +		{
> +		  varinfo_t vi = lookup_restrict_pointed_var (p);
> +		  if (vi != NULL)
> +		    {
> +		      make_constraint_from (p, vi->id);
> +		      make_restrict_var_constraints (vi);
> +		    }
> +		  else
> +		    make_constraint_from_global_restrict (p, "PARM_RESTRICT");
> +		}
>   	      else if (p->may_have_pointers)
>   		make_constraint_from (p, nonlocal_id);
>   	    }
> -- 1.9.1

Thinking it over a bit more, I realized the constraint handling started 
to be messy. I've reworked the patch series to simplify that first.

      1	Simplify constraint handling
      2	Rename make_restrict_var_constraints to make_param_constraints
      3	Add recursion to make_param_constraints
      4	Add handle_param parameter to create_variable_info_for_1
      5	Handle recursive restrict pointer in create_variable_info_for_1
      6	Handle restrict struct fields recursively

Currently doing bootstrap and regtest on x86_64.

I'll repost the patch series in reply to this message.

Thanks,
- Tom
diff mbox

Patch

Handle restrict struct fields recursively

2015-10-26  Tom de Vries  <tom@codesourcery.com>

	* tree-ssa-structalias.c (struct fieldoff): Add restrict_var field.
	(push_fields_onto_fieldstack): Add and handle handle_param parameter.
	(create_variable_info_for_1): Add extra arg to call to
	push_fields_onto_fieldstack.  Add type_contains_placeholder_p test.
	Handle restrict pointer fields.
	(intra_create_variable_infos): Call create_variable_info_for_1 with
	handle_param == true.  Call make_restrict_var_constraints.

	* gcc.dg/tree-ssa/restrict-8.c: New test.
---
 gcc/testsuite/gcc.dg/tree-ssa/restrict-8.c | 17 +++++++++++
 gcc/tree-ssa-structalias.c                 | 47 +++++++++++++++++++++++++-----
 2 files changed, 56 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/restrict-8.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/restrict-8.c b/gcc/testsuite/gcc.dg/tree-ssa/restrict-8.c
new file mode 100644
index 0000000..b0ab164
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/restrict-8.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-fre1" } */
+
+struct s
+{
+  int *__restrict__ *__restrict__ pp;
+};
+
+int
+f (struct s s, int *b)
+{
+  *b = 1;
+  **s.pp = 2;
+  return *b;
+}
+
+/* { dg-final { scan-tree-dump-times "return 1" 1 "fre1" } } */
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 344c3b2..2031175 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -399,6 +399,7 @@  new_var_info (tree t, const char *name)
   return ret;
 }
 
+static varinfo_t create_variable_info_for_1 (tree, const char *, bool);
 
 /* A map mapping call statements to per-stmt variables for uses
    and clobbers specific to the call.  */
@@ -5196,6 +5197,8 @@  struct fieldoff
   unsigned may_have_pointers : 1;
 
   unsigned only_restrict_pointers : 1;
+
+  varinfo_t restrict_var;
 };
 typedef struct fieldoff fieldoff_s;
 
@@ -5290,11 +5293,12 @@  field_must_have_pointers (tree t)
    OFFSET is used to keep track of the offset in this entire
    structure, rather than just the immediately containing structure.
    Returns false if the caller is supposed to handle the field we
-   recursed for.  */
+   recursed for.  If HANDLE_PARAM is set, we're handling part of a function
+   parameter.  */
 
 static bool
 push_fields_onto_fieldstack (tree type, vec<fieldoff_s> *fieldstack,
-			     HOST_WIDE_INT offset)
+			     HOST_WIDE_INT offset, bool handle_param)
 {
   tree field;
   bool empty_p = true;
@@ -5320,7 +5324,7 @@  push_fields_onto_fieldstack (tree type, vec<fieldoff_s> *fieldstack,
 	    || TREE_CODE (field_type) == UNION_TYPE)
 	  push = true;
 	else if (!push_fields_onto_fieldstack
-		    (field_type, fieldstack, offset + foff)
+		    (field_type, fieldstack, offset + foff, handle_param)
 		 && (DECL_SIZE (field)
 		     && !integer_zerop (DECL_SIZE (field))))
 	  /* Empty structures may have actual size, like in C++.  So
@@ -5341,7 +5345,8 @@  push_fields_onto_fieldstack (tree type, vec<fieldoff_s> *fieldstack,
 	    if (!pair
 		&& offset + foff != 0)
 	      {
-		fieldoff_s e = {0, offset + foff, false, false, false, false};
+		fieldoff_s e = {0, offset + foff, false, false, false, false,
+				NULL};
 		pair = fieldstack->safe_push (e);
 	      }
 
@@ -5375,6 +5380,19 @@  push_fields_onto_fieldstack (tree type, vec<fieldoff_s> *fieldstack,
 		  = (!has_unknown_size
 		     && POINTER_TYPE_P (field_type)
 		     && TYPE_RESTRICT (field_type));
+		if (handle_param
+		    && e.only_restrict_pointers
+		    && !type_contains_placeholder_p (TREE_TYPE (field_type)))
+		  {
+		    varinfo_t rvi;
+		    tree heapvar = build_fake_var_decl (TREE_TYPE (field_type));
+		    DECL_EXTERNAL (heapvar) = 1;
+		    rvi = create_variable_info_for_1 (heapvar, "PARM_NOALIAS",
+						      true);
+		    rvi->is_restrict_var = 1;
+		    insert_vi_for_tree (heapvar, rvi);
+		    e.restrict_var = rvi;
+		  }
 		fieldstack->safe_push (e);
 	      }
 	  }
@@ -5679,7 +5697,7 @@  create_variable_info_for_1 (tree decl, const char *name, bool handle_param)
       bool notokay = false;
       unsigned int i;
 
-      push_fields_onto_fieldstack (decl_type, &fieldstack, 0);
+      push_fields_onto_fieldstack (decl_type, &fieldstack, 0, handle_param);
 
       for (i = 0; !notokay && fieldstack.iterate (i, &fo); i++)
 	if (fo->has_unknown_size
@@ -5722,6 +5740,7 @@  create_variable_info_for_1 (tree decl, const char *name, bool handle_param)
 	  && TYPE_RESTRICT (TREE_TYPE (decl)))
 	vi->only_restrict_pointers = 1;
       if (vi->only_restrict_pointers
+	  && !type_contains_placeholder_p (TREE_TYPE (TREE_TYPE (decl)))
 	  && handle_param)
 	{
 	  varinfo_t rvi;
@@ -5769,6 +5788,10 @@  create_variable_info_for_1 (tree decl, const char *name, bool handle_param)
       newvi->fullsize = vi->fullsize;
       newvi->may_have_pointers = fo->may_have_pointers;
       newvi->only_restrict_pointers = fo->only_restrict_pointers;
+      if (handle_param
+	  && newvi->only_restrict_pointers
+	  && fo->restrict_var != NULL)
+	insert_restrict_pointed_var (newvi, fo->restrict_var);
       if (i + 1 < fieldstack.length ())
 	{
 	  varinfo_t tem = new_var_info (decl, name);
@@ -5934,8 +5957,7 @@  intra_create_variable_infos (struct function *fn)
       varinfo_t p = lookup_vi_for_tree (t);
       if (p == NULL)
 	{
-	  p = create_variable_info_for_1 (t, alias_get_name (t),
-					  recursive_restrict_p);
+	  p = create_variable_info_for_1 (t, alias_get_name (t), true);
 	  insert_vi_for_tree (t, p);
 	}
 
@@ -5968,7 +5990,16 @@  intra_create_variable_infos (struct function *fn)
 	  for (; p; p = vi_next (p))
 	    {
 	      if (p->only_restrict_pointers)
-		make_constraint_from_global_restrict (p, "PARM_RESTRICT");
+		{
+		  varinfo_t vi = lookup_restrict_pointed_var (p);
+		  if (vi != NULL)
+		    {
+		      make_constraint_from (p, vi->id);
+		      make_restrict_var_constraints (vi);
+		    }
+		  else
+		    make_constraint_from_global_restrict (p, "PARM_RESTRICT");
+		}
 	      else if (p->may_have_pointers)
 		make_constraint_from (p, nonlocal_id);
 	    }
-- 
1.9.1