diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index df1dad468df162c282d2306430cd98a537972dae..26a5f7128d2d53dc824a69d103684e63285a05df 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -15199,7 +15199,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) OMP_CLAUSE_LINEAR_STEP (c)); remove = true; } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && reduction_seen == -2) OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; if (remove) diff --git a/gcc/omp-low.c b/gcc/omp-low.c index ed805e2e6d2af97b28eb9c9d82dc2a03775641a9..eec34818f1be107a557b5511c76142ffb5099f82 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -1197,6 +1197,14 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) if (is_oacc_parallel_or_serial (ctx) || is_oacc_kernels (ctx)) ctx->local_reduction_clauses = tree_cons (NULL, c, ctx->local_reduction_clauses); + if ((OMP_CLAUSE_REDUCTION_INSCAN (c) + || OMP_CLAUSE_REDUCTION_TASK (c)) && ctx->allocate_map) + { + tree decl = OMP_CLAUSE_DECL (c); + /* For now. */ + if (ctx->allocate_map->get (decl)) + ctx->allocate_map->remove (decl); + } /* FALLTHRU */ case OMP_CLAUSE_IN_REDUCTION: @@ -4392,13 +4400,17 @@ lower_private_allocate (tree var, tree new_var, tree &allocator, if (allocator) return false; gcc_assert (allocate_ptr == NULL_TREE); - if (ctx->allocate_map && DECL_P (new_var)) + if (ctx->allocate_map + && (DECL_P (new_var) || (TYPE_P (new_var) && size))) if (tree *allocatorp = ctx->allocate_map->get (var)) allocator = *allocatorp; if (allocator == NULL_TREE) return false; if (!is_ref && omp_is_reference (var)) - return false; + { + allocator = NULL_TREE; + return false; + } if (TREE_CODE (allocator) != INTEGER_CST) allocator = build_outer_var_ref (allocator, ctx); @@ -4410,19 +4422,24 @@ lower_private_allocate (tree var, tree new_var, tree &allocator, allocator = var; } - tree ptr_type, align, sz; - if (is_ref) + tree ptr_type, align, sz = size; + if (TYPE_P (new_var)) + { + ptr_type = build_pointer_type (new_var); + align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (new_var)); + } + else if (is_ref) { ptr_type = build_pointer_type (TREE_TYPE (TREE_TYPE (new_var))); align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type))); - sz = size; } else { ptr_type = build_pointer_type (TREE_TYPE (new_var)); align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (new_var)); - sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var)); + if (sz == NULL_TREE) + sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var)); } if (TREE_CODE (sz) != INTEGER_CST) { @@ -4855,7 +4872,23 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, tree type = TREE_TYPE (d); gcc_assert (TREE_CODE (type) == ARRAY_TYPE); tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); + tree sz = v; const char *name = get_name (orig_var); + if (pass != 3 && !TREE_CONSTANT (v)) + { + tree t = maybe_lookup_decl (v, ctx); + if (t) + v = t; + else + v = maybe_lookup_decl_in_outer_ctx (v, ctx); + gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue); + t = fold_build2_loc (clause_loc, PLUS_EXPR, + TREE_TYPE (v), v, + build_int_cst (TREE_TYPE (v), 1)); + sz = fold_build2_loc (clause_loc, MULT_EXPR, + TREE_TYPE (v), t, + TYPE_SIZE_UNIT (TREE_TYPE (type))); + } if (pass == 3) { tree xv = create_tmp_var (ptr_type_node); @@ -4913,6 +4946,13 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, gimplify_assign (cond, x, ilist); x = xv; } + else if (lower_private_allocate (var, type, allocator, + allocate_ptr, ilist, ctx, + true, + TREE_CONSTANT (v) + ? TYPE_SIZE_UNIT (type) + : sz)) + x = allocate_ptr; else if (TREE_CONSTANT (v)) { x = create_tmp_var_raw (type, name); @@ -4924,20 +4964,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, { tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN); - tree t = maybe_lookup_decl (v, ctx); - if (t) - v = t; - else - v = maybe_lookup_decl_in_outer_ctx (v, ctx); - gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue); - t = fold_build2_loc (clause_loc, PLUS_EXPR, - TREE_TYPE (v), v, - build_int_cst (TREE_TYPE (v), 1)); - t = fold_build2_loc (clause_loc, MULT_EXPR, - TREE_TYPE (v), t, - TYPE_SIZE_UNIT (TREE_TYPE (type))); tree al = size_int (TYPE_ALIGN (TREE_TYPE (type))); - x = build_call_expr_loc (clause_loc, atmp, 2, t, al); + x = build_call_expr_loc (clause_loc, atmp, 2, sz, al); } tree ptype = build_pointer_type (TREE_TYPE (type)); @@ -5199,6 +5227,12 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, gimple_seq_add_stmt (dlist, g); gimple_seq_add_stmt (dlist, gimple_build_label (end2)); } + if (allocator) + { + tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE); + g = gimple_build_call (f, 2, allocate_ptr, allocator); + gimple_seq_add_stmt (dlist, g); + } continue; } else if (pass == 2) diff --git a/libgomp/testsuite/libgomp.c-c++-common/allocate-1.c b/libgomp/testsuite/libgomp.c-c++-common/allocate-1.c index 532795f06f146b359cf9aee13df8dc5a3dd53dcb..5dd51b5a2b96504560b9e111af5ec092e8d2137a 100644 --- a/libgomp/testsuite/libgomp.c-c++-common/allocate-1.c +++ b/libgomp/testsuite/libgomp.c-c++-common/allocate-1.c @@ -3,7 +3,7 @@ #include <stdint.h> void -foo (int x, omp_allocator_handle_t h, int fl) +foo (int x, int *p, int *q, int px, omp_allocator_handle_t h, int fl) { int y = 0, r = 0, i, i1, l, l2[4], l3, n = 8; int i2, j2, n2 = 9, l4; @@ -11,7 +11,12 @@ foo (int x, omp_allocator_handle_t h, int fl) int i4, j4, n4 = 11, l6; int i5; int v[x], w[x]; + int r2[4] = { 0, 0, 0, 0 }; int xo = x; + for (i = 0; i < 4; i++) + p[i] = 0; + for (i = 0; i < 3; i++) + q[i] = 0; for (i = 0; i < x; i++) w[i] = i; #pragma omp parallel private (y, v) firstprivate (x) allocate (x, y, v) @@ -117,6 +122,21 @@ foo (int x, omp_allocator_handle_t h, int fl) if ((fl & 2) && (((uintptr_t) &i5) & 63) != 0) abort (); } + #pragma omp for reduction(+:p[2:px], q[:3], r2) allocate(h: p, q, r2) + for (i = 0; i < 32; i++) + { + p[2] += i; + p[3] += 2 * i; + q[0] += 3 * i; + q[2] += 4 * i; + r2[0] += 5 * i; + r2[3] += 6 * i; + /* Can't really rely on alignment of &p[0], the implementation could + allocate the whole array or do what GCC does and allocate only part + of it. */ + if ((fl & 1) && (((uintptr_t) &q[0] | (uintptr_t) &r2[0]) & 63) != 0) + abort (); + } } if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64) abort (); @@ -130,6 +150,10 @@ foo (int x, omp_allocator_handle_t h, int fl) abort (); if (i5 != 19) abort (); + if (p[2] != (32 * 31) / 2 || p[3] != 2 * (32 * 31) / 2 + || q[0] != 3 * (32 * 31) / 2 || q[2] != 4 * (32 * 31) / 2 + || r2[0] != 5 * (32 * 31) / 2 || r2[3] != 6 * (32 * 31) / 2) + abort (); } void @@ -239,15 +263,16 @@ main () { omp_atk_fallback, omp_atv_null_fb } }; omp_allocator_handle_t a = omp_init_allocator (omp_default_mem_space, 2, traits); + int p[4], q[3]; if (a == omp_null_allocator) abort (); omp_set_default_allocator (omp_default_mem_alloc); - foo (42, omp_null_allocator, 0); - foo (42, omp_default_mem_alloc, 0); - foo (42, a, 1); + foo (42, p, q, 2, omp_null_allocator, 0); + foo (42, p, q, 2, omp_default_mem_alloc, 0); + foo (42, p, q, 2, a, 1); omp_set_default_allocator (a); - foo (42, omp_null_allocator, 3); - foo (42, omp_default_mem_alloc, 2); + foo (42, p, q, 2, omp_null_allocator, 3); + foo (42, p, q, 2, omp_default_mem_alloc, 2); bar (42, a); omp_destroy_allocator (a); return 0;