diff options
author | mikael <mikael@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-05 21:41:15 +0000 |
---|---|---|
committer | mikael <mikael@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-05 21:41:15 +0000 |
commit | 3a2545a18b36242908d5498ef7bd9e7a8aa96a10 (patch) | |
tree | 6b50b567f3e7b484d1a22fbe37c2dcf74d0ad824 /gcc/fortran | |
parent | 66feb54cdf22a430c0b228314b1a13899c225ce7 (diff) | |
download | gcc-3a2545a18b36242908d5498ef7bd9e7a8aa96a10.tar.gz |
Fix fortran scalar elemental dependency mishandling
PR fortran/66089
gcc/fortran/
* trans-expr.c (expr_is_variable, gfc_expr_is_variable): Rename
the former to the latter and make it non-static. Update callers.
* gfortran.h (gfc_expr_is_variable): New declaration.
(struct gfc_ss_info): Add field needs_temporary.
* trans-array.c (gfc_scalar_elemental_arg_saved_as_argument):
Tighten the condition on aggregate expressions with a check
that the expression is a variable and doesn't need a temporary.
(gfc_conv_resolve_dependency): Add intermediary reference variable.
Set the needs_temporary field.
gcc/testsuite/
* gfortran.dg/elemental_dependency_6.f90: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233188 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/fortran/trans-array.c | 18 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.c | 10 | ||||
-rw-r--r-- | gcc/fortran/trans.h | 5 |
4 files changed, 36 insertions, 10 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index dc0b8f2efd6..f94fbe5df05 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,16 @@ +2016-02-05 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/66089 + * trans-expr.c (expr_is_variable, gfc_expr_is_variable): Rename + the former to the latter and make it non-static. Update callers. + * gfortran.h (gfc_expr_is_variable): New declaration. + (struct gfc_ss_info): Add field needs_temporary. + * trans-array.c (gfc_scalar_elemental_arg_saved_as_argument): + Tighten the condition on aggregate expressions with a check + that the expression is a variable and doesn't need a temporary. + (gfc_conv_resolve_dependency): Add intermediary reference variable. + Set the needs_temporary field. + 2016-02-03 Andre Vehreschild <vehre@gcc.gnu.org> PR fortran/67451 diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index eeb688c9b91..2ff283312b6 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -2464,10 +2464,12 @@ gfc_scalar_elemental_arg_saved_as_reference (gfc_ss_info * ss_info) return true; /* If the expression is a data reference of aggregate type, + and the data reference is not used on the left hand side, avoid a copy by saving a reference to the content. */ - if (ss_info->expr->expr_type == EXPR_VARIABLE + if (!ss_info->data.scalar.needs_temporary && (ss_info->expr->ts.type == BT_DERIVED - || ss_info->expr->ts.type == BT_CLASS)) + || ss_info->expr->ts.type == BT_CLASS) + && gfc_expr_is_variable (ss_info->expr)) return true; /* Otherwise the expression is evaluated to a temporary variable before the @@ -4461,6 +4463,7 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest, gfc_ss *ss; gfc_ref *lref; gfc_ref *rref; + gfc_ss_info *ss_info; gfc_expr *dest_expr; gfc_expr *ss_expr; int nDepend = 0; @@ -4471,15 +4474,16 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest, for (ss = rss; ss != gfc_ss_terminator; ss = ss->next) { - ss_expr = ss->info->expr; + ss_info = ss->info; + ss_expr = ss_info->expr; - if (ss->info->array_outer_dependency) + if (ss_info->array_outer_dependency) { nDepend = 1; break; } - if (ss->info->type != GFC_SS_SECTION) + if (ss_info->type != GFC_SS_SECTION) { if (flag_realloc_lhs && dest_expr != ss_expr @@ -4494,6 +4498,10 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest, nDepend = gfc_check_dependency (dest_expr, ss_expr, false); + if (ss_info->type == GFC_SS_REFERENCE + && gfc_check_dependency (dest_expr, ss_expr, false)) + ss_info->data.scalar.needs_temporary = 1; + continue; } diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 87af7acb8f2..4baadc84ef0 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -8834,8 +8834,8 @@ gfc_trans_array_constructor_copy (gfc_expr * expr1, gfc_expr * expr2) /* Tells whether the expression is to be treated as a variable reference. */ -static bool -expr_is_variable (gfc_expr *expr) +bool +gfc_expr_is_variable (gfc_expr *expr) { gfc_expr *arg; gfc_component *comp; @@ -8848,7 +8848,7 @@ expr_is_variable (gfc_expr *expr) if (arg) { gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE); - return expr_is_variable (arg); + return gfc_expr_is_variable (arg); } /* A data-pointer-returning function should be considered as a variable @@ -9329,7 +9329,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag, must have its components deallocated afterwards. */ scalar_to_array = (expr2->ts.type == BT_DERIVED && expr2->ts.u.derived->attr.alloc_comp - && !expr_is_variable (expr2) + && !gfc_expr_is_variable (expr2) && expr1->rank && !expr2->rank); scalar_to_array |= (expr1->ts.type == BT_DERIVED && expr1->rank @@ -9373,7 +9373,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag, } tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, - expr_is_variable (expr2) || scalar_to_array + gfc_expr_is_variable (expr2) || scalar_to_array || expr2->expr_type == EXPR_ARRAY, !(l_is_temp || init_flag) && dealloc); gfc_add_expr_to_block (&body, tmp); diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 3026e3bbd2d..316ee9b540f 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -210,6 +210,10 @@ typedef struct gfc_ss_info this is the symbol of the corresponding dummy argument. */ gfc_symbol *dummy_arg; tree value; + /* Tells that the scalar is a reference to a variable that might + be present on the lhs, so that we should evaluate the value + itself before the loop, not just the reference. */ + unsigned needs_temporary:1; } scalar; @@ -464,6 +468,7 @@ bool gfc_conv_ieee_arithmetic_function (gfc_se *, gfc_expr *); tree gfc_save_fp_state (stmtblock_t *); void gfc_restore_fp_state (stmtblock_t *, tree); +bool gfc_expr_is_variable (gfc_expr *); /* Does an intrinsic map directly to an external library call This is true for array-returning intrinsics, unless |