Hi! Last week we've agreed that it is allowed to modify the base of array section used in task_reductions within the taskgroup construct, so we can't reread/recompute the base and bias again, either we'd need to save those at the start of the region, or we can just read it from where we've previously stored it into the array passed to the runtime library.
Tested on x86_64-linux, committed to gomp-5_0-branch. 2018-10-08 Jakub Jelinek <ja...@redhat.com> * omp-low.c (lower_omp_task_reductions): For array section reductions, read address from avar array instead of computing it again at the end of taskgroup, as the base might have changed during the taskgroup. * testsuite/libgomp.c-c++-common/task-reduction-5.c: New test. --- gcc/omp-low.c.jj 2018-09-27 21:13:24.946076732 +0200 +++ gcc/omp-low.c 2018-10-08 17:30:42.147353172 +0200 @@ -6787,7 +6787,7 @@ lower_omp_task_reductions (omp_context * omp_task_reduction_iterate (pass, code, ccode, &c, &decl, &type, &next); c = next) { - tree var = decl, ref, orig_var = decl; + tree var = decl, ref; if (TREE_CODE (decl) == MEM_REF) { var = TREE_OPERAND (var, 0); @@ -6798,7 +6798,6 @@ lower_omp_task_reductions (omp_context * var = TREE_OPERAND (var, 0); else if (TREE_CODE (var) == INDIRECT_REF) var = TREE_OPERAND (var, 0); - orig_var = var; if (is_variable_sized (var)) { gcc_assert (DECL_HAS_VALUE_EXPR_P (var)); @@ -6895,48 +6894,17 @@ lower_omp_task_reductions (omp_context * rcode = PLUS_EXPR; if (TREE_CODE (decl) == MEM_REF) { - tree d = decl; tree type = TREE_TYPE (new_var); tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); tree i = create_tmp_var (TREE_TYPE (v), NULL); tree ptype = build_pointer_type (TREE_TYPE (type)); - tree bias = TREE_OPERAND (d, 1); - d = TREE_OPERAND (d, 0); - if (TREE_CODE (d) == POINTER_PLUS_EXPR) - { - tree b = TREE_OPERAND (d, 1); - b = maybe_lookup_decl_in_outer_ctx (b, ctx); - if (integer_zerop (bias)) - bias = b; - else - { - bias = fold_convert (TREE_TYPE (b), bias); - bias = fold_build2 (PLUS_EXPR, TREE_TYPE (b), b, bias); - } - d = TREE_OPERAND (d, 0); - } - /* For ref build_outer_var_ref already performs this, so - only new_var needs a dereference. */ - if (TREE_CODE (d) == INDIRECT_REF) - ref = build_fold_indirect_ref (ref); - else if (TREE_CODE (d) == ADDR_EXPR) - { - if (orig_var == var) - ref = build_fold_addr_expr (ref); - } - else - gcc_assert (orig_var == var); if (DECL_P (v)) { v = maybe_lookup_decl_in_outer_ctx (v, ctx); gimplify_expr (&v, end, NULL, is_gimple_val, fb_rvalue); } - if (!integer_zerop (bias)) - { - bias = fold_convert (sizetype, bias); - ref = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ref), - ref, bias); - } + ref = build4 (ARRAY_REF, pointer_sized_int_node, avar, + size_int (7 + cnt * 3), NULL_TREE, NULL_TREE); new_var = build_fold_addr_expr (new_var); new_var = fold_convert (ptype, new_var); ref = fold_convert (ptype, ref); --- libgomp/testsuite/libgomp.c-c++-common/task-reduction-5.c.jj 2018-10-08 17:31:11.993853975 +0200 +++ libgomp/testsuite/libgomp.c-c++-common/task-reduction-5.c 2018-10-08 17:22:33.200531039 +0200 @@ -0,0 +1,55 @@ +extern +#ifdef __cplusplus +"C" +#endif +void abort (void); + +int *q; + +void +bar (int *p, int *r, int s) +{ + #pragma omp task in_reduction (*: p[0], q[0], r[s - 1]) + { + *p *= 4; + *q *= 5; + r[s - 1] *= 6; + } +} + +void +foo (int *p, int *r, int s) +{ + int *p2 = p; + #pragma omp taskgroup task_reduction (*: p[0], q[0], r[s]) + { + p = (int *) 0; + s++; + bar (p2, r, s); + r++; + #pragma omp taskwait + #pragma omp task in_reduction (*: p2[0], q[0], r[s - 2]) + { + *p2 *= 2; + *q *= 3; + r[s - 2] *= 7; + } + s++; + p2 = (int *) 0; + q = (int *) 0; + r = (int *) 0; + } +} + +int +main () +{ + int a = 1, b = 1, c[2] = { 1, 0 }; + q = &b; + #pragma omp parallel num_threads (2) + #pragma omp master + foo (&a, &c[0], 0); + if (a != 8 || b != 15 || c[0] != 42 || c[1] != 0) + abort (); + return 0; +} Jakub