diff options
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 476 |
1 files changed, 420 insertions, 56 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 29f385c..46f726a 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -231,6 +231,8 @@ struct gimplify_omp_ctx bool target_firstprivatize_array_bases; bool add_safelen1; bool order_concurrent; + bool has_depend; + bool in_for_exprs; int defaultmap[4]; }; @@ -780,7 +782,7 @@ gimple_add_tmp_var (tree tmp) if (gimplify_omp_ctxp) { struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; - int flag = GOVD_LOCAL; + int flag = GOVD_LOCAL | GOVD_SEEN; while (ctx && (ctx->region_type == ORT_WORKSHARE || ctx->region_type == ORT_TASKGROUP @@ -793,14 +795,16 @@ gimple_add_tmp_var (tree tmp) { if (TREE_CODE (DECL_SIZE_UNIT (tmp)) != INTEGER_CST) ctx->add_safelen1 = true; - else + else if (ctx->in_for_exprs) flag = GOVD_PRIVATE; + else + flag = GOVD_PRIVATE | GOVD_SEEN; break; } ctx = ctx->outer_context; } if (ctx) - omp_add_variable (ctx, tmp, flag | GOVD_SEEN); + omp_add_variable (ctx, tmp, flag); } } else if (cfun) @@ -1237,8 +1241,11 @@ asan_poison_variable (tree decl, bool poison, gimple_stmt_iterator *it, /* It's necessary to have all stack variables aligned to ASAN granularity bytes. */ - if (DECL_ALIGN_UNIT (decl) <= ASAN_SHADOW_GRANULARITY) - SET_DECL_ALIGN (decl, BITS_PER_UNIT * ASAN_SHADOW_GRANULARITY); + gcc_assert (!hwasan_sanitize_p () || hwasan_sanitize_stack_p ()); + unsigned shadow_granularity + = hwasan_sanitize_p () ? HWASAN_TAG_GRANULE_SIZE : ASAN_SHADOW_GRANULARITY; + if (DECL_ALIGN_UNIT (decl) <= shadow_granularity) + SET_DECL_ALIGN (decl, BITS_PER_UNIT * shadow_granularity); HOST_WIDE_INT flags = poison ? ASAN_MARK_POISON : ASAN_MARK_UNPOISON; @@ -3384,6 +3391,20 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) cfun->calls_eh_return = true; break; + case BUILT_IN_CLEAR_PADDING: + if (call_expr_nargs (*expr_p) == 1) + { + /* Remember the original type of the argument in an internal + dummy second argument, as in GIMPLE pointer conversions are + useless. */ + p = CALL_EXPR_ARG (*expr_p, 0); + *expr_p + = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p, + build_zero_cst (TREE_TYPE (p))); + return GS_OK; + } + break; + default: ; } @@ -4586,7 +4607,11 @@ gimplify_init_ctor_eval_range (tree object, tree lower, tree upper, gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value), pre_p, cleared); else - gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value)); + { + if (gimplify_expr (&value, pre_p, NULL, is_gimple_val, fb_rvalue) + != GS_ERROR) + gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value)); + } /* We exit the loop when the index var is equal to the upper bound. */ gimplify_seq_add_stmt (pre_p, @@ -5518,6 +5543,19 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, return GS_OK; } + case NOP_EXPR: + /* Pull out compound literal expressions from a NOP_EXPR. + Those are created in the C FE to drop qualifiers during + lvalue conversion. */ + if ((TREE_CODE (TREE_OPERAND (*from_p, 0)) == COMPOUND_LITERAL_EXPR) + && tree_ssa_useless_type_conversion (*from_p)) + { + *from_p = TREE_OPERAND (*from_p, 0); + ret = GS_OK; + changed = true; + } + break; + case COMPOUND_LITERAL_EXPR: { tree complit = TREE_OPERAND (*expr_p, 1); @@ -7586,6 +7624,14 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) goto do_outer; } + /* Don't mark as GOVD_SEEN addressable temporaries seen only in simd + lb, b or incr expressions, those shouldn't be turned into simd arrays. */ + if (ctx->region_type == ORT_SIMD + && ctx->in_for_exprs + && ((n->value & (GOVD_PRIVATE | GOVD_SEEN | GOVD_EXPLICIT)) + == GOVD_PRIVATE)) + flags &= ~GOVD_SEEN; + if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0 && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN && DECL_SIZE (decl)) @@ -8364,6 +8410,113 @@ extract_base_bit_offset (tree base, tree *base_ref, poly_int64 *bitposp, return base; } +/* Returns true if EXPR is or contains (as a sub-component) BASE_PTR. */ + +static bool +is_or_contains_p (tree expr, tree base_ptr) +{ + while (expr != base_ptr) + if (TREE_CODE (base_ptr) == COMPONENT_REF) + base_ptr = TREE_OPERAND (base_ptr, 0); + else + break; + return expr == base_ptr; +} + +/* Implement OpenMP 5.x map ordering rules for target directives. There are + several rules, and with some level of ambiguity, hopefully we can at least + collect the complexity here in one place. */ + +static void +omp_target_reorder_clauses (tree *list_p) +{ + /* Collect refs to alloc/release/delete maps. */ + auto_vec<tree, 32> ard; + tree *cp = list_p; + while (*cp != NULL_TREE) + if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP + && (OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ALLOC + || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_RELEASE + || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_DELETE)) + { + /* Unlink cp and push to ard. */ + tree c = *cp; + tree nc = OMP_CLAUSE_CHAIN (c); + *cp = nc; + ard.safe_push (c); + + /* Any associated pointer type maps should also move along. */ + while (*cp != NULL_TREE + && OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP + && (OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_FIRSTPRIVATE_REFERENCE + || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_FIRSTPRIVATE_POINTER + || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ATTACH_DETACH + || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_POINTER + || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ALWAYS_POINTER + || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_TO_PSET)) + { + c = *cp; + nc = OMP_CLAUSE_CHAIN (c); + *cp = nc; + ard.safe_push (c); + } + } + else + cp = &OMP_CLAUSE_CHAIN (*cp); + + /* Link alloc/release/delete maps to the end of list. */ + for (unsigned int i = 0; i < ard.length (); i++) + { + *cp = ard[i]; + cp = &OMP_CLAUSE_CHAIN (ard[i]); + } + *cp = NULL_TREE; + + /* OpenMP 5.0 requires that pointer variables are mapped before + its use as a base-pointer. */ + auto_vec<tree *, 32> atf; + for (tree *cp = list_p; *cp; cp = &OMP_CLAUSE_CHAIN (*cp)) + if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP) + { + /* Collect alloc, to, from, to/from clause tree pointers. */ + gomp_map_kind k = OMP_CLAUSE_MAP_KIND (*cp); + if (k == GOMP_MAP_ALLOC + || k == GOMP_MAP_TO + || k == GOMP_MAP_FROM + || k == GOMP_MAP_TOFROM + || k == GOMP_MAP_ALWAYS_TO + || k == GOMP_MAP_ALWAYS_FROM + || k == GOMP_MAP_ALWAYS_TOFROM) + atf.safe_push (cp); + } + + for (unsigned int i = 0; i < atf.length (); i++) + if (atf[i]) + { + tree *cp = atf[i]; + tree decl = OMP_CLAUSE_DECL (*cp); + if (TREE_CODE (decl) == INDIRECT_REF || TREE_CODE (decl) == MEM_REF) + { + tree base_ptr = TREE_OPERAND (decl, 0); + STRIP_TYPE_NOPS (base_ptr); + for (unsigned int j = i + 1; j < atf.length (); j++) + { + tree *cp2 = atf[j]; + tree decl2 = OMP_CLAUSE_DECL (*cp2); + if (is_or_contains_p (decl2, base_ptr)) + { + /* Move *cp2 to before *cp. */ + tree c = *cp2; + *cp2 = OMP_CLAUSE_CHAIN (c); + OMP_CLAUSE_CHAIN (c) = *cp; + *cp = c; + atf[j] = NULL; + } + } + } + } +} + /* Scan the OMP clauses in *LIST_P, installing mappings into a new and previous omp contexts. */ @@ -8405,6 +8558,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, break; } + if (code == OMP_TARGET + || code == OMP_TARGET_DATA + || code == OMP_TARGET_ENTER_DATA + || code == OMP_TARGET_EXIT_DATA) + omp_target_reorder_clauses (list_p); + while ((c = *list_p) != NULL) { bool remove = false; @@ -8559,7 +8718,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, { error_at (OMP_CLAUSE_LOCATION (c), "invalid %<task%> reduction modifier on construct " - "other than %<parallel%>, %<for%> or %<sections%>"); + "other than %<parallel%>, %qs or %<sections%>", + lang_GNU_Fortran () ? "do" : "for"); OMP_CLAUSE_REDUCTION_TASK (c) = 0; } } @@ -8845,15 +9005,18 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, } else if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER || (OMP_CLAUSE_MAP_KIND (c) - == GOMP_MAP_FIRSTPRIVATE_REFERENCE)) + == GOMP_MAP_FIRSTPRIVATE_REFERENCE) + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH) && TREE_CODE (OMP_CLAUSE_SIZE (c)) != INTEGER_CST) { OMP_CLAUSE_SIZE (c) = get_initialized_tmp_var (OMP_CLAUSE_SIZE (c), pre_p, NULL, false); - omp_add_variable (ctx, OMP_CLAUSE_SIZE (c), - GOVD_FIRSTPRIVATE | GOVD_SEEN); + if ((region_type & ORT_TARGET) != 0) + omp_add_variable (ctx, OMP_CLAUSE_SIZE (c), + GOVD_FIRSTPRIVATE | GOVD_SEEN); } + if (!DECL_P (decl)) { tree d = decl, *pd; @@ -8878,7 +9041,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, bool indir_p = false; tree orig_decl = decl; tree decl_ref = NULL_TREE; - if ((region_type & ORT_ACC) != 0 + if ((region_type & (ORT_ACC | ORT_TARGET | ORT_TARGET_DATA)) != 0 && TREE_CODE (*pd) == COMPONENT_REF && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH && code != OACC_UPDATE) @@ -8886,9 +9049,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, while (TREE_CODE (decl) == COMPONENT_REF) { decl = TREE_OPERAND (decl, 0); - if ((TREE_CODE (decl) == MEM_REF - && integer_zerop (TREE_OPERAND (decl, 1))) - || INDIRECT_REF_P (decl)) + if (((TREE_CODE (decl) == MEM_REF + && integer_zerop (TREE_OPERAND (decl, 1))) + || INDIRECT_REF_P (decl)) + && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0))) + == POINTER_TYPE)) { indir_p = true; decl = TREE_OPERAND (decl, 0); @@ -8915,8 +9080,9 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, } if (decl != orig_decl && DECL_P (decl) && indir_p) { - gomp_map_kind k = (code == OACC_EXIT_DATA) ? GOMP_MAP_DETACH - : GOMP_MAP_ATTACH; + gomp_map_kind k + = ((code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA) + ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH); /* We have a dereference of a struct member. Make this an attach/detach operation, and ensure the base pointer is mapped as a FIRSTPRIVATE_POINTER. */ @@ -8925,6 +9091,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, tree next_clause = OMP_CLAUSE_CHAIN (c); if (k == GOMP_MAP_ATTACH && code != OACC_ENTER_DATA + && code != OMP_TARGET_ENTER_DATA && (!next_clause || (OMP_CLAUSE_CODE (next_clause) != OMP_CLAUSE_MAP) || (OMP_CLAUSE_MAP_KIND (next_clause) @@ -8972,17 +9139,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, if (code == OACC_UPDATE && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH) OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER); - if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue, fb_lvalue) - == GS_ERROR) - { - remove = true; - break; - } if (DECL_P (decl) && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH - && code != OACC_UPDATE) + && code != OACC_UPDATE + && code != OMP_TARGET_UPDATE) { if (error_operand_p (decl)) { @@ -9044,15 +9206,19 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, bool has_attachments = false; /* For OpenACC, pointers in structs should trigger an attach action. */ - if (attach_detach && (region_type & ORT_ACC) != 0) + if (attach_detach + && ((region_type & (ORT_ACC | ORT_TARGET | ORT_TARGET_DATA)) + || code == OMP_TARGET_ENTER_DATA + || code == OMP_TARGET_EXIT_DATA)) + { /* Turn a GOMP_MAP_ATTACH_DETACH clause into a GOMP_MAP_ATTACH or GOMP_MAP_DETACH clause after we have detected a case that needs a GOMP_MAP_STRUCT mapping added. */ gomp_map_kind k - = (code == OACC_EXIT_DATA) ? GOMP_MAP_DETACH - : GOMP_MAP_ATTACH; + = ((code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA) + ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH); OMP_CLAUSE_SET_MAP_KIND (c, k); has_attachments = true; } @@ -9148,33 +9314,38 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, break; if (scp) continue; - tree d1 = OMP_CLAUSE_DECL (*sc); - tree d2 = OMP_CLAUSE_DECL (c); - while (TREE_CODE (d1) == ARRAY_REF) - d1 = TREE_OPERAND (d1, 0); - while (TREE_CODE (d2) == ARRAY_REF) - d2 = TREE_OPERAND (d2, 0); - if (TREE_CODE (d1) == INDIRECT_REF) - d1 = TREE_OPERAND (d1, 0); - if (TREE_CODE (d2) == INDIRECT_REF) - d2 = TREE_OPERAND (d2, 0); - while (TREE_CODE (d1) == COMPONENT_REF) - if (TREE_CODE (d2) == COMPONENT_REF - && TREE_OPERAND (d1, 1) - == TREE_OPERAND (d2, 1)) - { + if ((region_type & ORT_ACC) != 0) + { + /* This duplicate checking code is currently only + enabled for OpenACC. */ + tree d1 = OMP_CLAUSE_DECL (*sc); + tree d2 = OMP_CLAUSE_DECL (c); + while (TREE_CODE (d1) == ARRAY_REF) d1 = TREE_OPERAND (d1, 0); + while (TREE_CODE (d2) == ARRAY_REF) d2 = TREE_OPERAND (d2, 0); - } - else - break; - if (d1 == d2) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE appears more than once in map " - "clauses", OMP_CLAUSE_DECL (c)); - remove = true; - break; + if (TREE_CODE (d1) == INDIRECT_REF) + d1 = TREE_OPERAND (d1, 0); + if (TREE_CODE (d2) == INDIRECT_REF) + d2 = TREE_OPERAND (d2, 0); + while (TREE_CODE (d1) == COMPONENT_REF) + if (TREE_CODE (d2) == COMPONENT_REF + && TREE_OPERAND (d1, 1) + == TREE_OPERAND (d2, 1)) + { + d1 = TREE_OPERAND (d1, 0); + d2 = TREE_OPERAND (d2, 0); + } + else + break; + if (d1 == d2) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE appears more than once in map " + "clauses", OMP_CLAUSE_DECL (c)); + remove = true; + break; + } } if (maybe_lt (offset1, offsetn) || (known_eq (offset1, offsetn) @@ -9220,6 +9391,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, } } } + + if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue, fb_lvalue) + == GS_ERROR) + { + remove = true; + break; + } + if (!remove && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_POINTER && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH @@ -9236,10 +9415,60 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, break; } + else + { + /* DECL_P (decl) == true */ + tree *sc; + if (struct_map_to_clause + && (sc = struct_map_to_clause->get (decl)) != NULL + && OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_STRUCT + && decl == OMP_CLAUSE_DECL (*sc)) + { + /* We have found a map of the whole structure after a + leading GOMP_MAP_STRUCT has been created, so refill the + leading clause into a map of the whole structure + variable, and remove the current one. + TODO: we should be able to remove some maps of the + following structure element maps if they are of + compatible TO/FROM/ALLOC type. */ + OMP_CLAUSE_SET_MAP_KIND (*sc, OMP_CLAUSE_MAP_KIND (c)); + OMP_CLAUSE_SIZE (*sc) = unshare_expr (OMP_CLAUSE_SIZE (c)); + remove = true; + break; + } + } flags = GOVD_MAP | GOVD_EXPLICIT; if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM) flags |= GOVD_MAP_ALWAYS_TO; + + if ((code == OMP_TARGET + || code == OMP_TARGET_DATA + || code == OMP_TARGET_ENTER_DATA + || code == OMP_TARGET_EXIT_DATA) + && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH) + { + for (struct gimplify_omp_ctx *octx = outer_ctx; octx; + octx = octx->outer_context) + { + splay_tree_node n + = splay_tree_lookup (octx->variables, + (splay_tree_key) OMP_CLAUSE_DECL (c)); + /* If this is contained in an outer OpenMP region as a + firstprivate value, remove the attach/detach. */ + if (n && (n->value & GOVD_FIRSTPRIVATE)) + { + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FIRSTPRIVATE_POINTER); + goto do_add; + } + } + + enum gomp_map_kind map_kind = (code == OMP_TARGET_EXIT_DATA + ? GOMP_MAP_DETACH + : GOMP_MAP_ATTACH); + OMP_CLAUSE_SET_MAP_KIND (c, map_kind); + } + goto do_add; case OMP_CLAUSE_DEPEND: @@ -9284,6 +9513,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, remove = true; break; } + if (code == OMP_TASK) + ctx->has_depend = true; break; case OMP_CLAUSE_TO: @@ -9708,6 +9939,30 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, omp_add_variable (ctx, decl, GOVD_NONTEMPORAL); break; + case OMP_CLAUSE_ALLOCATE: + decl = OMP_CLAUSE_DECL (c); + if (error_operand_p (decl)) + { + remove = true; + break; + } + if (gimplify_expr (&OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), pre_p, NULL, + is_gimple_val, fb_rvalue) == GS_ERROR) + { + remove = true; + break; + } + else if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE + || (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) + == INTEGER_CST)) + ; + else if (code == OMP_TASKLOOP + || !DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))) + OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) + = get_initialized_tmp_var (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), + pre_p, NULL, false); + break; + case OMP_CLAUSE_DEFAULT: ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c); break; @@ -9970,6 +10225,11 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) return 0; } code = OMP_CLAUSE_SHARED; + /* Don't optimize shared into firstprivate for read-only vars + on tasks with depend clause, we shouldn't try to copy them + until the dependencies are satisfied. */ + if (gimplify_omp_ctxp->has_depend) + flags |= GOVD_WRITTEN; } else if (flags & GOVD_PRIVATE) code = OMP_CLAUSE_PRIVATE; @@ -10257,6 +10517,10 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE); OMP_CLAUSE_PRIVATE_DEBUG (c) = 1; } + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED + && ctx->has_depend + && DECL_P (decl)) + n->value |= GOVD_WRITTEN; if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED && (n->value & GOVD_WRITTEN) == 0 && DECL_P (decl) @@ -10270,6 +10534,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, && omp_shared_to_firstprivate_optimizable_decl_p (decl)) omp_mark_stores (gimplify_omp_ctxp->outer_context, decl); } + else + n->value &= ~GOVD_EXPLICIT; break; case OMP_CLAUSE_LASTPRIVATE: @@ -10569,6 +10835,41 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, && omp_shared_to_firstprivate_optimizable_decl_p (decl)) omp_mark_stores (gimplify_omp_ctxp->outer_context, decl); break; + + case OMP_CLAUSE_ALLOCATE: + decl = OMP_CLAUSE_DECL (c); + n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl); + if (n != NULL && !(n->value & GOVD_SEEN)) + { + if ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LINEAR)) + != 0 + && (n->value & (GOVD_REDUCTION | GOVD_LASTPRIVATE)) == 0) + remove = true; + } + if (!remove + && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) + && TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST + && ((ctx->region_type & (ORT_PARALLEL | ORT_TARGET)) != 0 + || (ctx->region_type & ORT_TASKLOOP) == ORT_TASK + || (ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)) + { + tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c); + n = splay_tree_lookup (ctx->variables, (splay_tree_key) allocator); + if (n == NULL) + { + enum omp_clause_default_kind default_kind + = ctx->default_kind; + ctx->default_kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; + omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), + true); + ctx->default_kind = default_kind; + } + else + omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), + true); + } + break; + case OMP_CLAUSE_COPYIN: case OMP_CLAUSE_COPYPRIVATE: case OMP_CLAUSE_IF: @@ -11417,6 +11718,15 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_TILE); if (c) tile = list_length (OMP_CLAUSE_TILE_LIST (c)); + c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ALLOCATE); + hash_set<tree> *allocate_uids = NULL; + if (c) + { + allocate_uids = new hash_set<tree>; + for (; c; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE) + allocate_uids->add (OMP_CLAUSE_DECL (c)); + } for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++) { t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i); @@ -11743,12 +12053,13 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) as an iteration counter. This is valid, since DECL cannot be modified in the body of the loop. Similarly for any iteration vars in simd with collapse > 1 where the iterator vars must be - lastprivate. */ + lastprivate. And similarly for vars mentioned in allocate clauses. */ if (orig_for_stmt != for_stmt) var = decl; else if (!is_gimple_reg (decl) || (ort == ORT_SIMD - && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)) + && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1) + || (allocate_uids && allocate_uids->contains (decl))) { struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; /* Make sure omp_add_variable is not called on it prematurely. @@ -11784,6 +12095,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) else var = decl; + gimplify_omp_ctxp->in_for_exprs = true; if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC) { tree lb = TREE_OPERAND (t, 1); @@ -11796,6 +12108,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) else tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, is_gimple_val, fb_rvalue, false); + gimplify_omp_ctxp->in_for_exprs = false; ret = MIN (ret, tret); if (ret == GS_ERROR) return ret; @@ -11805,6 +12118,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gcc_assert (COMPARISON_CLASS_P (t)); gcc_assert (TREE_OPERAND (t, 0) == decl); + gimplify_omp_ctxp->in_for_exprs = true; if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC) { tree ub = TREE_OPERAND (t, 1); @@ -11817,6 +12131,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) else tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, is_gimple_val, fb_rvalue, false); + gimplify_omp_ctxp->in_for_exprs = false; ret = MIN (ret, tret); /* Handle OMP_FOR_INCR. */ @@ -11882,6 +12197,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gcc_unreachable (); } + gimplify_omp_ctxp->in_for_exprs = true; tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, is_gimple_val, fb_rvalue, false); ret = MIN (ret, tret); @@ -11903,6 +12219,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) ret = MIN (ret, tret); } } + gimplify_omp_ctxp->in_for_exprs = false; break; default: @@ -11975,6 +12292,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) } BITMAP_FREE (has_decl_expr); + delete allocate_uids; if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP || (loop_p && orig_for_stmt == for_stmt)) @@ -12104,6 +12422,20 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) tree *gtask_clauses_ptr = &task_clauses; tree outer_for_clauses = NULL_TREE; tree *gforo_clauses_ptr = &outer_for_clauses; + bitmap lastprivate_uids = NULL; + if (omp_find_clause (c, OMP_CLAUSE_ALLOCATE)) + { + c = omp_find_clause (c, OMP_CLAUSE_LASTPRIVATE); + if (c) + { + lastprivate_uids = BITMAP_ALLOC (NULL); + for (; c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c), + OMP_CLAUSE_LASTPRIVATE)) + bitmap_set_bit (lastprivate_uids, + DECL_UID (OMP_CLAUSE_DECL (c))); + } + c = *gfor_clauses_ptr; + } for (; c; c = OMP_CLAUSE_CHAIN (c)) switch (OMP_CLAUSE_CODE (c)) { @@ -12149,7 +12481,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) *gforo_clauses_ptr = c; gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c); break; - /* Taskloop clause we duplicate on both taskloops. */ + /* Collapse clause we duplicate on both taskloops. */ case OMP_CLAUSE_COLLAPSE: *gfor_clauses_ptr = c; gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c); @@ -12191,12 +12523,43 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr); break; + /* Allocate clause we duplicate on task and inner taskloop + if the decl is lastprivate, otherwise just put on task. */ + case OMP_CLAUSE_ALLOCATE: + if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) + && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))) + { + /* Additionally, put firstprivate clause on task + for the allocator if it is not constant. */ + *gtask_clauses_ptr + = build_omp_clause (OMP_CLAUSE_LOCATION (c), + OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (*gtask_clauses_ptr) + = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c); + gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr); + } + if (lastprivate_uids + && bitmap_bit_p (lastprivate_uids, + DECL_UID (OMP_CLAUSE_DECL (c)))) + { + *gfor_clauses_ptr = c; + gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c); + *gtask_clauses_ptr = copy_node (c); + gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr); + } + else + { + *gtask_clauses_ptr = c; + gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c); + } + break; default: gcc_unreachable (); } *gfor_clauses_ptr = NULL_TREE; *gtask_clauses_ptr = NULL_TREE; *gforo_clauses_ptr = NULL_TREE; + BITMAP_FREE (lastprivate_uids); g = gimple_build_bind (NULL_TREE, gfor, NULL_TREE); g = gimple_build_omp_task (g, task_clauses, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); @@ -12453,7 +12816,8 @@ gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p) { error_at (OMP_CLAUSE_LOCATION (*pc), "invalid %<task%> reduction modifier on construct " - "other than %<parallel%>, %<for%> or %<sections%>"); + "other than %<parallel%>, %qs or %<sections%>", + lang_GNU_Fortran () ? "do" : "for"); OMP_CLAUSE_REDUCTION_TASK (*pc) = 0; } pc = &OMP_CLAUSE_CHAIN (*pc); @@ -15064,7 +15428,7 @@ gimplify_function_tree (tree fndecl) if necessary. */ cfun->curr_properties |= PROP_gimple_lva; - if (asan_sanitize_use_after_scope () && sanitize_flags_p (SANITIZE_ADDRESS)) + if (asan_sanitize_use_after_scope ()) asan_poisoned_variables = new hash_set<tree> (); bind = gimplify_body (fndecl, true); if (asan_poisoned_variables) |