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 OpenMP taskloop handling of reference temporaries (PR middle-end/86539)


Hi!

The FE guarantees that the iterator type the middle-end sees is either some
integral type, or pointer type.  For taskloop, we need to pass around
(firstprivatize) the b and lb expressions if they aren't simple constants,
but unfortunately for the middle-end reference vs. pointer type differences
are considered useless, so when we gimplify (int *) x where int &x, we can
end up with a temporary that has int & type.  That matters for
firstprivate clause though, int * is firstprivatized by copying the pointer,
while int & is firstprivatized by adding an int temporary, initializing that
temporary from the orig reference and initializing the new private reference
to the address of the int temporary.

So, the following code ensures that the temporary we firstprivatize has the
right type.

Bootstrapped/regtested on x86_64-linux and i686-linux, queued for
backporting.

2018-07-17  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/86539
	* gimplify.c (gimplify_omp_for): Ensure taskloop firstprivatized init
	and cond temporaries don't have reference type if iterator has
	pointer type.  For init use &for_pre_body instead of pre_p if
	for_pre_body is non-empty.

	* testsuite/libgomp.c++/pr86539.C: New test.

--- gcc/gimplify.c.jj	2018-07-10 09:11:24.251062149 +0200
+++ gcc/gimplify.c	2018-07-16 19:10:25.386498090 +0200
@@ -9811,9 +9811,26 @@ gimplify_omp_for (tree *expr_p, gimple_s
 	  t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
 	  if (!is_gimple_constant (TREE_OPERAND (t, 1)))
 	    {
+	      tree type = TREE_TYPE (TREE_OPERAND (t, 0));
 	      TREE_OPERAND (t, 1)
 		= get_initialized_tmp_var (TREE_OPERAND (t, 1),
-					   pre_p, NULL, false);
+					   gimple_seq_empty_p (for_pre_body)
+					   ? pre_p : &for_pre_body, NULL,
+					   false);
+	      /* Reference to pointer conversion is considered useless,
+		 but is significant for firstprivate clause.  Force it
+		 here.  */
+	      if (TREE_CODE (type) == POINTER_TYPE
+		  && (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 1)))
+		      == REFERENCE_TYPE))
+		{
+		  tree v = create_tmp_var (TYPE_MAIN_VARIANT (type));
+		  tree m = build2 (INIT_EXPR, TREE_TYPE (v), v,
+				   TREE_OPERAND (t, 1));
+		  gimplify_and_add (m, gimple_seq_empty_p (for_pre_body)
+				       ? pre_p : &for_pre_body);
+		  TREE_OPERAND (t, 1) = v;
+		}
 	      tree c = build_omp_clause (input_location,
 					 OMP_CLAUSE_FIRSTPRIVATE);
 	      OMP_CLAUSE_DECL (c) = TREE_OPERAND (t, 1);
@@ -9825,11 +9842,26 @@ gimplify_omp_for (tree *expr_p, gimple_s
 	  t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
 	  if (!is_gimple_constant (TREE_OPERAND (t, 1)))
 	    {
+	      tree type = TREE_TYPE (TREE_OPERAND (t, 0));
 	      TREE_OPERAND (t, 1)
 		= get_initialized_tmp_var (TREE_OPERAND (t, 1),
 					   gimple_seq_empty_p (for_pre_body)
 					   ? pre_p : &for_pre_body, NULL,
 					   false);
+	      /* Reference to pointer conversion is considered useless,
+		 but is significant for firstprivate clause.  Force it
+		 here.  */
+	      if (TREE_CODE (type) == POINTER_TYPE
+		  && (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 1)))
+		      == REFERENCE_TYPE))
+		{
+		  tree v = create_tmp_var (TYPE_MAIN_VARIANT (type));
+		  tree m = build2 (INIT_EXPR, TREE_TYPE (v), v,
+				   TREE_OPERAND (t, 1));
+		  gimplify_and_add (m, gimple_seq_empty_p (for_pre_body)
+				       ? pre_p : &for_pre_body);
+		  TREE_OPERAND (t, 1) = v;
+		}
 	      tree c = build_omp_clause (input_location,
 					 OMP_CLAUSE_FIRSTPRIVATE);
 	      OMP_CLAUSE_DECL (c) = TREE_OPERAND (t, 1);
--- libgomp/testsuite/libgomp.c++/pr86539.C.jj	2018-07-16 18:56:40.491472344 +0200
+++ libgomp/testsuite/libgomp.c++/pr86539.C	2018-07-16 18:56:34.068464199 +0200
@@ -0,0 +1,28 @@
+// PR middle-end/86539
+
+int a[384];
+
+__attribute__((noipa)) void
+foo (int &b, int &c)
+{
+  #pragma omp taskloop shared (a) collapse(3)
+  for (int i = 0; i < 1; i++)
+    for (int *p = &b; p < &c; p++)
+      for (int j = 0; j < 1; j++)
+	if (p < &a[128] || p >= &a[256])
+	  __builtin_abort ();
+	else
+	  p[0]++;
+}
+
+int
+main ()
+{
+  #pragma omp parallel
+  #pragma omp single
+    foo (a[128], a[256]);
+  for (int i = 0; i < 384; i++)
+    if (a[i] != (i >= 128 && i < 256))
+      __builtin_abort ();
+  return 0;
+}

	Jakub


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