aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimplify.cc')
-rw-r--r--gcc/gimplify.cc246
1 files changed, 210 insertions, 36 deletions
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 5bdd970..422ad12 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -2395,7 +2395,7 @@ warn_switch_unreachable_and_auto_init_r (gimple_stmt_iterator *gsi_p,
const char *var_name_str = TREE_STRING_POINTER (var_name);
warning_at (gimple_location (stmt), OPT_Wtrivial_auto_var_init,
- "%qs cannot be initialized with"
+ "%qs cannot be initialized with "
"%<-ftrivial-auto-var_init%>",
var_name_str);
break;
@@ -3874,8 +3874,8 @@ find_supercontext (void)
/* OpenMP: Handle the append_args and adjust_args clauses of
declare_variant for EXPR, which is a CALL_EXPR whose CALL_EXPR_FN
- is the variant, within a dispatch construct with clauses DISPATCH_CLAUSES
- and location DISPATCH_LOC.
+ is the variant, within a dispatch construct with clauses DISPATCH_CLAUSES.
+ WANT_VALUE and POINTERIZE are as for expand_variant_call_expr.
'append_args' causes interop objects are added after the last regular
(nonhidden, nonvariadic) arguments of the variant function.
@@ -3885,7 +3885,7 @@ find_supercontext (void)
address. */
static tree
modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
- location_t dispatch_loc)
+ bool want_value, bool pointerize)
{
tree fndecl = get_callee_fndecl (expr);
@@ -3893,9 +3893,11 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
if (!fndecl)
return expr;
+ tree init_code = NULL_TREE;
+ tree cleanup = NULL_TREE;
+ tree clobbers = NULL_TREE;
int nargs = call_expr_nargs (expr);
tree dispatch_device_num = NULL_TREE;
- tree dispatch_device_num_init = NULL_TREE;
tree dispatch_interop = NULL_TREE;
tree dispatch_append_args = NULL_TREE;
int nfirst_args = 0;
@@ -3956,14 +3958,6 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
"the %<device%> clause must be present if the %<interop%> "
"clause has more than one list item");
}
- if (dispatch_append_args && nappend != ninterop)
- {
- sorry_at (EXPR_LOCATION (TREE_PURPOSE (dispatch_append_args)),
- "%<append_args%> clause not yet supported for %qD, except "
- "when specifying all %d objects in the %<interop%> clause "
- "of the %<dispatch%> directive", fndecl, nappend);
- inform (dispatch_loc, "required by %<dispatch%> construct");
- }
else if (dispatch_append_args)
{
tree *buffer = XALLOCAVEC (tree, nargs + nappend);
@@ -3976,11 +3970,146 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
arg = TREE_CHAIN (arg);
buffer[i] = CALL_EXPR_ARG (expr, i);
}
- int j = nappend;
+ int j = ninterop;
for (tree t = dispatch_interop; t; t = TREE_CHAIN (t))
if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
buffer[i + --j] = OMP_CLAUSE_DECL (t);
gcc_checking_assert (j == 0);
+
+ /* Do we need to create additional interop objects? */
+ if (ninterop < nappend)
+ {
+ if (dispatch_device_num == NULL_TREE)
+ /* Not remapping device number. */
+ dispatch_device_num = build_int_cst (integer_type_node,
+ GOMP_DEVICE_DEFAULT_OMP_61);
+ int nnew = nappend - ninterop;
+ tree nobjs = build_int_cst (integer_type_node, nnew);
+ tree a, t;
+
+ /* Skip to the append_args clause for the first constructed
+ interop argument. */
+ tree apparg = dispatch_append_args;
+ for (j = 0; j < ninterop; j++)
+ apparg = TREE_CHAIN (apparg);
+
+ /* omp_interop_t *objs[n]; */
+ tree objtype = build_pointer_type (pointer_sized_int_node);
+ t = build_array_type_nelts (objtype, nnew);
+ tree objs = create_tmp_var (t, "interopobjs");
+
+ /* int target_tgtsync[n]; */
+ t = build_array_type_nelts (integer_type_node, nnew);
+ tree target_tgtsync = create_tmp_var (t, "tgt_tgtsync");
+
+ /* Scan first to determine if we need a prefer_type array. */
+ tree prefer_type = NULL_TREE;
+ tree prefer_type_type = NULL_TREE;
+ for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
+ if (TREE_VALUE (a) != NULL_TREE)
+ {
+ /* const char *prefer_type[n]; */
+ t = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
+ prefer_type_type = build_pointer_type (t);
+ t = build_array_type_nelts (prefer_type_type, nnew);
+ prefer_type = create_tmp_var (t, "pref_type");
+ break;
+ }
+
+ /* Initialize the arrays, generating temp vars and clobbers for
+ the interobject objects. (The constructed array holding the
+ pointers to these objects shouldn't need clobbering as there's
+ no reason for GOMP_interop to modify its contents.) */
+ for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
+ {
+ /* The allocated temporaries for the interop objects
+ have type omp_interop_t, which is an integer type that
+ can encode a pointer. */
+ tree objvar = create_tmp_var (pointer_sized_int_node, "interop");
+ buffer[i + j] = objvar;
+ TREE_ADDRESSABLE (objvar) = 1;
+ /* Generate a clobber for the temporary for when we're done
+ with it. */
+ tree c = build_clobber (pointer_sized_int_node,
+ CLOBBER_OBJECT_END);
+ c = build2 (MODIFY_EXPR, pointer_sized_int_node, objvar, c);
+ if (clobbers)
+ clobbers = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
+ c, clobbers);
+ else
+ clobbers = c;
+
+ /* objs[offset] = &objvar; */
+ tree offset = build_int_cst (integer_type_node, j - ninterop);
+ tree init = build4 (ARRAY_REF, objtype, objs, offset,
+ NULL_TREE, NULL_TREE);
+ init = build2 (MODIFY_EXPR, objtype, init,
+ build_fold_addr_expr (objvar));
+ if (init_code)
+ init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
+ init_code, init);
+ else
+ init_code = init;
+
+ /* target_tgtsync[offset] = tgt;
+ (Don't blame me, I didn't design the encoding of this
+ info into the dispatch interop clause data structure,
+ but the runtime wants a bit mask.) */
+ tree tree_tgt = TREE_OPERAND (TREE_PURPOSE (a), 0);
+ int tgt = 0;
+ if (TREE_PURPOSE (tree_tgt) == boolean_true_node)
+ tgt |= GOMP_INTEROP_TARGET;
+ if (TREE_VALUE (tree_tgt) == boolean_true_node)
+ tgt |= GOMP_INTEROP_TARGETSYNC;
+ init = build4 (ARRAY_REF, integer_type_node,
+ target_tgtsync, offset, NULL_TREE, NULL_TREE);
+ init = build2 (MODIFY_EXPR, integer_type_node, init,
+ build_int_cst (integer_type_node, tgt));
+ init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
+ init_code, init);
+
+ if (prefer_type)
+ {
+ tree pref = TREE_VALUE (a);
+ if (pref == NULL_TREE)
+ pref = null_pointer_node;
+ else
+ pref = build_fold_addr_expr (pref);
+ init = build4 (ARRAY_REF, prefer_type_type, prefer_type,
+ offset, NULL_TREE, NULL_TREE);
+ init = build2 (MODIFY_EXPR, prefer_type_type, init,
+ pref);
+ init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
+ init_code, init);
+ }
+ }
+
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_INTEROP);
+ tree create
+ = build_call_expr (fn, 11, dispatch_device_num,
+ nobjs, objs, target_tgtsync,
+ prefer_type ? prefer_type : null_pointer_node,
+ integer_zero_node, null_pointer_node,
+ integer_zero_node, null_pointer_node,
+ integer_zero_node, null_pointer_node);
+ if (init_code)
+ init_code = build2 (COMPOUND_EXPR, TREE_TYPE (create),
+ init_code, create);
+ else
+ init_code = create;
+
+ cleanup
+ = build_call_expr (fn, 11, dispatch_device_num,
+ integer_zero_node, null_pointer_node,
+ null_pointer_node, null_pointer_node,
+ integer_zero_node, null_pointer_node,
+ nobjs, objs,
+ integer_zero_node, null_pointer_node);
+ if (clobbers)
+ cleanup = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
+ cleanup, clobbers);
+ }
+
for (j = 0; j < nappend; j++)
{
/* Fortran permits by-reference or by-value for the dummy arg
@@ -4040,8 +4169,9 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
/* Nothing to do for adjust_args? */
if (!dispatch_adjust_args_list || !TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
- return expr;
+ goto add_cleanup;
+ /* Handle adjust_args. */
for (int i = 0; i < nargs; i++)
{
tree *arg_p = &CALL_EXPR_ARG (expr, i);
@@ -4126,9 +4256,14 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
= builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
tree call = build_call_expr (fn, 0);
dispatch_device_num = create_tmp_var_raw (TREE_TYPE (call));
- dispatch_device_num_init
+ tree init
= build4 (TARGET_EXPR, TREE_TYPE (call),
dispatch_device_num, call, NULL_TREE, NULL_TREE);
+ if (init_code)
+ init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
+ init_code, init);
+ else
+ init_code = init;
}
// We want to emit the following statement:
@@ -4163,9 +4298,35 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
}
}
}
- if (dispatch_device_num_init)
- expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr),
- dispatch_device_num_init, expr);
+
+ add_cleanup:
+ if (cleanup)
+ {
+ tree result = NULL_TREE;
+ if (want_value && pointerize)
+ {
+ tree tmp = create_tmp_var (build_pointer_type (TREE_TYPE (expr)),
+ "cleanuptmp");
+ result = build_simple_mem_ref (tmp);
+ expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp,
+ build_fold_addr_expr (expr));
+ }
+ else if (want_value)
+ {
+ tree tmp = create_tmp_var (TREE_TYPE (expr), "cleanuptmp");
+ result = tmp;
+ expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp, expr);
+ }
+ if (init_code)
+ expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
+ expr = build2 (TRY_FINALLY_EXPR, void_type_node, expr, cleanup);
+
+ if (result)
+ expr = build2 (COMPOUND_EXPR, TREE_TYPE (result), expr, result);
+ }
+ else if (init_code)
+ expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
+
return expr;
}
@@ -4173,7 +4334,7 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
resolution and expansion of the CALL_EXPR EXPR. WANT_VALUE is true
if the result value of the call is needed; POINTERIZE is true if it
also needs to be pointerized. If OMP_DISPATCH_P is true, apply
- associated transformations using DISPATCH_CLAUSES and DISPATCH_LOC.
+ associated transformations using DISPATCH_CLAUSES.
This function may return either the original call or some other
expression such as a conditional to select one of multiple calls.
@@ -4183,8 +4344,7 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
static tree
expand_variant_call_expr (tree expr, bool want_value, bool pointerize,
- bool omp_dispatch_p,
- tree dispatch_clauses, location_t dispatch_loc)
+ bool omp_dispatch_p, tree dispatch_clauses)
{
/* If we've already processed this call, stop now. This can happen
if the variant call resolves to the original function, or to
@@ -4239,7 +4399,8 @@ expand_variant_call_expr (tree expr, bool want_value, bool pointerize,
if (omp_dispatch_p)
thiscall = modify_call_for_omp_dispatch (thiscall,
dispatch_clauses,
- dispatch_loc);
+ want_value,
+ pointerize);
if (!tail)
tail = thiscall;
else
@@ -4301,7 +4462,8 @@ expand_variant_call_expr (tree expr, bool want_value, bool pointerize,
if (omp_dispatch_p)
thiscall = modify_call_for_omp_dispatch (thiscall,
dispatch_clauses,
- dispatch_loc);
+ want_value,
+ pointerize);
}
if (pointerize)
thiscall = build_fold_addr_expr_loc (loc, thiscall);
@@ -4337,15 +4499,11 @@ gimplify_variant_call_expr (tree expr, fallback_t fallback,
|| TREE_ADDRESSABLE (type)))
pointerize = true;
- if (omp_dispatch_p)
- return expand_variant_call_expr (expr, want_value, pointerize,
- omp_dispatch_p,
- gimplify_omp_ctxp->clauses,
- gimplify_omp_ctxp->location);
- else
- return expand_variant_call_expr (expr, want_value, pointerize,
- omp_dispatch_p,
- NULL_TREE, UNKNOWN_LOCATION);
+ return expand_variant_call_expr (expr, want_value, pointerize,
+ omp_dispatch_p,
+ (omp_dispatch_p
+ ? gimplify_omp_ctxp->clauses
+ : NULL_TREE));
}
@@ -13853,6 +14011,9 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_CLAUSE_IF_PRESENT:
case OMP_CLAUSE_FINALIZE:
case OMP_CLAUSE_INTEROP:
+ case OMP_CLAUSE_INIT:
+ case OMP_CLAUSE_USE:
+ case OMP_CLAUSE_DESTROY:
break;
case OMP_CLAUSE_ORDER:
@@ -18480,6 +18641,21 @@ gimplify_omp_ordered (tree expr, gimple_seq body)
return gimple_build_omp_ordered (body, OMP_ORDERED_CLAUSES (expr));
}
+/* Gimplify an OMP_INTEROP statement. */
+
+static enum gimplify_status
+gimplify_omp_interop (tree *expr_p, gimple_seq *pre_p)
+{
+ tree expr = *expr_p;
+
+ gimplify_scan_omp_clauses (&OMP_INTEROP_CLAUSES (expr), pre_p, ORT_TASK,
+ OMP_INTEROP);
+ gimple *stmt = gimple_build_omp_interop (OMP_INTEROP_CLAUSES (expr));
+ gimplify_seq_add_stmt (pre_p, stmt);
+ *expr_p = NULL_TREE;
+ return GS_ALL_DONE;
+}
+
/* Callback for walk_tree to find an IFN_GOMP_DISPATCH. */
static tree
@@ -19953,9 +20129,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
}
case OMP_INTEROP:
- sorry_at (EXPR_LOCATION (*expr_p),
- "%<#pragma omp interop%> not yet supported");
- ret = GS_ERROR;
+ ret = gimplify_omp_interop (expr_p, pre_p);
break;
case OMP_ATOMIC:
case OMP_ATOMIC_READ: