Re: [patch, fortran] Inline packing for array temporaries
Hi Paul, Could you provide the patch, please, or was it already posted? Actually, no. I was so intent on providing the test cases that I missed the patch itself :-) Here it is. Regards Thomas Index: fortran/expr.c === --- fortran/expr.c (Revision 270622) +++ fortran/expr.c (Arbeitskopie) @@ -5713,6 +5713,9 @@ gfc_is_simply_contiguous (gfc_expr *expr, bool str gfc_ref *ref, *part_ref = NULL; gfc_symbol *sym; + if (expr->expr_type == EXPR_ARRAY) +return true; + if (expr->expr_type == EXPR_FUNCTION) { if (expr->value.function.esym) Index: fortran/trans-array.c === --- fortran/trans-array.c (Revision 270622) +++ fortran/trans-array.c (Arbeitskopie) @@ -7869,6 +7869,23 @@ array_parameter_size (tree desc, gfc_expr *expr, t *size, fold_convert (gfc_array_index_type, elem)); } +/* Helper function - return true if the argument is a pointer. */ + +static bool +is_pointer (gfc_expr *e) +{ + gfc_symbol *sym; + + if (e->expr_type != EXPR_VARIABLE || e->symtree == NULL) +return false; + + sym = e->symtree->n.sym; + if (sym == NULL) +return false; + + return sym->attr.pointer || sym->attr.proc_pointer; +} + /* Convert an array for passing as an actual parameter. */ void @@ -8120,6 +8137,19 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * "Creating array temporary at %L", >where); } + /* When optmizing, we can use gfc_conv_subref_array_arg for + making the packing and unpacking operation visible to the + optimizers. */ + + if (g77 && optimize && !optimize_size && expr->expr_type == EXPR_VARIABLE + && !is_pointer (expr)) + { + gfc_conv_subref_array_arg (se, expr, g77, + fsym ? fsym->attr.intent : INTENT_INOUT, + false, fsym, proc_name, sym); + return; + } + ptr = build_call_expr_loc (input_location, gfor_fndecl_in_pack, 1, desc); Index: fortran/trans-expr.c === --- fortran/trans-expr.c (Revision 270622) +++ fortran/trans-expr.c (Arbeitskopie) @@ -4576,8 +4576,10 @@ gfc_apply_interface_mapping (gfc_interface_mapping an actual argument derived type array is copied and then returned after the function call. */ void -gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77, - sym_intent intent, bool formal_ptr) +gfc_conv_subref_array_arg (gfc_se *se, gfc_expr * expr, int g77, + sym_intent intent, bool formal_ptr, + const gfc_symbol *fsym, const char *proc_name, + gfc_symbol *sym) { gfc_se lse; gfc_se rse; @@ -4594,7 +4596,37 @@ void stmtblock_t body; int n; int dimen; + gfc_se work_se; + gfc_se *parmse; + bool pass_optional; + pass_optional = fsym && fsym->attr.optional && sym && sym->attr.optional; + + if (pass_optional) +{ + gfc_init_se (_se, NULL); + parmse = _se; +} + else +parmse = se; + + if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS) +{ + /* We will create a temporary array, so let us warn. */ + char * msg; + + if (fsym && proc_name) + msg = xasprintf ("An array temporary was created for argument " + "'%s' of procedure '%s'", fsym->name, proc_name); + else + msg = xasprintf ("An array temporary was created"); + + tmp = build_int_cst (logical_type_node, 1); + gfc_trans_runtime_check (false, true, tmp, >pre, + >where, msg); + free (msg); +} + gfc_init_se (, NULL); gfc_init_se (, NULL); @@ -4848,6 +4880,53 @@ class_array_fcn: else parmse->expr = gfc_build_addr_expr (NULL_TREE, parmse->expr); + if (pass_optional) +{ + tree present; + tree type; + stmtblock_t else_block; + tree pre_stmts, post_stmts; + tree pointer; + tree else_stmt; + + /* Make this into + + if (present (a)) + { + parmse->pre; + optional = parse->expr; + } + else + optional = NULL; + call foo (optional); + if (present (a)) +parmse->post; + + */ + + type = TREE_TYPE (parmse->expr); + pointer = gfc_create_var (type, "optional"); + tmp = gfc_conv_expr_present (sym); + present = gfc_evaluate_now (tmp, >pre); + gfc_add_modify (>pre, pointer, parmse->expr); + pre_stmts = gfc_finish_block (>pre); + + gfc_init_block (_block); + gfc_add_modify (_block, pointer, build_int_cst (type, 0)); + else_stmt = gfc_finish_block (_block); + + tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, present, + pre_stmts, else_stmt); + gfc_add_expr_to_block (>pre, tmp); + + post_stmts = gfc_finish_block (>post); + tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, present, + post_stmts, build_empty_stmt (input_location)); + gfc_add_expr_to_block (>post, tmp); + + se->expr =
Re: [patch, fortran] Inline packing for array temporaries
Hi Thomas, > (Dominique, could you tell us again what the magic incantation for > 32-bit mode is?) I use: time make -k -j8 check RUNTESTFLAGS="--target_board=unix'{-m32,-m64}'" > & check-*.log & Dominique
Re: [patch, fortran] Inline packing for array temporaries
Hi Thomas, Could you provide the patch, please, or was it already posted? Cheers Paul On Sun, 28 Apr 2019 at 10:46, Thomas Koenig wrote: > > Hello world, > > going back a patch which was not included in gcc-9 because it was too > late in the development cycle, here is a patch which, when optimizing > and not optimizing for size, does inline packing for an argument. > As you can see from the code and the test cases, there is provision > for optional arguments. It was necessary to split some test cases > to take account for the new pack inline / pack in the library split. > > I did regression-testing on x86_64-pc-linux-gnu, in 64-bit mode. > (Dominique, could you tell us again what the magic incantation for > 32-bit mode is?) > > OK for trunk? (Not for backporting) > > Regards > > Thomas > > 2019-04-28 Thomas Koenig > > PR fortran/88821 > * expr.c (gfc_is_simply_contiguous): Return true for > an EXPR_ARRAY. > * trans-array.c (is_pointer): New function. > (gfc_conv_array_parameter): Call gfc_conv_subref_array_arg > when not optimizing and not optimizing for size if the formal > arg is passed by reference. > * trans-expr.c (gfc_conv_subref_array_arg): Add arguments > fsym, proc_name and sym. Add run-time warning for temporary > array creation. Wrap argument if passing on an optional > argument to an optional argument. > * trans.h (gfc_conv_subref_array_arg): Add optional arguments > fsym, proc_name and sym to prototype. > > 2019-04-28 Thomas Koenig > > PR fortran/88821 > * gfortran.dg/alloc_comp_auto_array_3.f90: Add -O0 to dg-options > to make sure the test for internal_pack is retained. > * gfortran.dg/assumed_type_2.f90: Split compile and run time > tests into this and > * gfortran.dg/assumed_type_2a.f90: New file. > * gfortran.dg/c_loc_test_22.f90: Likewise. > * gfortran.dg/contiguous_3.f90: Likewise. > * gfortran.dg/internal_pack_11.f90: Likewise. > * gfortran.dg/internal_pack_12.f90: Likewise. > * gfortran.dg/internal_pack_16.f90: Likewise. > * gfortran.dg/internal_pack_17.f90: Likewise. > * gfortran.dg/internal_pack_18.f90: Likewise. > * gfortran.dg/internal_pack_4.f90: Likewise. > * gfortran.dg/internal_pack_5.f90: Add -O0 to dg-options > to make sure the test for internal_pack is retained. > * gfortran.dg/internal_pack_6.f90: Split compile and run time > tests into this and > * gfortran.dg/internal_pack_6a.f90: New file. > * gfortran.dg/internal_pack_8.f90: Likewise. > * gfortran.dg/missing_optional_dummy_6: Split compile and run time > tests into this and > * gfortran.dg/missing_optional_dummy_6a.f90: New file. > * gfortran.dg/no_arg_check_2.f90: Split compile and run time tests > into this and > * gfortran.dg/no_arg_check_2a.f90: New file. > * gfortran.dg/typebound_assignment_5.f90: Split compile and run > time > tests into this and > * gfortran.dg/typebound_assignment_5a.f90: New file. > * gfortran.dg/typebound_assignment_6.f90: Split compile and run > time > tests into this and > * gfortran.dg/typebound_assignment_6a.f90: New file. > * gfortran.dg/internal_pack_19.f90: New file. > * gfortran.dg/internal_pack_20.f90: New file. > * gfortran.dg/internal_pack_21.f90: New file. -- "If you can't explain it simply, you don't understand it well enough" - Albert Einstein
[patch, fortran] Inline packing for array temporaries
Hello world, going back a patch which was not included in gcc-9 because it was too late in the development cycle, here is a patch which, when optimizing and not optimizing for size, does inline packing for an argument. As you can see from the code and the test cases, there is provision for optional arguments. It was necessary to split some test cases to take account for the new pack inline / pack in the library split. I did regression-testing on x86_64-pc-linux-gnu, in 64-bit mode. (Dominique, could you tell us again what the magic incantation for 32-bit mode is?) OK for trunk? (Not for backporting) Regards Thomas 2019-04-28 Thomas Koenig PR fortran/88821 * expr.c (gfc_is_simply_contiguous): Return true for an EXPR_ARRAY. * trans-array.c (is_pointer): New function. (gfc_conv_array_parameter): Call gfc_conv_subref_array_arg when not optimizing and not optimizing for size if the formal arg is passed by reference. * trans-expr.c (gfc_conv_subref_array_arg): Add arguments fsym, proc_name and sym. Add run-time warning for temporary array creation. Wrap argument if passing on an optional argument to an optional argument. * trans.h (gfc_conv_subref_array_arg): Add optional arguments fsym, proc_name and sym to prototype. 2019-04-28 Thomas Koenig PR fortran/88821 * gfortran.dg/alloc_comp_auto_array_3.f90: Add -O0 to dg-options to make sure the test for internal_pack is retained. * gfortran.dg/assumed_type_2.f90: Split compile and run time tests into this and * gfortran.dg/assumed_type_2a.f90: New file. * gfortran.dg/c_loc_test_22.f90: Likewise. * gfortran.dg/contiguous_3.f90: Likewise. * gfortran.dg/internal_pack_11.f90: Likewise. * gfortran.dg/internal_pack_12.f90: Likewise. * gfortran.dg/internal_pack_16.f90: Likewise. * gfortran.dg/internal_pack_17.f90: Likewise. * gfortran.dg/internal_pack_18.f90: Likewise. * gfortran.dg/internal_pack_4.f90: Likewise. * gfortran.dg/internal_pack_5.f90: Add -O0 to dg-options to make sure the test for internal_pack is retained. * gfortran.dg/internal_pack_6.f90: Split compile and run time tests into this and * gfortran.dg/internal_pack_6a.f90: New file. * gfortran.dg/internal_pack_8.f90: Likewise. * gfortran.dg/missing_optional_dummy_6: Split compile and run time tests into this and * gfortran.dg/missing_optional_dummy_6a.f90: New file. * gfortran.dg/no_arg_check_2.f90: Split compile and run time tests into this and * gfortran.dg/no_arg_check_2a.f90: New file. * gfortran.dg/typebound_assignment_5.f90: Split compile and run time tests into this and * gfortran.dg/typebound_assignment_5a.f90: New file. * gfortran.dg/typebound_assignment_6.f90: Split compile and run time tests into this and * gfortran.dg/typebound_assignment_6a.f90: New file. * gfortran.dg/internal_pack_19.f90: New file. * gfortran.dg/internal_pack_20.f90: New file. * gfortran.dg/internal_pack_21.f90: New file. ! { dg-do run } ! { dg-options "-O -fdump-tree-original" } ! Test handling of the optional argument. MODULE M1 INTEGER, PARAMETER :: dp=KIND(0.0D0) CONTAINS SUBROUTINE S1(a) REAL(dp), DIMENSION(45), INTENT(OUT), & OPTIONAL :: a if (present(a)) STOP 1 END SUBROUTINE S1 SUBROUTINE S2(a) REAL(dp), DIMENSION(:, :), INTENT(OUT), & OPTIONAL :: a CALL S1(a) END SUBROUTINE END MODULE M1 USE M1 CALL S2() END ! { dg-final { scan-tree-dump-times "optional" 4 "original" } } ! { dg-final { scan-tree-dump-not "_gfortran_internal_unpack" "original" } } ! { dg-do compile } ! { dg-options "-O -fdump-tree-original" } ! Check that internal_pack is not called with -O. module x implicit none contains subroutine bar(a, n) integer, intent(in) :: n integer, intent(in), dimension(n) :: a print *,a end subroutine bar end module x program main use x implicit none integer, parameter :: n = 10 integer, dimension(n) :: a integer :: i a = [(i,i=1,n)] call bar(a(n:1:-1),n) end program main ! { dg-final { scan-tree-dump-not "_gfortran_internal_pack" "original" } } ! { dg-do compile } ! { dg-options "-Os -fdump-tree-original" } ! Check that internal_pack is called with -Os. module x implicit none contains subroutine bar(a, n) integer, intent(in) :: n integer, intent(in), dimension(n) :: a print *,a end subroutine bar end module x program main use x implicit none integer, parameter :: n = 10 integer, dimension(n) :: a integer :: i a = [(i,i=1,n)] call bar(a(n:1:-1),n) end program main ! { dg-final { scan-tree-dump-times "_gfortran_internal_pack" 1 "original"