diff options
Diffstat (limited to 'gcc/gimplify.cc')
-rw-r--r-- | gcc/gimplify.cc | 246 |
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: |