diff mbox series

[committed] Fix OpenMP taskloop handling of reference temporaries (PR middle-end/86539)

Message ID 20180717081127.GI7166@tucnak
State New
Headers show
Series [committed] Fix OpenMP taskloop handling of reference temporaries (PR middle-end/86539) | expand

Commit Message

Jakub Jelinek July 17, 2018, 8:11 a.m. UTC
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.


	Jakub
diff mbox series

Patch

--- 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;
+}