ada-tree.h (DECL_RESTRICTED_ALIASING_P): New flag.
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 2 Oct 2015 09:18:34 +0000 (09:18 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 2 Oct 2015 09:18:34 +0000 (09:18 +0000)
* gcc-interface/ada-tree.h (DECL_RESTRICTED_ALIASING_P): New flag.
* gcc-interface/decl.c (gnat_to_gnu_param): For parameters passed by
reference but whose type isn't by-ref and whose mechanism hasn't been
forced to by-ref, set the DECL_RESTRICTED_ALIASING_P flag directly on
them instead of changing their type.
* gcc-interface/trans.c (scan_rhs_r): New helper function.
(independent_iterations_p): New predicate.
(Loop_Statement_to_gnu): For a loop with an iteration scheme, set an
ivdep pragma if the iterations are independent.

From-SVN: r228377

13 files changed:
gcc/ada/ChangeLog
gcc/ada/gcc-interface/ada-tree.h
gcc/ada/gcc-interface/decl.c
gcc/ada/gcc-interface/trans.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/vect15.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/vect15.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/vect16.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/vect16.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/vect17.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/vect17.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/vect18.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/vect18.ads [new file with mode: 0644]

index fb8c6cc91a42d7707569a56b6c928b57b0f84898..0e5d83abddfa914780c1740e1ebe573640144f3a 100644 (file)
@@ -1,3 +1,15 @@
+2015-10-02  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc-interface/ada-tree.h (DECL_RESTRICTED_ALIASING_P): New flag.
+       * gcc-interface/decl.c (gnat_to_gnu_param): For parameters passed by
+       reference but whose type isn't by-ref and whose mechanism hasn't been
+       forced to by-ref, set the DECL_RESTRICTED_ALIASING_P flag directly on
+       them instead of changing their type.
+       * gcc-interface/trans.c (scan_rhs_r): New helper function.
+       (independent_iterations_p): New predicate.
+       (Loop_Statement_to_gnu): For a loop with an iteration scheme, set an
+       ivdep pragma if the iterations are independent.
+
 2015-10-02  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc-interface/trans.c (find_loop_for): Use FOR_EACH_VEC_ELT_REVERSE.
index 5f6d0a1054021117d644a83f77ddbde5359f9812..686445125f132734f0285c8705a208e9cfc3626e 100644 (file)
@@ -369,6 +369,21 @@ do {                                                  \
    in the main unit, i.e. the full declaration is available.  */
 #define DECL_TAFT_TYPE_P(NODE) DECL_LANG_FLAG_0 (TYPE_DECL_CHECK (NODE))
 
+/* Nonzero in a PARM_DECL passed by reference but for which only a restricted
+   form of aliasing is allowed.  The first restriction comes explicitly from
+   the RM 6.2(12) clause: there is no read-after-write dependency between a
+   store based on such a PARM_DECL and a load not based on this PARM_DECL,
+   so stores based on such PARM_DECLs can be sunk past all loads based on
+   a distinct object.  The second restriction can be inferred from the same
+   clause: there is no write-after-write dependency between a store based
+   on such a PARM_DECL and a store based on a distinct such PARM_DECL, as
+   the compiler would be allowed to pass the parameters by copy and the
+   order of assignment to actual parameters after a call is arbitrary as
+   per the RM 6.4.1(17) clause, so stores based on distinct such PARM_DECLs
+   can be swapped.  */
+#define DECL_RESTRICTED_ALIASING_P(NODE) \
+  DECL_LANG_FLAG_0 (PARM_DECL_CHECK (NODE))
+
 /* Nonzero in a DECL if it is always used by reference, i.e. an INDIRECT_REF
    is needed to access the object.  */
 #define DECL_BY_REF_P(NODE) DECL_LANG_FLAG_1 (NODE)
index cb3d7788346eec7e10246dd6868e26f2e5f90c69..ca36ce5180acbf25eca19f2ceb6ce5f4796fd899 100644 (file)
@@ -5585,6 +5585,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
   bool ro_param = in_param && !Address_Taken (gnat_param);
   bool by_return = false, by_component_ptr = false;
   bool by_ref = false;
+  bool restricted_aliasing_p = false;
   tree gnu_param;
 
   /* Copy-return is used only for the first parameter of a valued procedure.
@@ -5675,15 +5676,12 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
                   || (!foreign
                       && default_pass_by_ref (gnu_param_type)))))
     {
+      gnu_param_type = build_reference_type (gnu_param_type);
       /* We take advantage of 6.2(12) by considering that references built for
         parameters whose type isn't by-ref and for which the mechanism hasn't
-        been forced to by-ref are restrict-qualified in the C sense.  */
-      bool restrict_p
+        been forced to by-ref allow only a restricted form of aliasing.  */
+      restricted_aliasing_p
        = !TYPE_IS_BY_REFERENCE_P (gnu_param_type) && mech != By_Reference;
-      gnu_param_type = build_reference_type (gnu_param_type);
-      if (restrict_p)
-       gnu_param_type
-         = change_qualified_type (gnu_param_type, TYPE_QUAL_RESTRICT);
       by_ref = true;
     }
 
@@ -5731,6 +5729,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
   DECL_POINTS_TO_READONLY_P (gnu_param)
     = (ro_param && (by_ref || by_component_ptr));
   DECL_CAN_NEVER_BE_NULL_P (gnu_param) = Can_Never_Be_Null (gnat_param);
+  DECL_RESTRICTED_ALIASING_P (gnu_param) = restricted_aliasing_p;
 
   /* If no Mechanism was specified, indicate what we're using, then
      back-annotate it.  */
index 58e3d322258480450d8fc7d4ed9bf63d61dcb824..1da381b9cc67b139d0fcad87c9698ca52fa88ddb 100644 (file)
@@ -2714,6 +2714,89 @@ can_be_lower_p (tree val1, tree val2)
   return tree_int_cst_lt (val1, val2);
 }
 
