From c74559df76560e75fd3adc58cccaab99ece47eeb Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Sat, 8 Feb 2014 10:10:14 +0100
Subject: [PATCH] re PR c/59984 (OpenMP pragma makes loop incorrect)

	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.

From-SVN: r207629
---
 gcc/ChangeLog                       |  8 ++++
 gcc/gimplify.c                      |  9 +++-
 gcc/omp-low.c                       |  8 +++-
 gcc/testsuite/ChangeLog             |  3 ++
 gcc/testsuite/gcc.dg/vect/pr59984.c | 64 +++++++++++++++++++++++++++++
 5 files changed, 90 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr59984.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2b9464a3d6df..1c745247e177 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
 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.
+
 	PR middle-end/60092
 	* tree-ssa-ccp.c (surely_varying_stmt_p): Don't return true
 	if TYPE_ATTRIBUTES (gimple_call_fntype ()) contain
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 9c9998dd1939..957a82f107af 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1042,7 +1042,14 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
 	      && (! 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;
 
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 2c35751a957a..f99b2a62264e 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -8946,8 +8946,14 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   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))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 274081191219..053acd0b3d8b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
 2014-02-08  Jakub Jelinek  <jakub@redhat.com>
 
+	PR c/59984
+	* gcc.dg/vect/pr59984.c: New test.
+
 	PR middle-end/60092
 	* gcc.dg/attr-alloc_align-1.c: New test.
 	* gcc.dg/attr-alloc_align-2.c: New test.
diff --git a/gcc/testsuite/gcc.dg/vect/pr59984.c b/gcc/testsuite/gcc.dg/vect/pr59984.c
new file mode 100644
index 000000000000..c772d82f6bba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr59984.c
@@ -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" } } */
-- 
GitLab