Hello world,
the attached patch lets the middle-end know that variables
associated with intent(out) arguments become undefined, by
issuing an assignment to a special value (a "clobber")
before entering the procedure.
Originally, I had also planned to do so on entry to the
procedure, see https://gcc.gnu.org/ml/fortran/2018-09/msg00148.html .
This turned out to cause regressions; some details are outlined
in the PR.
Regression-tested. OK for trunk?
Regards
Thomas
2018-09-22 Thomas Koenig
PR fortran/41453
* trans.h (gfc_conv_expr_reference): Add optional argument
add_clobber to prototype.
(gfc_conv_procedure_call): Set add_clobber argument to
gfc_conv_procedure_reference to true for scalar, INTENT(OUT),
non-pointer, non-allocatable, non-dummy variables whose type
is neither BT_CHARACTER, BT_DERIVED or BT_CLASS, but only if
the procedure is not elemental.
* trans-expr.c (gfc_conv_procedure_reference): Add clobber
statement before call if add_clobber is set.
2018-09-22 Thomas Koenig
PR fortran/41453
* gfortran.dg/intent_optimize_2.f90: New test.
Index: trans-expr.c
===
--- trans-expr.c (Revision 264487)
+++ trans-expr.c (Arbeitskopie)
@@ -5276,8 +5276,17 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol *
}
}
else
- gfc_conv_expr_reference (&parmse, e);
+ {
+ bool add_clobber;
+ add_clobber = fsym && fsym->attr.intent == INTENT_OUT
+ && !fsym->attr.allocatable && !fsym->attr.pointer
+ && !e->symtree->n.sym->attr.pointer
+ && !e->symtree->n.sym->attr.dummy /* See PR 41453. */
+ && e->ts.type != BT_CHARACTER && e->ts.type != BT_DERIVED
+ && e->ts.type != BT_CLASS && !sym->attr.elemental;
+ gfc_conv_expr_reference (&parmse, e, add_clobber);
+ }
/* Catch base objects that are not variables. */
if (e->ts.type == BT_CLASS
&& e->expr_type != EXPR_VARIABLE
@@ -8060,7 +8069,7 @@ gfc_conv_expr_type (gfc_se * se, gfc_expr * expr,
values only. */
void
-gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr)
+gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr, bool add_clobber)
{
gfc_ss *ss;
tree var;
@@ -8100,6 +8109,16 @@ void
gfc_add_block_to_block (&se->pre, &se->post);
se->expr = var;
}
+ else if (add_clobber)
+ {
+ tree clobber;
+ tree var;
+ /* FIXME: This fails if var is passed by reference, see PR
+ 41453. */
+ var = expr->symtree->n.sym->backend_decl;
+ clobber = build_clobber (TREE_TYPE (var));
+ gfc_add_modify (&se->pre, var, clobber);
+ }
return;
}
Index: trans.h
===
--- trans.h (Revision 264487)
+++ trans.h (Arbeitskopie)
@@ -485,7 +485,8 @@ tree gfc_build_compare_string (tree, tree, tree, t
void gfc_conv_expr (gfc_se * se, gfc_expr * expr);
void gfc_conv_expr_val (gfc_se * se, gfc_expr * expr);
void gfc_conv_expr_lhs (gfc_se * se, gfc_expr * expr);
-void gfc_conv_expr_reference (gfc_se * se, gfc_expr *);
+void gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr,
+ bool add_clobber = false);
void gfc_conv_expr_type (gfc_se * se, gfc_expr *, tree);
! { dg-do compile }
! { dg-options "-O -fno-inline -fdump-tree-optimized -fdump-tree-original" }
! PR fortran/41453
! Check that there is one clobber in the *.original tree, plus that
! the constant 123456789 has been removed tue to the INTENT(OUT).
module x
implicit none
contains
subroutine foo(a)
integer, intent(out) :: a
a = 42
end subroutine foo
end module x
program main
use x
implicit none
integer :: a
a = 12345689
call foo(a)
print *,a
end program main
! { dg-final { scan-tree-dump-times "123456789" 0 "optimized" } }
! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } }