diff options
Diffstat (limited to 'gcc/gimplify.cc')
-rw-r--r-- | gcc/gimplify.cc | 417 |
1 files changed, 370 insertions, 47 deletions
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index 422ad12..9f9ff92 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -273,6 +273,7 @@ struct gimplify_omp_ctx { struct gimplify_omp_ctx *outer_context; splay_tree variables; + hash_map<omp_name_type<tree>, tree> *implicit_mappers; hash_set<tree> *privatized_types; tree clauses; /* Iteration variables in an OMP_FOR. */ @@ -507,6 +508,7 @@ new_omp_context (enum omp_region_type region_type) c = XCNEW (struct gimplify_omp_ctx); c->outer_context = gimplify_omp_ctxp; c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0); + c->implicit_mappers = new hash_map<omp_name_type<tree>, tree>; c->privatized_types = new hash_set<tree>; c->location = input_location; c->region_type = region_type; @@ -530,6 +532,7 @@ delete_omp_context (struct gimplify_omp_ctx *c) { splay_tree_delete (c->variables); delete c->privatized_types; + delete c->implicit_mappers; c->loop_iter_var.release (); XDELETE (c); } @@ -3887,6 +3890,7 @@ static tree modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses, bool want_value, bool pointerize) { + location_t loc = EXPR_LOCATION (expr); tree fndecl = get_callee_fndecl (expr); /* Skip processing if we don't get the expected call form. */ @@ -3933,24 +3937,9 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses, the split between early/late resolution, etc instead of the code as written by the user. */ if (dispatch_interop) - { - for (tree t = dispatch_interop; t; t = TREE_CHAIN (t)) - if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP) - ninterop++; - if (nappend < ninterop) - { - error_at (OMP_CLAUSE_LOCATION (dispatch_interop), - "number of list items in %<interop%> clause (%d) " - "exceeds the number of %<append_args%> items (%d) for " - "%<declare variant%> candidate %qD", - ninterop, nappend, fndecl); - inform (dispatch_append_args - ? EXPR_LOCATION (TREE_PURPOSE (dispatch_append_args)) - : DECL_SOURCE_LOCATION (fndecl), - "%<declare variant%> candidate %qD declared here", - fndecl); - } - } + for (tree t = dispatch_interop; t; t = TREE_CHAIN (t)) + if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP) + ninterop++; if (dispatch_interop && !dispatch_device_num) { gcc_checking_assert (ninterop > 1); @@ -3958,7 +3947,19 @@ 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"); } - else if (dispatch_append_args) + if (nappend < ninterop) + { + error_at (OMP_CLAUSE_LOCATION (dispatch_interop), + "number of list items in %<interop%> clause (%d) " + "exceeds the number of %<append_args%> items (%d) for " + "%<declare variant%> candidate %qD", ninterop, nappend, fndecl); + inform (dispatch_append_args + ? EXPR_LOCATION (TREE_PURPOSE (dispatch_append_args)) + : DECL_SOURCE_LOCATION (fndecl), + "%<declare variant%> candidate %qD declared here", fndecl); + ninterop = nappend; + } + if (dispatch_append_args) { tree *buffer = XALLOCAVEC (tree, nargs + nappend); tree arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); @@ -3971,7 +3972,7 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses, buffer[i] = CALL_EXPR_ARG (expr, i); } int j = ninterop; - for (tree t = dispatch_interop; t; t = TREE_CHAIN (t)) + for (tree t = dispatch_interop; t && j > 0; t = TREE_CHAIN (t)) if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP) buffer[i + --j] = OMP_CLAUSE_DECL (t); gcc_checking_assert (j == 0); @@ -4084,14 +4085,17 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses, } } + objs = build_fold_addr_expr (objs); + target_tgtsync = build_fold_addr_expr (target_tgtsync); + prefer_type = prefer_type ? build_fold_addr_expr (prefer_type) + : null_pointer_node; 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); + = build_call_expr_loc (loc, fn, 11, dispatch_device_num, + nobjs, objs, target_tgtsync, prefer_type, + 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); @@ -4099,12 +4103,12 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses, 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); + = build_call_expr_loc (loc, 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); @@ -4285,8 +4289,8 @@ modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses, actual_ptr); } tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_MAPPED_PTR); - tree mapped_arg = build_call_expr (fn, 2, actual_ptr, - dispatch_device_num); + tree mapped_arg = build_call_expr_loc (loc, fn, 2, actual_ptr, + dispatch_device_num); if (TREE_CODE (*arg_p) == ADDR_EXPR || (TREE_CODE (TREE_TYPE (actual_ptr)) == REFERENCE_TYPE)) @@ -4507,6 +4511,21 @@ gimplify_variant_call_expr (tree expr, fallback_t fallback, } +/* Helper function for gimplify_call_expr, called via walk_tree. + Find used user labels. */ + +static tree +find_used_user_labels (tree *tp, int *, void *) +{ + if (TREE_CODE (*tp) == LABEL_EXPR + && !DECL_ARTIFICIAL (LABEL_EXPR_LABEL (*tp)) + && DECL_NAME (LABEL_EXPR_LABEL (*tp)) + && TREE_USED (LABEL_EXPR_LABEL (*tp))) + return *tp; + return NULL_TREE; +} + + /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P. WANT_VALUE is true if the result of the call is desired. */ @@ -4567,8 +4586,14 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback) fndecl, 0)); return GS_OK; } - /* If not optimizing, ignore the assumptions. */ - if (!optimize || seen_error ()) + /* If not optimizing, ignore the assumptions unless there + are used user labels in it. */ + if ((!optimize + && !walk_tree_without_duplicates (&CALL_EXPR_ARG (*expr_p, + 0), + find_used_user_labels, + NULL)) + || seen_error ()) { *expr_p = NULL_TREE; return GS_ALL_DONE; @@ -9204,11 +9229,18 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) | GOVD_MAP_ALLOC_ONLY)) == flags) { tree type = TREE_TYPE (decl); + location_t loc = DECL_SOURCE_LOCATION (decl); if (gimplify_omp_ctxp->target_firstprivatize_array_bases && omp_privatize_by_reference (decl)) type = TREE_TYPE (type); - if (!omp_mappable_type (type)) + + if (!verify_type_context (loc, TCTX_OMP_MAP_IMP_REF, type)) + /* Check if TYPE can appear in a target region. + verify_type_context has already issued an error if it + can't. */ + nflags |= GOVD_MAP | GOVD_EXPLICIT; + else if (!omp_mappable_type (type)) { error ("%qD referenced in target region does not have " "a mappable type", decl); @@ -9283,7 +9315,8 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN && DECL_SIZE (decl)) { - if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + tree size; + if (!poly_int_tree_p (DECL_SIZE (decl))) { splay_tree_node n2; tree t = DECL_VALUE_EXPR (decl); @@ -9294,16 +9327,14 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) n2->value |= GOVD_SEEN; } else if (omp_privatize_by_reference (decl) - && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))) - && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))) - != INTEGER_CST)) + && (size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))) + && !poly_int_tree_p (size)) { splay_tree_node n2; - tree t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))); - gcc_assert (DECL_P (t)); - n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t); + gcc_assert (DECL_P (size)); + n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) size); if (n2) - omp_notice_variable (ctx, t, true); + omp_notice_variable (ctx, size, true); } } @@ -12864,6 +12895,218 @@ error_out: return success; } +struct instantiate_mapper_info +{ + tree *mapper_clauses_p; + struct gimplify_omp_ctx *omp_ctx; + gimple_seq *pre_p; +}; + +/* Helper function for omp_instantiate_mapper. */ + +static tree +remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data) +{ + copy_body_data *id = (copy_body_data *) data; + + if (DECL_P (*tp)) + { + tree replacement = remap_decl (*tp, id); + if (*tp != replacement) + { + *tp = unshare_expr (replacement); + *walk_subtrees = 0; + } + } + + return NULL_TREE; +} + +/* A copy_decl implementation (for use with tree-inline.cc functions) that + only transform decls or SSA names that are part of a map we already + prepared. */ + +static tree +omp_mapper_copy_decl (tree var, copy_body_data *cb) +{ + tree *repl = cb->decl_map->get (var); + + if (repl) + return *repl; + + return var; +} + +static tree * +omp_instantiate_mapper (gimple_seq *pre_p, + hash_map<omp_name_type<tree>, tree> *implicit_mappers, + tree mapperfn, tree expr, enum gomp_map_kind outer_kind, + tree *mapper_clauses_p) +{ + tree mapper_name = NULL_TREE; + tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapperfn); + gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER); + + tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper); + tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper); + + /* The "extraction map" is used to map the mapper variable in the "declare + mapper" directive, and also any temporary variables that have been created + as part of expanding the mapper function's body (which are expanded as a + "bind" expression in the pre_p sequence). */ + hash_map<tree, tree> extraction_map; + + extraction_map.put (dummy_var, expr); + extraction_map.put (expr, expr); + + /* This copy_body_data is only used to remap the decls in the + OMP_DECLARE_MAPPER tree node expansion itself. All relevant decls should + already be in the current function. */ + copy_body_data id; + memset (&id, 0, sizeof (id)); + id.src_fn = current_function_decl; + id.dst_fn = current_function_decl; + id.src_cfun = cfun; + id.decl_map = &extraction_map; + id.copy_decl = omp_mapper_copy_decl; + id.transform_call_graph_edges = CB_CGE_DUPLICATE; // ??? + id.transform_new_cfg = true; // ??? + + for (; clause; clause = OMP_CLAUSE_CHAIN (clause)) + { + enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (clause); + tree *nested_mapper_p = NULL; + + if (map_kind == GOMP_MAP_PUSH_MAPPER_NAME) + { + mapper_name = OMP_CLAUSE_DECL (clause); + continue; + } + else if (map_kind == GOMP_MAP_POP_MAPPER_NAME) + { + mapper_name = NULL_TREE; + continue; + } + + tree decl = OMP_CLAUSE_DECL (clause); + tree unshared, type; + bool nonunit_array_with_mapper = false; + + if (TREE_CODE (decl) == OMP_ARRAY_SECTION) + { + location_t loc = OMP_CLAUSE_LOCATION (clause); + tree tmp = lang_hooks.decls.omp_map_array_section (loc, decl); + if (tmp == decl) + { + unshared = unshare_expr (clause); + nonunit_array_with_mapper = true; + type = TREE_TYPE (TREE_TYPE (decl)); + } + else + { + unshared = build_omp_clause (OMP_CLAUSE_LOCATION (clause), + OMP_CLAUSE_CODE (clause)); + OMP_CLAUSE_DECL (unshared) = tmp; + OMP_CLAUSE_SIZE (unshared) + = DECL_P (tmp) ? DECL_SIZE_UNIT (tmp) + : TYPE_SIZE_UNIT (TREE_TYPE (tmp)); + type = TREE_TYPE (tmp); + } + } + else + { + unshared = unshare_expr (clause); + type = TREE_TYPE (decl); + } + + walk_tree (&unshared, remap_mapper_decl_1, &id, NULL); + + if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET) + OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind); + + decl = OMP_CLAUSE_DECL (unshared); + type = TYPE_MAIN_VARIANT (type); + + nested_mapper_p = implicit_mappers->get ({ mapper_name, type }); + + if (nested_mapper_p && *nested_mapper_p != mapperfn) + { + if (nonunit_array_with_mapper) + { + sorry ("user-defined mapper with non-unit length array section"); + continue; + } + + if (map_kind == GOMP_MAP_UNSET) + map_kind = outer_kind; + + mapper_clauses_p + = omp_instantiate_mapper (pre_p, implicit_mappers, + *nested_mapper_p, decl, map_kind, + mapper_clauses_p); + continue; + } + + *mapper_clauses_p = unshared; + mapper_clauses_p = &OMP_CLAUSE_CHAIN (unshared); + } + + return mapper_clauses_p; +} + +static int +omp_instantiate_implicit_mappers (splay_tree_node n, void *data) +{ + tree decl = (tree) n->key; + instantiate_mapper_info *im_info = (instantiate_mapper_info *) data; + gimplify_omp_ctx *ctx = im_info->omp_ctx; + tree *mapper_p = NULL; + tree type = TREE_TYPE (decl); + bool ref_p = false; + unsigned flags = n->value; + + if (flags & (GOVD_EXPLICIT | GOVD_LOCAL)) + return 0; + if ((flags & GOVD_SEEN) == 0) + return 0; + /* If we already have clauses pertaining to a struct variable, then we don't + want to implicitly invoke a user-defined mapper. */ + if ((flags & GOVD_EXPLICIT) != 0 && AGGREGATE_TYPE_P (TREE_TYPE (decl))) + return 0; + + if (TREE_CODE (type) == REFERENCE_TYPE) + { + ref_p = true; + type = TREE_TYPE (type); + } + + type = TYPE_MAIN_VARIANT (type); + + if (DECL_P (decl) && type && AGGREGATE_TYPE_P (type)) + { + gcc_assert (ctx); + mapper_p = ctx->implicit_mappers->get ({ NULL_TREE, type }); + } + + if (mapper_p) + { + /* If we have a reference, map the pointed-to object rather than the + reference itself. */ + if (ref_p) + decl = build_fold_indirect_ref (decl); + + im_info->mapper_clauses_p + = omp_instantiate_mapper (im_info->pre_p, ctx->implicit_mappers, + *mapper_p, decl, GOMP_MAP_TOFROM, + im_info->mapper_clauses_p); + /* Make sure we don't map the same variable implicitly in + gimplify_adjust_omp_clauses_1 also. */ + n->value |= GOVD_EXPLICIT; + } + + return 0; +} + /* Scan the OMP clauses in *LIST_P, installing mappings into a new and previous omp contexts. */ @@ -12939,6 +13182,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, unsigned int flags; tree decl; auto_vec<omp_addr_token *, 10> addr_tokens; + tree op = NULL_TREE; + location_t loc = OMP_CLAUSE_LOCATION (c); if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end)) { @@ -12946,6 +13191,36 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, grp_end = NULL_TREE; } + if (code == OMP_TARGET + || code == OMP_TARGET_DATA + || code == OMP_TARGET_ENTER_DATA + || code == OMP_TARGET_EXIT_DATA) + /* Do some target-specific type checks for map operands. */ + switch (OMP_CLAUSE_CODE (c)) + { + case OMP_CLAUSE_MAP: + op = OMP_CLAUSE_OPERAND (c, 0); + verify_type_context (loc, TCTX_OMP_MAP, TREE_TYPE (op)); + break; + case OMP_CLAUSE_PRIVATE: + op = OMP_CLAUSE_OPERAND (c, 0); + verify_type_context (loc, TCTX_OMP_PRIVATE, TREE_TYPE (op)); + break; + case OMP_CLAUSE_FIRSTPRIVATE: + op = OMP_CLAUSE_OPERAND (c, 0); + verify_type_context (loc, TCTX_OMP_FIRSTPRIVATE, TREE_TYPE (op)); + break; + case OMP_CLAUSE_IS_DEVICE_PTR: + case OMP_CLAUSE_USE_DEVICE_ADDR: + case OMP_CLAUSE_USE_DEVICE_PTR: + case OMP_CLAUSE_HAS_DEVICE_ADDR: + op = OMP_CLAUSE_OPERAND (c, 0); + verify_type_context (loc, TCTX_OMP_DEVICE_ADDR, TREE_TYPE (op)); + break; + default: + break; + } + switch (OMP_CLAUSE_CODE (c)) { case OMP_CLAUSE_PRIVATE: @@ -13628,6 +13903,17 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, } goto do_notice; + case OMP_CLAUSE__MAPPER_BINDING_: + { + tree name = OMP_CLAUSE__MAPPER_BINDING__ID (c); + tree var = OMP_CLAUSE__MAPPER_BINDING__DECL (c); + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (var)); + tree fndecl = OMP_CLAUSE__MAPPER_BINDING__MAPPER (c); + ctx->implicit_mappers->put ({ name, type }, fndecl); + remove = true; + break; + } + case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_USE_DEVICE_ADDR: flags = GOVD_EXPLICIT; @@ -14563,7 +14849,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0) OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause) = 1; if (DECL_SIZE (decl) - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + && !poly_int_tree_p (DECL_SIZE (decl))) { tree decl2 = DECL_VALUE_EXPR (decl); gcc_assert (INDIRECT_REF_P (decl2)); @@ -14712,6 +14998,30 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, || code == OMP_TARGET_ENTER_DATA || code == OMP_TARGET_EXIT_DATA) { + tree mapper_clauses = NULL_TREE; + instantiate_mapper_info im_info; + + im_info.mapper_clauses_p = &mapper_clauses; + im_info.omp_ctx = ctx; + im_info.pre_p = pre_p; + + splay_tree_foreach (ctx->variables, + omp_instantiate_implicit_mappers, + (void *) &im_info); + + if (mapper_clauses) + { + mapper_clauses + = lang_hooks.decls.omp_finish_mapper_clauses (mapper_clauses); + + /* Stick the implicitly-expanded mapper clauses at the end of the + clause list. */ + tree *tail = list_p; + while (*tail) + tail = &OMP_CLAUSE_CHAIN (*tail); + *tail = mapper_clauses; + } + vec<omp_mapping_group> *groups; groups = omp_gather_mapping_groups (list_p); hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL; @@ -15304,7 +15614,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, if (!DECL_P (decl)) break; if (DECL_SIZE (decl) - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + && !poly_int_tree_p (DECL_SIZE (decl))) { tree decl2 = DECL_VALUE_EXPR (decl); gcc_assert (INDIRECT_REF_P (decl2)); @@ -19197,6 +19507,15 @@ gimplify_omp_metadirective (tree *expr_p, gimple_seq *pre_p, gimple_seq *, return GS_OK; } +/* Gimplify an OMP_DECLARE_MAPPER node (by just removing it). */ + +static enum gimplify_status +gimplify_omp_declare_mapper (tree *expr_p) +{ + *expr_p = NULL_TREE; + return GS_ALL_DONE; +} + /* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the expression produces a value to be used as an operand inside a GIMPLE statement, the value will be stored back in *EXPR_P. This value will @@ -20158,6 +20477,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = GS_ALL_DONE; break; + case OMP_DECLARE_MAPPER: + ret = gimplify_omp_declare_mapper (expr_p); + break; + case TRANSACTION_EXPR: ret = gimplify_transaction (expr_p, pre_p); break; |