+/* Helper function for walk_tree, used by independent_iterations_p below.  */
+
+static tree
+scan_rhs_r (tree *tp, int *walk_subtrees, void *data)
+{
+  bitmap *params = (bitmap *)data;
+  tree t = *tp;
+
+  /* No need to walk into types or decls.  */
+  if (IS_TYPE_OR_DECL_P (t))
+    *walk_subtrees = 0;
+
+  if (TREE_CODE (t) == PARM_DECL && bitmap_bit_p (*params, DECL_UID (t)))
+    return t;
+
+  return NULL_TREE;
+}
+
+/* Return true if STMT_LIST generates independent iterations in a loop.  */
+
+static bool
+independent_iterations_p (tree stmt_list)
+{
+  tree_stmt_iterator tsi;
+  bitmap params = BITMAP_GGC_ALLOC();
+  auto_vec<tree> rhs;
+  tree iter;
+  int i;
+
+  if (TREE_CODE (stmt_list) == BIND_EXPR)
+    stmt_list = BIND_EXPR_BODY (stmt_list);
+
+  /* Scan the list and return false on anything that is not either a check
+     or an assignment to a parameter with restricted aliasing.  */
+  for (tsi = tsi_start (stmt_list); !tsi_end_p (tsi); tsi_next (&tsi))
+    {
+      tree stmt = tsi_stmt (tsi);
+
+      switch (TREE_CODE (stmt))
+       {
+       case COND_EXPR:
+         {
+           if (COND_EXPR_ELSE (stmt))
+             return false;
+           if (TREE_CODE (COND_EXPR_THEN (stmt)) != CALL_EXPR)
+             return false;
+           tree func = get_callee_fndecl (COND_EXPR_THEN (stmt));
+           if (!(func && TREE_THIS_VOLATILE (func)))
+             return false;
+           break;
+         }
+
+       case MODIFY_EXPR:
+         {
+           tree lhs = TREE_OPERAND (stmt, 0);
+           while (handled_component_p (lhs))
+             lhs = TREE_OPERAND (lhs, 0);
+           if (TREE_CODE (lhs) != INDIRECT_REF)
+             return false;
+           lhs = TREE_OPERAND (lhs, 0);
+           if (!(TREE_CODE (lhs) == PARM_DECL
+                 && DECL_RESTRICTED_ALIASING_P (lhs)))
+             return false;
+           bitmap_set_bit (params, DECL_UID (lhs));
+           rhs.safe_push (TREE_OPERAND (stmt, 1));
+           break;
+         }
+
+       default:
+         return false;
+       }
+    }
+
+  /* At this point we know that the list contains only statements that will
+     modify parameters with restricted aliasing.  Check that the statements
+     don't at the time read from these parameters.  */
+  FOR_EACH_VEC_ELT (rhs, i, iter)
+    if (walk_tree_without_duplicates (&iter, scan_rhs_r, &params))
+      return false;
+
+  return true;
+}
+
 /* Subroutine of gnat_to_gnu to translate gnat_node, an N_Loop_Statement,
    to a GCC tree, which is returned.  */
 
@@ -3038,6 +3121,13 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
            add_stmt_with_node_force (rci->invariant_cond, gnat_node);
          }
 
+      /* Second, if loop vectorization is enabled and the iterations of the
+        loop can easily be proved as independent, mark the loop.  */
+      if (optimize
+         && flag_tree_loop_vectorize
+         && independent_iterations_p (LOOP_STMT_BODY (gnu_loop_stmt)))
+       LOOP_STMT_IVDEP (gnu_loop_stmt) = 1;
+
       add_stmt (gnu_loop_stmt);
       gnat_poplevel ();
       gnu_loop_stmt = end_stmt_group ();
