mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 04:10:29 +08:00
re PR fortran/35681 (wrong result for vector subscripted array expression in MVBITS)
2008-11-16 Mikael Morin <mikael.morin@tele2.fr> PR fortran/35681 * dependency.c (gfc_check_argument_var_dependency): Add elemental check flag. Issue a warning if we find a dependency but don't generate a temporary. Add the case of an elemental function call as actual argument to an elemental procedure. Add the case of an operator expression as actual argument to an elemental procedure. (gfc_check_argument_dependency): Add elemental check flag. Update calls to gfc_check_argument_var_dependency. (gfc_check_fncall_dependency): Add elemental check flag. Update call to gfc_check_argument_dependency. * trans-stmt.c (gfc_trans_call): Make call to gfc_conv_elemental_dependency unconditional, but with a flag whether we should check dependencies between variables. (gfc_conv_elemental_dependency): Add elemental check flag. Update call to gfc_check_fncall_dependency. * trans-expr.c (gfc_trans_arrayfunc_assign): Update call to gfc_check_fncall_dependency. * resolve.c (find_noncopying_intrinsics): Update call to gfc_check_fncall_dependency. * dependency.h (enum gfc_dep_check): New enum. (gfc_check_fncall_dependency): Update prototype. 2008-11-16 Mikael Morin <mikael.morin@tele2.fr> PR fortran/35681 * gfortran.dg/elemental_dependency_1.f90: New test. From-SVN: r141931
This commit is contained in:
parent
d3ea650c44
commit
2b0bd71482
@ -1,3 +1,28 @@
|
||||
2008-11-16 Mikael Morin <mikael.morin@tele2.fr>
|
||||
|
||||
PR fortran/35681
|
||||
* dependency.c (gfc_check_argument_var_dependency): Add
|
||||
elemental check flag. Issue a warning if we find a dependency
|
||||
but don't generate a temporary. Add the case of an elemental
|
||||
function call as actual argument to an elemental procedure.
|
||||
Add the case of an operator expression as actual argument
|
||||
to an elemental procedure.
|
||||
(gfc_check_argument_dependency): Add elemental check flag.
|
||||
Update calls to gfc_check_argument_var_dependency.
|
||||
(gfc_check_fncall_dependency): Add elemental check flag.
|
||||
Update call to gfc_check_argument_dependency.
|
||||
* trans-stmt.c (gfc_trans_call): Make call to
|
||||
gfc_conv_elemental_dependency unconditional, but with a flag
|
||||
whether we should check dependencies between variables.
|
||||
(gfc_conv_elemental_dependency): Add elemental check flag.
|
||||
Update call to gfc_check_fncall_dependency.
|
||||
* trans-expr.c (gfc_trans_arrayfunc_assign): Update call to
|
||||
gfc_check_fncall_dependency.
|
||||
* resolve.c (find_noncopying_intrinsics): Update call to
|
||||
gfc_check_fncall_dependency.
|
||||
* dependency.h (enum gfc_dep_check): New enum.
|
||||
(gfc_check_fncall_dependency): Update prototype.
|
||||
|
||||
2008-11-16 Mikael Morin <mikael.morin@tele2.fr>
|
||||
|
||||
PR fortran/37992
|
||||
|
@ -432,25 +432,81 @@ gfc_ref_needs_temporary_p (gfc_ref *ref)
|
||||
|
||||
static int
|
||||
gfc_check_argument_var_dependency (gfc_expr *var, sym_intent intent,
|
||||
gfc_expr *expr)
|
||||
gfc_expr *expr, gfc_dep_check elemental)
|
||||
{
|
||||
gfc_expr *arg;
|
||||
|
||||
gcc_assert (var->expr_type == EXPR_VARIABLE);
|
||||
gcc_assert (var->rank > 0);
|
||||
|
||||
switch (expr->expr_type)
|
||||
{
|
||||
case EXPR_VARIABLE:
|
||||
return (gfc_ref_needs_temporary_p (expr->ref)
|
||||
|| gfc_check_dependency (var, expr, 1));
|
||||
/* In case of elemental subroutines, there is no dependency
|
||||
between two same-range array references. */
|
||||
if (gfc_ref_needs_temporary_p (expr->ref)
|
||||
|| gfc_check_dependency (var, expr, !elemental))
|
||||
{
|
||||
if (elemental == ELEM_DONT_CHECK_VARIABLE)
|
||||
{
|
||||
/* Elemental procedures forbid unspecified intents,
|
||||
and we don't check dependencies for INTENT_IN args. */
|
||||
gcc_assert (intent == INTENT_OUT || intent == INTENT_INOUT);
|
||||
|
||||
/* We are told not to check dependencies.
|
||||
We do it, however, and issue a warning in case we find one.
|
||||
If a dependency is found in the case
|
||||
elemental == ELEM_CHECK_VARIABLE, we will generate
|
||||
a temporary, so we don't need to bother the user. */
|
||||
gfc_warning ("INTENT(%s) actual argument at %L might interfere "
|
||||
"with actual argument at %L.",
|
||||
intent == INTENT_OUT ? "OUT" : "INOUT",
|
||||
&var->where, &expr->where);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case EXPR_ARRAY:
|
||||
return gfc_check_dependency (var, expr, 1);
|
||||
|
||||
case EXPR_FUNCTION:
|
||||
if (intent != INTENT_IN && expr->inline_noncopying_intrinsic)
|
||||
if (intent != INTENT_IN && expr->inline_noncopying_intrinsic
|
||||
&& (arg = gfc_get_noncopying_intrinsic_argument (expr))
|
||||
&& gfc_check_argument_var_dependency (var, intent, arg, elemental))
|
||||
return 1;
|
||||
if (elemental)
|
||||
{
|
||||
expr = gfc_get_noncopying_intrinsic_argument (expr);
|
||||
return gfc_check_argument_var_dependency (var, intent, expr);
|
||||
if ((expr->value.function.esym
|
||||
&& expr->value.function.esym->attr.elemental)
|
||||
|| (expr->value.function.isym
|
||||
&& expr->value.function.isym->elemental))
|
||||
return gfc_check_fncall_dependency (var, intent, NULL,
|
||||
expr->value.function.actual,
|
||||
ELEM_CHECK_VARIABLE);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case EXPR_OP:
|
||||
/* In case of non-elemental procedures, there is no need to catch
|
||||
dependencies, as we will make a temporary anyway. */
|
||||
if (elemental)
|
||||
{
|
||||
/* If the actual arg EXPR is an expression, we need to catch
|
||||
a dependency between variables in EXPR and VAR,
|
||||
an intent((IN)OUT) variable. */
|
||||
if (expr->value.op.op1
|
||||
&& gfc_check_argument_var_dependency (var, intent,
|
||||
expr->value.op.op1,
|
||||
ELEM_CHECK_VARIABLE))
|
||||
return 1;
|
||||
else if (expr->value.op.op2
|
||||
&& gfc_check_argument_var_dependency (var, intent,
|
||||
expr->value.op.op2,
|
||||
ELEM_CHECK_VARIABLE))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@ -465,18 +521,19 @@ gfc_check_argument_var_dependency (gfc_expr *var, sym_intent intent,
|
||||
|
||||
static int
|
||||
gfc_check_argument_dependency (gfc_expr *other, sym_intent intent,
|
||||
gfc_expr *expr)
|
||||
gfc_expr *expr, gfc_dep_check elemental)
|
||||
{
|
||||
switch (other->expr_type)
|
||||
{
|
||||
case EXPR_VARIABLE:
|
||||
return gfc_check_argument_var_dependency (other, intent, expr);
|
||||
return gfc_check_argument_var_dependency (other, intent, expr, elemental);
|
||||
|
||||
case EXPR_FUNCTION:
|
||||
if (other->inline_noncopying_intrinsic)
|
||||
{
|
||||
other = gfc_get_noncopying_intrinsic_argument (other);
|
||||
return gfc_check_argument_dependency (other, INTENT_IN, expr);
|
||||
return gfc_check_argument_dependency (other, INTENT_IN, expr,
|
||||
elemental);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@ -491,7 +548,8 @@ gfc_check_argument_dependency (gfc_expr *other, sym_intent intent,
|
||||
|
||||
int
|
||||
gfc_check_fncall_dependency (gfc_expr *other, sym_intent intent,
|
||||
gfc_symbol *fnsym, gfc_actual_arglist *actual)
|
||||
gfc_symbol *fnsym, gfc_actual_arglist *actual,
|
||||
gfc_dep_check elemental)
|
||||
{
|
||||
gfc_formal_arglist *formal;
|
||||
gfc_expr *expr;
|
||||
@ -514,7 +572,7 @@ gfc_check_fncall_dependency (gfc_expr *other, sym_intent intent,
|
||||
&& formal->sym->attr.intent == INTENT_IN)
|
||||
continue;
|
||||
|
||||
if (gfc_check_argument_dependency (other, intent, expr))
|
||||
if (gfc_check_argument_dependency (other, intent, expr, elemental))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -19,13 +19,24 @@ You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/****************************** Enums *********************************/
|
||||
typedef enum
|
||||
{
|
||||
NOT_ELEMENTAL, /* Not elemental case: normal dependency check. */
|
||||
ELEM_CHECK_VARIABLE, /* Test whether variables overlap. */
|
||||
ELEM_DONT_CHECK_VARIABLE /* Test whether variables overlap only if used
|
||||
in an expression. */
|
||||
}
|
||||
gfc_dep_check;
|
||||
|
||||
|
||||
/*********************** Functions prototypes **************************/
|
||||
|
||||
bool gfc_ref_needs_temporary_p (gfc_ref *);
|
||||
bool gfc_full_array_ref_p (gfc_ref *);
|
||||
gfc_expr *gfc_get_noncopying_intrinsic_argument (gfc_expr *);
|
||||
int gfc_check_fncall_dependency (gfc_expr *, sym_intent, gfc_symbol *,
|
||||
gfc_actual_arglist *);
|
||||
gfc_actual_arglist *, gfc_dep_check);
|
||||
int gfc_check_dependency (gfc_expr *, gfc_expr *, bool);
|
||||
int gfc_is_same_range (gfc_array_ref *, gfc_array_ref *, int, int);
|
||||
int gfc_expr_is_one (gfc_expr *, int);
|
||||
|
@ -1491,7 +1491,8 @@ find_noncopying_intrinsics (gfc_symbol *fnsym, gfc_actual_arglist *actual)
|
||||
for (ap = actual; ap; ap = ap->next)
|
||||
if (ap->expr
|
||||
&& (expr = gfc_get_noncopying_intrinsic_argument (ap->expr))
|
||||
&& !gfc_check_fncall_dependency (expr, INTENT_IN, fnsym, actual))
|
||||
&& !gfc_check_fncall_dependency (expr, INTENT_IN, fnsym, actual,
|
||||
NOT_ELEMENTAL))
|
||||
ap->expr->inline_noncopying_intrinsic = 1;
|
||||
}
|
||||
|
||||
|
@ -4288,7 +4288,8 @@ gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
|
||||
/* Check for a dependency. */
|
||||
if (gfc_check_fncall_dependency (expr1, INTENT_OUT,
|
||||
expr2->value.function.esym,
|
||||
expr2->value.function.actual))
|
||||
expr2->value.function.actual,
|
||||
NOT_ELEMENTAL))
|
||||
return NULL;
|
||||
|
||||
/* The frontend doesn't seem to bother filling in expr->symtree for intrinsic
|
||||
|
@ -201,7 +201,8 @@ gfc_trans_entry (gfc_code * code)
|
||||
can be used, as is, to copy the result back to the variable. */
|
||||
static void
|
||||
gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
|
||||
gfc_symbol * sym, gfc_actual_arglist * arg)
|
||||
gfc_symbol * sym, gfc_actual_arglist * arg,
|
||||
gfc_dep_check check_variable)
|
||||
{
|
||||
gfc_actual_arglist *arg0;
|
||||
gfc_expr *e;
|
||||
@ -249,7 +250,7 @@ gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
|
||||
&& e->rank && fsym
|
||||
&& fsym->attr.intent != INTENT_IN
|
||||
&& gfc_check_fncall_dependency (e, fsym->attr.intent,
|
||||
sym, arg0))
|
||||
sym, arg0, check_variable))
|
||||
{
|
||||
tree initial;
|
||||
stmtblock_t temp_post;
|
||||
@ -333,6 +334,7 @@ gfc_trans_call (gfc_code * code, bool dependency_check)
|
||||
gfc_se se;
|
||||
gfc_ss * ss;
|
||||
int has_alternate_specifier;
|
||||
gfc_dep_check check_variable;
|
||||
|
||||
/* A CALL starts a new block because the actual arguments may have to
|
||||
be evaluated first. */
|
||||
@ -395,6 +397,10 @@ gfc_trans_call (gfc_code * code, bool dependency_check)
|
||||
gfc_add_ss_to_loop (&loop, ss);
|
||||
|
||||
gfc_conv_ss_startstride (&loop);
|
||||
/* TODO: gfc_conv_loop_setup generates a temporary for vector
|
||||
subscripts. This could be prevented in the elemental case
|
||||
as temporaries are handled separatedly
|
||||
(below in gfc_conv_elemental_dependencies). */
|
||||
gfc_conv_loop_setup (&loop, &code->expr->where);
|
||||
gfc_mark_ss_chain_used (ss, 1);
|
||||
|
||||
@ -404,12 +410,11 @@ gfc_trans_call (gfc_code * code, bool dependency_check)
|
||||
|
||||
/* For operator assignment, do dependency checking. */
|
||||
if (dependency_check)
|
||||
{
|
||||
gfc_symbol *sym;
|
||||
sym = code->resolved_sym;
|
||||
gfc_conv_elemental_dependencies (&se, &loopse, sym,
|
||||
code->ext.actual);
|
||||
}
|
||||
check_variable = ELEM_CHECK_VARIABLE;
|
||||
else
|
||||
check_variable = ELEM_DONT_CHECK_VARIABLE;
|
||||
gfc_conv_elemental_dependencies (&se, &loopse, code->resolved_sym,
|
||||
code->ext.actual, check_variable);
|
||||
|
||||
/* Generate the loop body. */
|
||||
gfc_start_scalarized_body (&loop, &body);
|
||||
|
@ -1,3 +1,8 @@
|
||||
2008-11-16 Mikael Morin <mikael.morin@tele2.fr>
|
||||
|
||||
PR fortran/35681
|
||||
* gfortran.dg/elemental_dependency_1.f90: New test.
|
||||
|
||||
2008-11-16 Mikael Morin <mikael.morin@tele2.fr>
|
||||
|
||||
PR fortran/37992
|
||||
|
Loading…
x
Reference in New Issue
Block a user