diff mbox

[committed] Fix #pragma omp simd with local address taken variables (PR c/59984)

Message ID 20140208092231.GD20378@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Feb. 8, 2014, 9:22 a.m. UTC
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  <jakub@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.


	Jakub
diff mbox

Patch

--- 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" } } */