index 2d1f34ccce181019bb28d04a826817db63608c82..ae4f5aa4efd2915d1d3dbd787fcb7dd339ad9b79 100644 (file)
@@ -1,3 +1,10 @@
+2015-10-02  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/vect15.ad[sb]: New test.
+       * gnat.dg/vect16.ad[sb]: Likewise.
+       * gnat.dg/vect17.ad[sb]: Likewise.
+       * gnat.dg/vect18.ad[sb]: Likewise.
+
 2015-10-02  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        PR rtl-optimization/67786
diff --git a/gcc/testsuite/gnat.dg/vect15.adb b/gcc/testsuite/gnat.dg/vect15.adb
new file mode 100644 (file)
index 0000000..ad66836
--- /dev/null
@@ -0,0 +1,15 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect15 is
+
+   procedure Add (X, Y : Sarray; R : out Sarray) is
+   begin
+      for I in Sarray'Range loop
+         R(I) := X(I) + Y(I);
+      end loop;
+   end;
+
+end Vect15;
+
+-- { dg-final { scan-tree-dump-not "possible aliasing" "vect"  } }
diff --git a/gcc/testsuite/gnat.dg/vect15.ads b/gcc/testsuite/gnat.dg/vect15.ads
new file mode 100644 (file)
index 0000000..9137512
--- /dev/null
@@ -0,0 +1,8 @@
+package Vect15 is
+
+   type Sarray is array (1 .. 4) of Long_Float;
+   for Sarray'Alignment use 16;
+
+   procedure Add (X, Y : Sarray; R : out Sarray);
+
+end Vect15;
diff --git a/gcc/testsuite/gnat.dg/vect16.adb b/gcc/testsuite/gnat.dg/vect16.adb
new file mode 100644 (file)
index 0000000..99fe320
--- /dev/null
@@ -0,0 +1,16 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect16 is
+
+   procedure Add_Sub (X, Y : Sarray; R,S : out Sarray) is
+   begin
+      for I in Sarray'Range loop
+         R(I) := X(I) + Y(I);
+         S(I) := X(I) - Y(I);
+      end loop;
+   end;
+
+end Vect16;
+
+-- { dg-final { scan-tree-dump-not "possible aliasing" "vect"  } }
diff --git a/gcc/testsuite/gnat.dg/vect16.ads b/gcc/testsuite/gnat.dg/vect16.ads
new file mode 100644 (file)
index 0000000..0192dcc
--- /dev/null
@@ -0,0 +1,8 @@
+package Vect16 is
+
+   type Sarray is array (1 .. 4) of Long_Float;
+   for Sarray'Alignment use 16;
+
+   procedure Add_Sub (X, Y : Sarray; R,S : out Sarray);
+
+end Vect16;
diff --git a/gcc/testsuite/gnat.dg/vect17.adb b/gcc/testsuite/gnat.dg/vect17.adb
new file mode 100644 (file)
index 0000000..f574ea2
--- /dev/null
@@ -0,0 +1,15 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect17 is
+
+   procedure Add (X, Y : aliased Sarray; R : aliased out Sarray) is
+   begin
+      for I in Sarray'Range loop
+         R(I) := X(I) + Y(I);
+      end loop;
+   end;
+
+end Vect17;
+
+-- { dg-final { scan-tree-dump "possible aliasing" "vect"  } }
diff --git a/gcc/testsuite/gnat.dg/vect17.ads b/gcc/testsuite/gnat.dg/vect17.ads
new file mode 100644 (file)
index 0000000..5c26157
--- /dev/null
@@ -0,0 +1,8 @@
+package Vect17 is
+
+   type Sarray is array (1 .. 4) of Long_Float;
+   for Sarray'Alignment use 16;
+
+   procedure Add (X, Y : aliased Sarray; R : aliased out Sarray);
+
+end Vect17;
diff --git a/gcc/testsuite/gnat.dg/vect18.adb b/gcc/testsuite/gnat.dg/vect18.adb
new file mode 100644 (file)
index 0000000..91b1175
--- /dev/null
@@ -0,0 +1,17 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect18 is
+
+   procedure Comp (X, Y : Sarray; R : in out Sarray) is
+      Tmp : Long_Float := R(4);
+   begin
+      for I in 1 .. 3 loop
+         R(I+1) := R(I) + X(I) + Y(I);
+      end loop;
+      R(1) := Tmp + X(4) + Y(4);
+   end;
+
+end Vect18;
+
+-- { dg-final { scan-tree-dump "bad data dependence" "vect"  } }
diff --git a/gcc/testsuite/gnat.dg/vect18.ads b/gcc/testsuite/gnat.dg/vect18.ads
new file mode 100644 (file)
index 0000000..a0ad135
--- /dev/null
@@ -0,0 +1,8 @@
+package Vect18 is
+
+   type Sarray is array (1 .. 4) of Long_Float;
+   for Sarray'Alignment use 16;
+
+   procedure Comp (X, Y : Sarray; R : in out Sarray);
+
+end Vect18;