aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c476
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)