In gcc 4.0, the restrict qualifier became less useful than in gcc 3.4.
One of the main uses of the restrict qualifier is in scheduling.  The
scheduler currently uses only RTL level aliasing information--we
currently have no mechanism for letting the RTL level query the alias
information at the tree level.  The RTL level aliasing analysis can
only handle restrict when the RTL level can determine whether a memory
reference is made through a restricted pointer.  In gcc 3.4, that
mostly worked.  In gcc 4.0, it often fails.  It fails because the
gimplification process introduces temporary variables, and those
variables do not carry the restrict qualifier.

I mentioned on IRC that I had a simple patch to let the RTL level
aliasing analysis see the underlying decl, the one with the restrict
qualifier.  My original patch was for the 4.0 branch.  This is a
version updated for the 4.1 branch.

I'm not proposing to install it yet.  I would like to hear from people
with access to some standard benchmarks whether it makes any
difference.

This patch isn't quite right, because it doesn't record underlying
declarations for FIELD_DECLs.  I wrote it that way because of concerns
about the different decl structs.  Actually I now suspect that that
was a mistake, and that the patch could handle FIELD_DECLs more or
less as written.  But, whatever.

If the patch helps on benchmarks I will clean it up and check it in.
If it does not help, I will discard it.  Obviously it is only going to
help for benchmarks which use the restrict qualifier.  And it is
obviously a short-term fix: the correct long-term fix is to implement
full support for the restrict qualifier at the tree level and to
expose the tree level alias analysis at RTL level.  I know that both
are being worked on, but that this work is unlikely to be in the 4.1
release.

This patch passes a bootstrap and testsuite run on i686-pc-linux-gnu.

Any comments are appreciated.

Ian

Index: alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/alias.c,v
retrieving revision 1.254
diff -p -u -r1.254 alias.c
--- alias.c     21 Jul 2005 22:34:33 -0000      1.254
+++ alias.c     25 Sep 2005 09:00:23 -0000
@@ -395,9 +395,12 @@ find_base_decl (tree t)
   if (t == 0 || t == error_mark_node || ! POINTER_TYPE_P (TREE_TYPE (t)))
     return 0;
 
-  /* If this is a declaration, return it.  */
+  /* If this is a declaration, return the underlying decl.  */
   if (DECL_P (t))
-    return t;
+    {
+      tree u = DECL_UNDERLYING_NONSCALAR_DECL (t);
+      return u ? u : t;
+    }
 
   /* Handle general expressions.  It would be nice to deal with
      COMPONENT_REFs here.  If we could tell that `a' and `b' were the
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.154
diff -p -u -r2.154 gimplify.c
--- gimplify.c  24 Sep 2005 16:21:43 -0000      2.154
+++ gimplify.c  25 Sep 2005 09:00:23 -0000
@@ -298,6 +298,57 @@ create_artificial_label (void)
   return lab;
 }
 
+/* Subroutine for find_single_nonscalar_decl.  */
+
+struct find_decl
+{
+  int c;
+  tree decl;
+};
+
+static tree
+find_single_nonscalar_decl_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+                              void *data)
+{
+  struct find_decl *pfd = (struct find_decl *) data;
+
+  if (DECL_P (*tp)
+      && !INTEGRAL_TYPE_P (TREE_TYPE (*tp))
+      && !SCALAR_FLOAT_TYPE_P (TREE_TYPE (*tp)))
+    {
+      ++pfd->c;
+      pfd->decl = *tp;
+    }
+
+  return NULL_TREE;
+}
+
+/* Find the single DECL of non-scalar type in the tree T and return
+   it.  If there are zero or more than one such DECLs, return
+   NULL.  */
+
+static tree
+find_single_nonscalar_decl (tree t)
+{
+  struct find_decl fd;
+
+  fd.c = 0;
+  fd.decl = NULL_TREE;
+  walk_tree (&t, find_single_nonscalar_decl_1, &fd, NULL);
+
+  /* We are only interestd in variables.  FIXME: We should probably
+     accept FIELD_DECL here, but it doesn't have the right decl
+     structure.  */
+  if (fd.c != 1
+      || TREE_CODE (fd.decl) == FUNCTION_DECL
+      || TREE_CODE (fd.decl) == LABEL_DECL
+      || TREE_CODE (fd.decl) == FIELD_DECL
+      || TREE_CODE (fd.decl) == TYPE_DECL)
+    return NULL_TREE;
+
+  return fd.decl;
+}
+
 /* Create a new temporary name with PREFIX.  Returns an identifier.  */
 
 static GTY(()) unsigned int tmp_var_id_num;
@@ -470,6 +521,18 @@ internal_get_tmp_var (tree val, tree *pr
 
   t = lookup_tmp_var (val, is_formal);
 
+  if (is_formal)
+    {
+      tree u = find_single_nonscalar_decl (val);
+
+      if (u && DECL_UNDERLYING_NONSCALAR_DECL (u))
+       u = DECL_UNDERLYING_NONSCALAR_DECL (u);
+      gcc_assert (!DECL_UNDERLYING_NONSCALAR_DECL (t)
+                 || DECL_UNDERLYING_NONSCALAR_DECL (t) == u);
+      if (u && lang_hooks.types_compatible_p (TREE_TYPE (u), TREE_TYPE (t)))
+       DECL_UNDERLYING_NONSCALAR_DECL (t) = u;
+    }
+
   if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
     DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
 
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.756
diff -p -u -r1.756 tree.h
--- tree.h      19 Sep 2005 14:54:28 -0000      1.756
+++ tree.h      25 Sep 2005 09:00:24 -0000
@@ -2280,10 +2280,16 @@ extern void decl_value_expr_insert (tree
 /* In VAR_DECL and PARM_DECL nodes, nonzero means declared `register'.  */
 #define DECL_REGISTER(NODE) (DECL_WRTL_CHECK (NODE)->decl_common.decl_flag_0)
 
+/* For a DECL which represents a temporary variable, this is the
+   underlying DECL of nonscalar type, if there is one.  */
+#define DECL_UNDERLYING_NONSCALAR_DECL(NODE) \
+  (DECL_WRTL_CHECK (NODE)->decl_with_rtl.underlying_nonscalar_decl)
+
 struct tree_decl_with_rtl GTY(())
 {
   struct tree_decl_common common;
   rtx rtl;
+  tree underlying_nonscalar_decl;
 };
 
 /* In a FIELD_DECL, this is the field position, counting in bytes, of the

Reply via email to