This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed] Fix reference handling in #pragma omp simd (PR middle-end/61252)


Hi!

As the testcase shows, in simd regions we need to treat references to
constant sizes more carefully not just if they have
OMP_CLAUSE_REDUCTION_PLACEHOLDER, but also when they don't.

Fixed thusly, committed to trunk and 4.9 after bootstrap/regtest
on x86_64-linux and i686-linux.

2014-05-21  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/61252
	* omp-low.c (handle_simd_reference): New function.
	(lower_rec_input_clauses): Use it.  Defer adding reference
	initialization even for reduction without placeholder if in simd,
	handle it properly later on.

	* testsuite/libgomp.c++/simd-9.C: New test.

--- gcc/omp-low.c.jj	2014-05-14 15:38:13.000000000 +0200
+++ gcc/omp-low.c	2014-05-20 19:14:12.619221073 +0200
@@ -2998,6 +2998,27 @@ lower_rec_simd_input_clauses (tree new_v
   return true;
 }
 
+/* Helper function of lower_rec_input_clauses.  For a reference
+   in simd reduction, add an underlying variable it will reference.  */
+
+static void
+handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
+{
+  tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
+  if (TREE_CONSTANT (z))
+    {
+      const char *name = NULL;
+      if (DECL_NAME (new_vard))
+	name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
+
+      z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
+      gimple_add_tmp_var (z);
+      TREE_ADDRESSABLE (z) = 1;
+      z = build_fold_addr_expr_loc (loc, z);
+      gimplify_assign (new_vard, z, ilist);
+    }
+}
+
 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
    from the receiver (aka child) side and initializers for REFERENCE_TYPE
    private variables.  Initialization statements go in ILIST, while calls
@@ -3189,13 +3210,11 @@ lower_rec_input_clauses (tree clauses, g
 		}
 	      else if (TREE_CONSTANT (x))
 		{
-		  /* For reduction with placeholder in SIMD loop,
-		     defer adding the initialization of the reference,
-		     because if we decide to use SIMD array for it,
-		     the initilization could cause expansion ICE.  */
-		  if (c_kind == OMP_CLAUSE_REDUCTION
-		      && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
-		      && is_simd)
+		  /* For reduction in SIMD loop, defer adding the
+		     initialization of the reference, because if we decide
+		     to use SIMD array for it, the initilization could cause
+		     expansion ICE.  */
+		  if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
 		    x = NULL_TREE;
 		  else
 		    {
@@ -3524,23 +3543,7 @@ lower_rec_input_clauses (tree clauses, g
 		     But if they aren't used, we need to emit the deferred
 		     initialization now.  */
 		  else if (is_reference (var) && is_simd)
-		    {
-		      tree z
-			= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
-		      if (TREE_CONSTANT (z))
-			{
-			  const char *name = NULL;
-			  if (DECL_NAME (var))
-			    name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
-
-			  z = create_tmp_var_raw
-				(TREE_TYPE (TREE_TYPE (new_vard)), name);
-			  gimple_add_tmp_var (z);
-			  TREE_ADDRESSABLE (z) = 1;
-			  z = build_fold_addr_expr_loc (clause_loc, z);
-			  gimplify_assign (new_vard, z, ilist);
-			}
-		    }
+		    handle_simd_reference (clause_loc, new_vard, ilist);
 		  x = lang_hooks.decls.omp_clause_default_ctor
 				(c, new_var, unshare_expr (x));
 		  if (x)
@@ -3573,6 +3576,13 @@ lower_rec_input_clauses (tree clauses, g
 		  if (code == MINUS_EXPR)
 		    code = PLUS_EXPR;
 
+		  tree new_vard = new_var;
+		  if (is_simd && is_reference (var))
+		    {
+		      gcc_assert (TREE_CODE (new_var) == MEM_REF);
+		      new_vard = TREE_OPERAND (new_var, 0);
+		      gcc_assert (DECL_P (new_vard));
+		    }
 		  if (is_simd
 		      && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
 						       idx, lane, ivar, lvar))
@@ -3584,9 +3594,18 @@ lower_rec_input_clauses (tree clauses, g
 		      x = build2 (code, TREE_TYPE (ref), ref, ivar);
 		      ref = build_outer_var_ref (var, ctx);
 		      gimplify_assign (ref, x, &llist[1]);
+
+		      if (new_vard != new_var)
+			{
+			  SET_DECL_VALUE_EXPR (new_vard,
+					       build_fold_addr_expr (lvar));
+			  DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+			}
 		    }
 		  else
 		    {
+		      if (is_reference (var) && is_simd)
+			handle_simd_reference (clause_loc, new_vard, ilist);
 		      gimplify_assign (new_var, x, ilist);
 		      if (is_simd)
 			{
--- libgomp/testsuite/libgomp.c++/simd-9.C.jj	2014-05-20 17:52:37.135319536 +0200
+++ libgomp/testsuite/libgomp.c++/simd-9.C	2014-05-20 17:56:58.511040120 +0200
@@ -0,0 +1,52 @@
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+extern "C" void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+#pragma omp declare reduction (foo:int:omp_out += omp_in) \
+		    initializer (omp_priv = 0)
+
+__attribute__((noinline, noclone)) void
+foo (int &u, int &v)
+{
+  int i;
+  #pragma omp simd aligned(a : 32) reduction(foo:u) reduction(+:v)
+  for (i = 0; i < 1024; i++)
+    {
+      int x = a[i];
+      u += x;
+      v += x;
+    }
+}
+
+__attribute__((noinline, noclone)) void
+bar (int &u, int &v)
+{
+  int i;
+  #pragma omp simd aligned(a : 32) reduction(foo:u) reduction(+:v) \
+		   safelen(1)
+  for (i = 0; i < 1024; i++)
+    {
+      int x = a[i];
+      u += x;
+      v += x;
+    }
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 1024; i++)
+    a[i] = (i & 31) + (i / 128);
+  int u = 0, v = 0;
+  foo (u, v);
+  if (u != 19456 || v != 19456)
+    abort ();
+  u = 0; v = 0;
+  bar (u, v);
+  if (u != 19456 || v != 19456)
+    abort ();
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]