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 <tkoe...@gcc.gnu.org> 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 <tkoe...@gcc.gnu.org> 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" } }