Hi!

If a non-static variable declared inside of #pragma {omp,} simd
body is addressable and we would still like to be able to vectorize
it, we must treat it like if it were private variable, i.e. create
omp simd array for it, otherwise all iterations might get address of
the same variable, rather than each SIMD lane it's own copy.

Fixed by the gimplify.c change.  The rest is that I've noticed that
for any #pragma omp for/simd loop we actually duplicated the block
and bind vars and e.g. in the debug info emitted them twice.

As for actual vectorization, if it turns out to be no longer addressable,
we vectorize it just fine, otherwise we are missing vectorization of
statements like:
_27 = GOMP_SIMD_LANE (...);
a_5 = &array[_27];
which can be vectorized as
vec_cst_29 = { &array[0], &array[1], ..., &array[vf - 1] };
(supposedly hoisted before the loop), and then it would be nice
to also handle this specially when passing such an address to
a linear parameter (so that we pass &array[0]).  Note that foo in
the testcase (the one not marked as linear) will be only vectorizable
when we have scatter support in the vectorizer.

I think the vectorizer changes need to wait for 5.0 though.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

2014-02-08  Jakub Jelinek  <ja...@redhat.com>

        PR c/59984
        * gimplify.c (gimplify_bind_expr): In ORT_SIMD region
        mark local addressable non-static vars as GOVD_PRIVATE
        instead of GOVD_LOCAL.
        * omp-low.c (lower_omp_for): Move gimple_bind_vars
        and BLOCK_VARS of gimple_bind_block to new_stmt rather
        than copying them.

        * gcc.dg/vect/pr59984.c: New test.

--- gcc/gimplify.c.jj   2014-02-06 23:06:49.000000000 +0100
+++ gcc/gimplify.c      2014-02-07 16:03:57.095077331 +0100
@@ -1042,7 +1042,14 @@ gimplify_bind_expr (tree *expr_p, gimple
              && (! DECL_SEEN_IN_BIND_EXPR_P (t)
                  || splay_tree_lookup (ctx->variables,
                                        (splay_tree_key) t) == NULL))
-           omp_add_variable (gimplify_omp_ctxp, t, GOVD_LOCAL | GOVD_SEEN);
+           {
+             if (ctx->region_type == ORT_SIMD
+                 && TREE_ADDRESSABLE (t)
+                 && !TREE_STATIC (t))
+               omp_add_variable (ctx, t, GOVD_PRIVATE | GOVD_SEEN);
+             else
+               omp_add_variable (ctx, t, GOVD_LOCAL | GOVD_SEEN);
+           }
 
          DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
 
--- gcc/omp-low.c.jj    2014-02-06 23:06:49.449786481 +0100
+++ gcc/omp-low.c       2014-02-07 21:44:02.902176938 +0100
@@ -9406,8 +9406,14 @@ lower_omp_for (gimple_stmt_iterator *gsi
   if (!gimple_seq_empty_p (omp_for_body)
       && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
     {
-      tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
+      gimple inner_bind = gimple_seq_first_stmt (omp_for_body);
+      tree vars = gimple_bind_vars (inner_bind);
       gimple_bind_append_vars (new_stmt, vars);
+      /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
+        keep them on the inner_bind and it's block.  */
+      gimple_bind_set_vars (inner_bind, NULL_TREE);
+      if (gimple_bind_block (inner_bind))
+       BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
     }
 
   if (gimple_omp_for_combined_into_p (stmt))
--- gcc/testsuite/gcc.dg/vect/pr59984.c.jj      2014-02-07 22:17:20.447769447 
+0100
+++ gcc/testsuite/gcc.dg/vect/pr59984.c 2014-02-07 22:17:40.639785545 +0100
@@ -0,0 +1,64 @@
+/* PR c/59984 */
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#include "tree-vect.h"
+
+#define N 128
+
+int a[N];
+
+#pragma omp declare simd
+__attribute__((noinline)) void
+foo (int in, int *out1, int *out2)
+{
+  *out1 = in * in - 1;
+  *out2 = in * in + 1;
+}
+
+#pragma omp declare simd linear (out1, out2)
+__attribute__((noinline)) void
+bar (int in, int *out1, int *out2)
+{
+  *out1 = in * in - 1;
+  *out2 = in * in + 1;
+}
+
+__attribute__((noinline)) void
+test (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    a[i] = i;
+#pragma omp simd
+  for (i = 0; i < N; i++)
+    {
+      int v1, v2;
+      foo (a[i], &v1, &v2);
+      a[i] = v1 * v2;
+    }
+  for (i = 0; i < N; i++)
+    if (a[i] != i * i * i * i - 1)
+      __builtin_abort ();
+  for (i = 0; i < N; i++)
+    a[i] = i;
+#pragma omp simd
+  for (i = 0; i < N; i++)
+    {
+      int v1, v2;
+      bar (a[i], &v1, &v2);
+      a[i] = v1 * v2;
+    }
+  for (i = 0; i < N; i++)
+    if (a[i] != i * i * i * i - 1)
+      __builtin_abort ();
+}
+
+int
+main ()
+{
+  check_vect ();
+  test ();
+  return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */

        Jakub

Reply via email to