https://gcc.gnu.org/g:91d52f87c5bc48eacaf305d515e7cce192c2cf9c
commit r15-6414-g91d52f87c5bc48eacaf305d515e7cce192c2cf9c Author: Andre Vehreschild <ve...@gcc.gnu.org> Date: Thu Oct 31 15:35:47 2024 +0100 Fortran: Remove adding and removing of caf_get. [PR107635] Preparatory work for PR107635. During resolve prevent adding caf_get calls for expressions on the left-hand-side of an assignment and removing them later on again. Furthermore has the caf_token in a component become a pointer to the component and not the backend_decl of the caf-component. In some cases the caf_token was added as last component in a derived type and not as the next one following the component that it was needed to be associated to. gcc/fortran/ChangeLog: PR fortran/107635 * gfortran.h (gfc_comp_caf_token): Convenient macro for accessing caf_token's tree. * resolve.cc (gfc_resolve_ref): Backup caf_lhs when resolving expr in array_ref. (remove_caf_get_intrinsic): Removed. (resolve_variable): Set flag caf_lhs when resolving lhs of assignment to prevent insertion of caf_get. (resolve_lock_unlock_event): Same, but the lhs is the parameter. (resolve_ordinary_assign): Move conversion to caf_send to resolve_codes. (resolve_codes): Adress caf_get and caf_send here. (resolve_fl_derived0): Set component's caf_token when token is necessary. * trans-array.cc (gfc_conv_array_parameter): Get a coarray for expression that have a corank. (structure_alloc_comps): Use macro to get caf_token's tree. (gfc_alloc_allocatable_for_assignment): Same. * trans-expr.cc (gfc_get_ultimate_alloc_ptr_comps_caf_token): Same. (gfc_trans_structure_assign): Same. * trans-intrinsic.cc (conv_expr_ref_to_caf_ref): Same. (has_ref_after_cafref): New function to figure that after a reference of a coarray another reference is present. (conv_caf_send): Get rhs from correct place, when caf_get is not removed. * trans-types.cc (gfc_get_derived_type): Get caf_token from component and no longer guessing. Diff: --- gcc/fortran/gfortran.h | 3 +- gcc/fortran/resolve.cc | 165 +++++++++++++++++++++-------------------- gcc/fortran/trans-array.cc | 30 ++++---- gcc/fortran/trans-expr.cc | 15 ++-- gcc/fortran/trans-intrinsic.cc | 32 ++++++-- gcc/fortran/trans-types.cc | 44 +++++------ 6 files changed, 158 insertions(+), 131 deletions(-) diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index d08439019a38..d66c13b26615 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1214,11 +1214,12 @@ typedef struct gfc_component /* Needed for procedure pointer components. */ struct gfc_typebound_proc *tb; /* When allocatable/pointer and in a coarray the associated token. */ - tree caf_token; + struct gfc_component *caf_token; } gfc_component; #define gfc_get_component() XCNEW (gfc_component) +#define gfc_comp_caf_token(cm) (cm)->caf_token->backend_decl /* Formal argument lists are lists of symbols. */ typedef struct gfc_formal_arglist diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index f892d809d209..06d870d80de3 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -85,6 +85,8 @@ static bitmap_obstack labels_obstack; /* True when simplifying a EXPR_VARIABLE argument to an inquiry function. */ static bool inquiry_argument = false; +/* True when we are on left hand side in an assignment of a coarray. */ +static bool caf_lhs = false; /* Is the symbol host associated? */ static bool @@ -5578,7 +5580,7 @@ gfc_resolve_ref (gfc_expr *expr) { int current_part_dimension, n_components, seen_part_dimension, dim; gfc_ref *ref, **prev, *array_ref; - bool equal_length; + bool equal_length, old_caf_lhs; for (ref = expr->ref; ref; ref = ref->next) if (ref->type == REF_ARRAY && ref->u.ar.as == NULL) @@ -5588,13 +5590,18 @@ gfc_resolve_ref (gfc_expr *expr) break; } + old_caf_lhs = caf_lhs; + caf_lhs = false; for (prev = &expr->ref; *prev != NULL; prev = *prev == NULL ? prev : &(*prev)->next) switch ((*prev)->type) { case REF_ARRAY: if (!resolve_array_ref (&(*prev)->u.ar)) - return false; + { + caf_lhs = old_caf_lhs; + return false; + } break; case REF_COMPONENT: @@ -5604,7 +5611,10 @@ gfc_resolve_ref (gfc_expr *expr) case REF_SUBSTRING: equal_length = false; if (!gfc_resolve_substring (*prev, &equal_length)) - return false; + { + caf_lhs = old_caf_lhs; + return false; + } if (expr->expr_type != EXPR_SUBSTRING && equal_length) { @@ -5618,6 +5628,7 @@ gfc_resolve_ref (gfc_expr *expr) } break; } + caf_lhs = old_caf_lhs; /* Check constraints on part references. */ @@ -5924,21 +5935,6 @@ add_caf_get_intrinsic (gfc_expr *e) free (wrapper); } - -static void -remove_caf_get_intrinsic (gfc_expr *e) -{ - gcc_assert (e->expr_type == EXPR_FUNCTION && e->value.function.isym - && e->value.function.isym->id == GFC_ISYM_CAF_GET); - gfc_expr *e2 = e->value.function.actual->expr; - e->value.function.actual->expr = NULL; - gfc_free_actual_arglist (e->value.function.actual); - gfc_free_shape (&e->shape, e->rank); - *e = *e2; - free (e2); -} - - /* Resolve a variable expression. */ static bool @@ -6284,13 +6280,18 @@ resolve_variable (gfc_expr *e) t = false; if (sym->as) - for (n = 0; n < sym->as->rank; n++) - { - if (!gfc_resolve_expr (sym->as->lower[n])) - t = false; - if (!gfc_resolve_expr (sym->as->upper[n])) - t = false; - } + { + bool old_caf_lhs = caf_lhs; + caf_lhs = false; + for (n = 0; n < sym->as->rank; n++) + { + if (!gfc_resolve_expr (sym->as->lower[n])) + t = false; + if (!gfc_resolve_expr (sym->as->upper[n])) + t = false; + } + caf_lhs = old_caf_lhs; + } specification_expr = saved_specification_expr; if (t) @@ -6365,7 +6366,8 @@ resolve_procedure: if (t) gfc_expression_rank (e); - if (t && flag_coarray == GFC_FCOARRAY_LIB && gfc_is_coindexed (e)) + if (t && flag_coarray == GFC_FCOARRAY_LIB && !caf_lhs + && gfc_is_coindexed (e)) add_caf_get_intrinsic (e); if (sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED) && sym != sym->result) @@ -10906,15 +10908,9 @@ find_reachable_labels (gfc_code *block) } } - static void resolve_lock_unlock_event (gfc_code *code) { - if (code->expr1->expr_type == EXPR_FUNCTION - && code->expr1->value.function.isym - && code->expr1->value.function.isym->id == GFC_ISYM_CAF_GET) - remove_caf_get_intrinsic (code->expr1); - if ((code->op == EXEC_LOCK || code->op == EXEC_UNLOCK) && (code->expr1->ts.type != BT_DERIVED || code->expr1->expr_type != EXPR_VARIABLE @@ -11993,45 +11989,7 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns) if (lhs->ts.type == BT_CLASS && rhs->ts.type != BT_CLASS) gfc_find_vtab (&rhs->ts); - bool caf_convert_to_send = flag_coarray == GFC_FCOARRAY_LIB - && (lhs_coindexed - || caf_possible_reallocate (lhs) - || (code->expr2->expr_type == EXPR_FUNCTION - && code->expr2->value.function.isym - && code->expr2->value.function.isym->id == GFC_ISYM_CAF_GET - && (code->expr1->rank == 0 || code->expr2->rank != 0) - && !gfc_expr_attr (rhs).allocatable - && !gfc_has_vector_subscript (rhs))); - - gfc_check_assign (lhs, rhs, 1, !caf_convert_to_send); - - /* Insert a GFC_ISYM_CAF_SEND intrinsic, when the LHS is a coindexed variable. - Additionally, insert this code when the RHS is a CAF as we then use the - GFC_ISYM_CAF_SEND intrinsic just to avoid a temporary; but do not do so if - the LHS is (re)allocatable or has a vector subscript. If the LHS is a - noncoindexed array and the RHS is a coindexed scalar, use the normal code - path. */ - if (caf_convert_to_send) - { - if (code->expr2->expr_type == EXPR_FUNCTION - && code->expr2->value.function.isym - && code->expr2->value.function.isym->id == GFC_ISYM_CAF_GET) - remove_caf_get_intrinsic (code->expr2); - code->op = EXEC_CALL; - gfc_get_sym_tree (GFC_PREFIX ("caf_send"), ns, &code->symtree, true); - code->resolved_sym = code->symtree->n.sym; - code->resolved_sym->attr.flavor = FL_PROCEDURE; - code->resolved_sym->attr.intrinsic = 1; - code->resolved_sym->attr.subroutine = 1; - code->resolved_isym = gfc_intrinsic_subroutine_by_id (GFC_ISYM_CAF_SEND); - gfc_commit_symbol (code->resolved_sym); - code->ext.actual = gfc_get_actual_arglist (); - code->ext.actual->expr = lhs; - code->ext.actual->next = gfc_get_actual_arglist (); - code->ext.actual->next->expr = rhs; - code->expr1 = NULL; - code->expr2 = NULL; - } + gfc_check_assign (lhs, rhs, 1); return false; } @@ -12956,7 +12914,22 @@ gfc_resolve_code (gfc_code *code, gfc_namespace *ns) start: t = true; if (code->op != EXEC_COMPCALL && code->op != EXEC_CALL_PPC) - t = gfc_resolve_expr (code->expr1); + { + switch (code->op) + { + case EXEC_ASSIGN: + case EXEC_LOCK: + case EXEC_UNLOCK: + case EXEC_EVENT_POST: + case EXEC_EVENT_WAIT: + caf_lhs = gfc_is_coindexed (code->expr1); + break; + default: + break; + } + t = gfc_resolve_expr (code->expr1); + caf_lhs = false; + } forall_flag = forall_save; gfc_do_concurrent_flag = do_concurrent_save; @@ -13077,15 +13050,46 @@ start: if (!t) break; - if (code->expr1->ts.type == BT_CLASS) - gfc_find_vtab (&code->expr2->ts); + if (flag_coarray == GFC_FCOARRAY_LIB + && (gfc_is_coindexed (code->expr1) + || caf_possible_reallocate (code->expr1) + || (code->expr2->expr_type == EXPR_FUNCTION + && code->expr2->value.function.isym + && code->expr2->value.function.isym->id + == GFC_ISYM_CAF_GET + && (code->expr1->rank == 0 || code->expr2->rank != 0) + && !gfc_expr_attr (code->expr2).allocatable + && !gfc_has_vector_subscript (code->expr2)))) + { + /* Insert a GFC_ISYM_CAF_SEND intrinsic, when the LHS is a + coindexed variable. Additionally, insert this code when the + RHS is a CAF as we then use the GFC_ISYM_CAF_SEND intrinsic + just to avoid a temporary; but do not do so if the LHS is + (re)allocatable or has a vector subscript. If the LHS is a + noncoindexed array and the RHS is a coindexed scalar, use the + normal code path. */ + code->op = EXEC_CALL; + gfc_get_sym_tree (GFC_PREFIX ("caf_send"), ns, &code->symtree, + true); + code->resolved_sym = code->symtree->n.sym; + code->resolved_sym->attr.flavor = FL_PROCEDURE; + code->resolved_sym->attr.intrinsic = 1; + code->resolved_sym->attr.subroutine = 1; + code->resolved_isym + = gfc_intrinsic_subroutine_by_id (GFC_ISYM_CAF_SEND); + gfc_commit_symbol (code->resolved_sym); + code->ext.actual = gfc_get_actual_arglist (); + code->ext.actual->expr = code->expr1; + code->ext.actual->next = gfc_get_actual_arglist (); + code->ext.actual->next->expr = code->expr2; + + code->expr1 = NULL; + code->expr2 = NULL; + break; + } - /* Remove a GFC_ISYM_CAF_GET inserted for a coindexed variable on - the LHS. */ - if (code->expr1->expr_type == EXPR_FUNCTION - && code->expr1->value.function.isym - && code->expr1->value.function.isym->id == GFC_ISYM_CAF_GET) - remove_caf_get_intrinsic (code->expr1); + if (code->expr1->ts.type == BT_CLASS) + gfc_find_vtab (&code->expr2->ts); /* If this is a pointer function in an lvalue variable context, the new code will have to be resolved afresh. This is also the @@ -16204,6 +16208,7 @@ resolve_fl_derived0 (gfc_symbol *sym) token->attr.artificial = 1; token->attr.caf_token = 1; } + c->caf_token = token; } } diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 52813857353f..e531dd5efb7b 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -9124,6 +9124,7 @@ gfc_conv_array_parameter (gfc_se *se, gfc_expr *expr, bool g77, { /* Every other type of array. */ se->want_pointer = (ctree) ? 0 : 1; + se->want_coarray = expr->corank; gfc_conv_expr_descriptor (se, expr); if (size) @@ -10141,9 +10142,11 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest, && caf_dereg_mode != GFC_CAF_COARRAY_NOCOARRAY) { if (c->caf_token) - caf_token = fold_build3_loc (input_location, COMPONENT_REF, - TREE_TYPE (c->caf_token), - decl, c->caf_token, NULL_TREE); + caf_token + = fold_build3_loc (input_location, COMPONENT_REF, + TREE_TYPE (gfc_comp_caf_token (c)), + decl, gfc_comp_caf_token (c), + NULL_TREE); else if (attr->dimension && !attr->proc_pointer) caf_token = gfc_conv_descriptor_token (comp); } @@ -10366,8 +10369,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest, gfc_init_se (&se, NULL); token = fold_build3_loc (input_location, COMPONENT_REF, - pvoid_type_node, decl, c->caf_token, - NULL_TREE); + pvoid_type_node, decl, + gfc_comp_caf_token (c), NULL_TREE); comp = gfc_conv_scalar_to_descriptor (&se, comp, c->ts.type == BT_CLASS ? CLASS_DATA (c)->attr @@ -10584,15 +10587,10 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest, dst_tok = gfc_conv_descriptor_token (dcmp); else { - /* For a scalar allocatable component the caf_token is - the next component. */ - if (!c->caf_token) - c->caf_token = c->next->backend_decl; - dst_tok = fold_build3_loc (input_location, - COMPONENT_REF, - pvoid_type_node, dest, - c->caf_token, - NULL_TREE); + dst_tok + = fold_build3_loc (input_location, COMPONENT_REF, + pvoid_type_node, dest, + gfc_comp_caf_token (c), NULL_TREE); } tmp = duplicate_allocatable_coarray (dcmp, dst_tok, comp, ctype, @@ -11477,8 +11475,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl) { tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts))); - tmp = fold_build2_loc (input_location, MULT_EXPR, - gfc_array_index_type, tmp, + tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, + fold_convert (gfc_array_index_type, tmp), expr1->ts.u.cl->backend_decl); } else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS) diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index e3a4f5924c9e..34891afb54ce 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -167,7 +167,10 @@ gfc_get_ultimate_alloc_ptr_comps_caf_token (gfc_se *outerse, gfc_expr *expr) if (last_caf_ref == NULL) return NULL_TREE; - tree comp = last_caf_ref->u.c.component->caf_token, caf; + tree comp = last_caf_ref->u.c.component->caf_token + ? gfc_comp_caf_token (last_caf_ref->u.c.component) + : NULL_TREE, + caf; gfc_se se; bool comp_ref = !last_caf_ref->u.c.component->attr.dimension; if (comp == NULL_TREE && comp_ref) @@ -9917,10 +9920,12 @@ gfc_trans_structure_assign (tree dest, gfc_expr * expr, bool init, bool coarray) if (cm->ts.type == BT_CLASS) field = gfc_class_data_get (field); - token = is_array ? gfc_conv_descriptor_token (field) - : fold_build3_loc (input_location, COMPONENT_REF, - TREE_TYPE (cm->caf_token), dest, - cm->caf_token, NULL_TREE); + token + = is_array + ? gfc_conv_descriptor_token (field) + : fold_build3_loc (input_location, COMPONENT_REF, + TREE_TYPE (gfc_comp_caf_token (cm)), dest, + gfc_comp_caf_token (cm), NULL_TREE); if (is_array) { diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index 1b36ac6e5ac1..41a1739080e5 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -1326,7 +1326,8 @@ conv_expr_ref_to_caf_ref (stmtblock_t *block, gfc_expr *expr) arr_desc_token_offset); } else if (ref->u.c.component->caf_token) - tmp2 = compute_component_offset (ref->u.c.component->caf_token, + tmp2 = compute_component_offset (gfc_comp_caf_token ( + ref->u.c.component), TREE_TYPE (tmp)); else tmp2 = integer_zero_node; @@ -1932,6 +1933,14 @@ gfc_conv_intrinsic_caf_get (gfc_se *se, gfc_expr *expr, tree lhs, tree lhs_kind, se->string_length = argse.string_length; } +static bool +has_ref_after_cafref (gfc_expr *expr) +{ + for (gfc_ref *ref = expr->ref; ref; ref = ref->next) + if (ref->type == REF_ARRAY && ref->u.ar.codimen) + return ref->next; + return false; +} /* Send data to a remote coarray. */ @@ -1949,8 +1958,16 @@ conv_caf_send (gfc_code *code) { gcc_assert (flag_coarray == GFC_FCOARRAY_LIB); - lhs_expr = code->ext.actual->expr; - rhs_expr = code->ext.actual->next->expr; + lhs_expr + = code->ext.actual->expr->expr_type == EXPR_FUNCTION + && code->ext.actual->expr->value.function.isym->id == GFC_ISYM_CAF_GET + ? code->ext.actual->expr->value.function.actual->expr + : code->ext.actual->expr; + rhs_expr = code->ext.actual->next->expr->expr_type == EXPR_FUNCTION + && code->ext.actual->next->expr->value.function.isym->id + == GFC_ISYM_CAF_GET + ? code->ext.actual->next->expr->value.function.actual->expr + : code->ext.actual->next->expr; lhs_is_coindexed = gfc_is_coindexed (lhs_expr); rhs_is_coindexed = gfc_is_coindexed (rhs_expr); may_require_tmp = gfc_check_dependency (lhs_expr, rhs_expr, true) == 0 @@ -2165,6 +2182,9 @@ conv_caf_send (gfc_code *code) { gfc_add_block_to_block (&block, &lhs_se.post); return gfc_finish_block (&block); } + else if (rhs_expr->expr_type == EXPR_FUNCTION + && rhs_expr->value.function.isym->id == GFC_ISYM_CAF_GET) + rhs_expr = rhs_expr->value.function.actual->expr; gfc_add_block_to_block (&block, &lhs_se.pre); @@ -2276,7 +2296,8 @@ conv_caf_send (gfc_code *code) { if (!rhs_is_coindexed) { - if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp) + if (lhs_caf_attr.alloc_comp || lhs_caf_attr.pointer_comp + || has_ref_after_cafref (lhs_expr)) { tree reference, dst_realloc; reference = conv_expr_ref_to_caf_ref (&block, lhs_expr); @@ -2313,7 +2334,8 @@ conv_caf_send (gfc_code *code) { caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl); rhs_image_index = gfc_caf_get_image_index (&block, rhs_expr, caf_decl); tmp = rhs_se.expr; - if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp) + if (rhs_caf_attr.alloc_comp || rhs_caf_attr.pointer_comp + || has_ref_after_cafref (lhs_expr)) { tmp_stat = gfc_find_stat_co (lhs_expr); diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc index e596a362c023..f3c5cb90efd7 100644 --- a/gcc/fortran/trans-types.cc +++ b/gcc/fortran/trans-types.cc @@ -2817,7 +2817,7 @@ gfc_get_derived_type (gfc_symbol * derived, int codimen) tree *chain = NULL; bool got_canonical = false; bool unlimited_entity = false; - gfc_component *c, *last_c = nullptr; + gfc_component *c; gfc_namespace *ns; tree tmp; bool coarray_flag, class_coarray_flag; @@ -3127,16 +3127,12 @@ gfc_get_derived_type (gfc_symbol * derived, int codimen) gcc_assert (field); /* Overwrite for class array to supply different bounds for different types. */ - if (class_coarray_flag || !c->backend_decl) + if (class_coarray_flag || !c->backend_decl || c->attr.caf_token) c->backend_decl = field; - if (c->attr.caf_token && last_c) - last_c->caf_token = field; if (c->attr.pointer && (c->attr.dimension || c->attr.codimension) && !(c->ts.type == BT_DERIVED && strcmp (c->name, "_data") == 0)) GFC_DECL_PTR_ARRAY_P (c->backend_decl) = 1; - - last_c = c; } /* Now lay out the derived type, including the fields. */ @@ -3162,24 +3158,24 @@ gfc_get_derived_type (gfc_symbol * derived, int codimen) copy_derived_types: - for (c = derived->components; c; c = c->next) - { - /* Do not add a caf_token field for class container components. */ - if ((codimen || coarray_flag) - && !c->attr.dimension && !c->attr.codimension - && (c->attr.allocatable || c->attr.pointer) - && !derived->attr.is_class) - { - /* Provide sufficient space to hold "_caf_symbol". */ - char caf_name[GFC_MAX_SYMBOL_LEN + 6]; - gfc_component *token; - snprintf (caf_name, sizeof (caf_name), "_caf_%s", c->name); - token = gfc_find_component (derived, caf_name, true, true, NULL); - gcc_assert (token); - c->caf_token = token->backend_decl; - suppress_warning (c->caf_token); - } - } + if (!derived->attr.vtype) + for (c = derived->components; c; c = c->next) + { + /* Do not add a caf_token field for class container components. */ + if ((codimen || coarray_flag) && !c->attr.dimension + && !c->attr.codimension && (c->attr.allocatable || c->attr.pointer) + && !derived->attr.is_class) + { + /* Provide sufficient space to hold "_caf_symbol". */ + char caf_name[GFC_MAX_SYMBOL_LEN + 6]; + gfc_component *token; + snprintf (caf_name, sizeof (caf_name), "_caf_%s", c->name); + token = gfc_find_component (derived, caf_name, true, true, NULL); + gcc_assert (token); + gfc_comp_caf_token (c) = token->backend_decl; + suppress_warning (gfc_comp_caf_token (c)); + } + } for (gfc_symbol *dt = gfc_derived_types; dt; dt = dt->dt_next) {