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  <ja...@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

Reply via email to