]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR fortran/88821 (Inline packing of non-contiguous arguments)
authorThomas Koenig <tkoenig@gcc.gnu.org>
Sun, 19 May 2019 10:21:06 +0000 (10:21 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Sun, 19 May 2019 10:21:06 +0000 (10:21 +0000)
2019-05-19  Thomas Koenig  <tkoenig@gcc.gnu.org>

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-05-19  Thomas Koenig  <tkoenig@gcc.gnu.org>

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.

From-SVN: r271377

30 files changed:
gcc/fortran/expr.c
gcc/fortran/trans-array.c
gcc/fortran/trans-expr.c
gcc/fortran/trans.h
gcc/testsuite/gfortran.dg/alloc_comp_auto_array_3.f90
gcc/testsuite/gfortran.dg/assumed_type_2.f90
gcc/testsuite/gfortran.dg/assumed_type_2a.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/c_loc_test_22.f90
gcc/testsuite/gfortran.dg/contiguous_3.f90
gcc/testsuite/gfortran.dg/internal_pack_11.f90
gcc/testsuite/gfortran.dg/internal_pack_12.f90
gcc/testsuite/gfortran.dg/internal_pack_16.f90
gcc/testsuite/gfortran.dg/internal_pack_17.f90
gcc/testsuite/gfortran.dg/internal_pack_18.f90
gcc/testsuite/gfortran.dg/internal_pack_19.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/internal_pack_20.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/internal_pack_21.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/internal_pack_4.f90
gcc/testsuite/gfortran.dg/internal_pack_5.f90
gcc/testsuite/gfortran.dg/internal_pack_6.f90
gcc/testsuite/gfortran.dg/internal_pack_6a.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/internal_pack_9.f90
gcc/testsuite/gfortran.dg/missing_optional_dummy_6.f90
gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/no_arg_check_2.f90
gcc/testsuite/gfortran.dg/no_arg_check_2a.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/typebound_assignment_5.f03
gcc/testsuite/gfortran.dg/typebound_assignment_5a.f03 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/typebound_assignment_6.f03
gcc/testsuite/gfortran.dg/typebound_assignment_6a.f03 [new file with mode: 0644]

index 474e9ecc40136422a5354ddb1ef1c47c02e0398d..949eff19cdd5cabea0c99346e669fa408b66585d 100644 (file)
@@ -5713,6 +5713,9 @@ gfc_is_simply_contiguous (gfc_expr *expr, bool strict, bool permit_element)
   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 8a0de6140edab818cadef41d196d87816752ccda..9c96d897f4164bd74d6011725387929047b6577c 100644 (file)
@@ -7866,6 +7866,23 @@ array_parameter_size (tree desc, gfc_expr *expr, tree *size)
                           *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
@@ -8117,6 +8134,20 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
                         "Creating array temporary at %L", &expr->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) && (fsym == NULL
+                                   || fsym->ts.type != BT_ASSUMED))
+       {
+         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 3711c38b2f237addd465870137920a254d775481..b7a8456c021425647425fd2f21b913d0f4168aaa 100644 (file)
@@ -4576,8 +4576,10 @@ gfc_apply_interface_mapping (gfc_interface_mapping * 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,6 +4596,36 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
   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 (&work_se, NULL);
+      parmse = &work_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, &parmse->pre,
+                              &expr->where, msg);
+      free (msg);
+    }
 
   gfc_init_se (&lse, NULL);
   gfc_init_se (&rse, 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, &se->pre);
+      gfc_add_modify (&parmse->pre, pointer, parmse->expr);
+      pre_stmts = gfc_finish_block (&parmse->pre);
+
+      gfc_init_block (&else_block);
+      gfc_add_modify (&else_block, pointer, build_int_cst (type, 0));
+      else_stmt = gfc_finish_block (&else_block);
+
+      tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, present,
+                            pre_stmts, else_stmt);
+      gfc_add_expr_to_block (&se->pre, tmp);
+
+      post_stmts = gfc_finish_block (&parmse->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 (&se->post, tmp);
+
+      se->expr = pointer;
+    }
+
   return;
 }
 
index 273c75a422c071d65a2f19c35a3629243a8ede91..e0118abaf18ebb14173f66f32eec77dac42beca3 100644 (file)
@@ -532,7 +532,10 @@ int gfc_is_intrinsic_libcall (gfc_expr *);
 int gfc_conv_procedure_call (gfc_se *, gfc_symbol *, gfc_actual_arglist *,
                             gfc_expr *, vec<tree, va_gc> *);
 
-void gfc_conv_subref_array_arg (gfc_se *, gfc_expr *, int, sym_intent, bool);
+void gfc_conv_subref_array_arg (gfc_se *, gfc_expr *, int, sym_intent, bool,
+                               const gfc_symbol *fsym = NULL,
+                               const char *proc_name = NULL,
+                               gfc_symbol *sym = NULL);
 
 /* Generate code for a scalar assignment.  */
 tree gfc_trans_scalar_assign (gfc_se *, gfc_se *, gfc_typespec, bool, bool,
index 15f9ecb74de644a2e78dab726d6d7c8c69a4e6d9..2af089e84e8d12cf43d6ad8863df9aba74ed86f5 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! Test the fix for PR66082. The original problem was with the first
 ! call foo_1d.
index dce5ac6839c60bc132f6ffeab4ec2d13ee9b9d03..5d3cd7eaece948f4d754dd073c023855cd0be17e 100644 (file)
@@ -1,5 +1,5 @@
-! { dg-do run }
-! { dg-options "-fdump-tree-original" }
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! PR fortran/48820
 !
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_2a.f90 b/gcc/testsuite/gfortran.dg/assumed_type_2a.f90
new file mode 100644 (file)
index 0000000..125bfcb
--- /dev/null
@@ -0,0 +1,139 @@
+! { dg-do run }
+!
+! PR fortran/48820
+!
+! Test TYPE(*)
+!
+
+module mod
+  use iso_c_binding, only: c_loc, c_ptr, c_bool
+  implicit none
+  interface my_c_loc
+    function my_c_loc1(x) bind(C)
+      import c_ptr
+      type(*) :: x
+      type(c_ptr) :: my_c_loc1
+    end function
+    function my_c_loc2(x) bind(C)
+      import c_ptr
+      type(*) :: x(*)
+      type(c_ptr) :: my_c_loc2
+    end function
+  end interface my_c_loc
+contains
+  subroutine sub_scalar (arg1, presnt)
+     type(*), target, optional :: arg1
+     logical :: presnt
+     type(c_ptr) :: cpt
+     if (presnt .neqv. present (arg1)) STOP 1
+     cpt = c_loc (arg1)
+  end subroutine sub_scalar
+
+  subroutine sub_array_shape (arg2, lbounds, ubounds)
+     type(*), target :: arg2(:,:)
+     type(c_ptr) :: cpt
+     integer :: lbounds(2), ubounds(2)
+     if (any (lbound(arg2) /= lbounds)) STOP 2
+     if (any (ubound(arg2) /= ubounds)) STOP 3
+     if (any (shape(arg2) /= ubounds-lbounds+1)) STOP 4
+     if (size(arg2) /= product (ubounds-lbounds+1)) STOP 5
+     if (rank (arg2) /= 2) STOP 6
+!     if (.not. is_continuous (arg2)) STOP 7 !<< Not yet implemented
+!     cpt = c_loc (arg2) ! << FIXME: Valid since TS29113
+     call sub_array_assumed (arg2)
+  end subroutine sub_array_shape
+
+  subroutine sub_array_assumed (arg3)
+     type(*), target :: arg3(*)
+     type(c_ptr) :: cpt
+     cpt = c_loc (arg3)
+  end subroutine sub_array_assumed
+end module
+
+use mod
+use iso_c_binding, only: c_int, c_null_ptr
+implicit none
+type t1
+  integer :: a
+end type t1
+type :: t2
+  sequence
+  integer :: b
+end type t2
+type, bind(C) :: t3
+  integer(c_int) :: c
+end type t3
+
+integer            :: scalar_int
+real, allocatable  :: scalar_real_alloc
+character, pointer :: scalar_char_ptr
+
+integer            :: array_int(3)
+real, allocatable  :: array_real_alloc(:,:)
+character, pointer :: array_char_ptr(:,:)
+
+type(t1)              :: scalar_t1
+type(t2), allocatable :: scalar_t2_alloc
+type(t3), pointer     :: scalar_t3_ptr
+
+type(t1)              :: array_t1(4)
+type(t2), allocatable :: array_t2_alloc(:,:)
+type(t3), pointer     :: array_t3_ptr(:,:)
+
+class(t1), allocatable :: scalar_class_t1_alloc
+class(t1), pointer     :: scalar_class_t1_ptr
+
+class(t1), allocatable :: array_class_t1_alloc(:,:)
+class(t1), pointer     :: array_class_t1_ptr(:,:)
+
+scalar_char_ptr => null()
+scalar_t3_ptr => null()
+
+call sub_scalar (presnt=.false.)
+call sub_scalar (scalar_real_alloc, .false.)
+call sub_scalar (scalar_char_ptr, .false.)
+call sub_scalar (null (), .false.)
+call sub_scalar (scalar_t2_alloc, .false.)
+call sub_scalar (scalar_t3_ptr, .false.)
+
+allocate (scalar_real_alloc, scalar_char_ptr, scalar_t3_ptr)
+allocate (scalar_class_t1_alloc, scalar_class_t1_ptr, scalar_t2_alloc)
+allocate (array_real_alloc(3:5,2:4), array_char_ptr(-2:2,2))
+allocate (array_t2_alloc(3:5,2:4), array_t3_ptr(-2:2,2))
+allocate (array_class_t1_alloc(3,3), array_class_t1_ptr(4,4))
+
+call sub_scalar (scalar_int, .true.)
+call sub_scalar (scalar_real_alloc, .true.)
+call sub_scalar (scalar_char_ptr, .true.)
+call sub_scalar (array_int(2), .true.)
+call sub_scalar (array_real_alloc(3,2), .true.)
+call sub_scalar (array_char_ptr(0,1), .true.)
+call sub_scalar (scalar_t1, .true.)
+call sub_scalar (scalar_t2_alloc, .true.)
+call sub_scalar (scalar_t3_ptr, .true.)
+call sub_scalar (array_t1(2), .true.)
+call sub_scalar (array_t2_alloc(3,2), .true.)
+call sub_scalar (array_t3_ptr(0,1), .true.)
+call sub_scalar (array_class_t1_alloc(2,1), .true.)
+call sub_scalar (array_class_t1_ptr(3,3), .true.)
+
+call sub_array_assumed (array_int)
+call sub_array_assumed (array_real_alloc)
+call sub_array_assumed (array_char_ptr)
+call sub_array_assumed (array_t1)
+call sub_array_assumed (array_t2_alloc)
+call sub_array_assumed (array_t3_ptr)
+call sub_array_assumed (array_class_t1_alloc)
+call sub_array_assumed (array_class_t1_ptr)
+
+call sub_array_shape (array_real_alloc, [1,1], shape(array_real_alloc))
+call sub_array_shape (array_char_ptr, [1,1], shape(array_char_ptr))
+call sub_array_shape (array_t2_alloc, [1,1], shape(array_t2_alloc))
+call sub_array_shape (array_t3_ptr, [1,1], shape(array_t3_ptr))
+call sub_array_shape (array_class_t1_alloc, [1,1], shape(array_class_t1_alloc))
+call sub_array_shape (array_class_t1_ptr, [1,1], shape(array_class_t1_ptr))
+
+deallocate (scalar_char_ptr, scalar_class_t1_ptr, array_char_ptr)
+deallocate (array_class_t1_ptr, array_t3_ptr)
+
+end
index 5f4f9775b4a4d08198683c4ba039175e6f586389..9c40b26d83028f768a6373955927817581d9277f 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! PR fortran/56907
 !
index 724ec83ed1089f909480347af9252e5e28b407a6..ba0ccce8f9ee319767519e973fa24b76fa6d96bb 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! PR fortran/40632
 !
index a1d357cee735af576a0a46f9a0ed9b6a376ca945..c341a1bbc5faf4f851e45648f4eac17eff7f12f5 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! Test the fix for PR43173, where unnecessary calls to internal_pack/unpack
 ! were being produced below. These references are contiguous and so do not
index 55631c80e6e83a008a0ac0cc45b35e9c9e4092b8..da507322cbb01782952ffff5e1ac261c79dad019 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! Test the fix for PR43243, where unnecessary calls to internal_pack/unpack
 ! were being produced below. These references are contiguous and so do not
index 7e34c2bf7334142291132b3184c4be770fffdc6e..92c4b150db8274ad49d6f67afb997cbb2f3f40d5 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-O0 -fdump-tree-original" }
 ! PR 59345 - pack/unpack was not needed here.
 SUBROUTINE S1(A)
  REAL :: A(3)
index c1b813b0c91b541a61ed4fb1b3932b1dab4b1bc1..176ad879ba25377754da57c60d44c699b6304270 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-O0 -fdump-tree-original" }
 ! PR 59345 - pack/unpack was not needed here.
 ! Original test case by Joost VandeVondele 
 SUBROUTINE S1(A)
index ede0691bb9f69728935d635ab1ca19a472d42834..b4404726d12c793a8fdb9914f7916b115c414cca 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-O0 -fdump-tree-original" }
 ! PR 57992 - this was packed/unpacked unnecessarily.
 ! Original case by Tobias Burnus.
 subroutine test
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_19.f90 b/gcc/testsuite/gfortran.dg/internal_pack_19.f90
new file mode 100644 (file)
index 0000000..06b916b
--- /dev/null
@@ -0,0 +1,23 @@
+! { 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" } }
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_20.f90 b/gcc/testsuite/gfortran.dg/internal_pack_20.f90
new file mode 100644 (file)
index 0000000..f93f06b
--- /dev/null
@@ -0,0 +1,23 @@
+! { 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" } }
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_21.f90 b/gcc/testsuite/gfortran.dg/internal_pack_21.f90
new file mode 100644 (file)
index 0000000..d0ce942
--- /dev/null
@@ -0,0 +1,24 @@
+! { 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" } }
index 00f316414bcee255599e06d18ea808cd82e2bf3c..9de09ab072b5440fad63ba32e13792e1cdbc8d07 100644 (file)
@@ -1,5 +1,4 @@
 ! { dg-do run }
-! { dg-options "-fdump-tree-original" }
 !
 ! PR fortran/36132
 !
@@ -25,6 +24,3 @@ END MODULE M1
 USE M1
 CALL S2()
 END
-
-! { dg-final { scan-tree-dump-times "a != 0B \\? \\\(.*\\\) _gfortran_internal_pack" 1 "original" } }
-! { dg-final { scan-tree-dump-times "if \\(a != 0B &&" 1 "original" } }
index 3c5868f9efc1769f064f780cafbf5e434eb39951..360ade491b568e00abe2002c8b1ffde4fbea2637 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! PR fortran/36909
 !
index d6102761904a009867b429b03e0289575380ab90..6d52a8c98c4a18ed87524a683f37c630fd08cf5a 100644 (file)
@@ -1,5 +1,5 @@
-! { dg-do run }
-! { dg-options "-fdump-tree-original" }
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! Test the fix for PR41113 and PR41117, in which unnecessary calls
 ! to internal_pack and internal_unpack were being generated.
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_6a.f90 b/gcc/testsuite/gfortran.dg/internal_pack_6a.f90
new file mode 100644 (file)
index 0000000..a9fb2b5
--- /dev/null
@@ -0,0 +1,56 @@
+! { dg-do run }
+!
+! Test the fix for PR41113 and PR41117, in which unnecessary calls
+! to internal_pack and internal_unpack were being generated.
+!
+! Contributed by Joost VandeVondele <jv244@cam.ac.uk>
+!
+MODULE M1
+ TYPE T1
+   REAL :: data(10) = [(i, i = 1, 10)]
+ END TYPE T1
+CONTAINS
+ SUBROUTINE S1(data, i, chksum)
+   REAL, DIMENSION(*) :: data
+   integer :: i, j
+   real :: subsum, chksum
+   subsum = 0
+   do j = 1, i
+     subsum = subsum + data(j)
+   end do
+   if (abs(subsum - chksum) > 1e-6) STOP 1
+ END SUBROUTINE S1
+END MODULE
+
+SUBROUTINE S2
+ use m1
+ TYPE(T1) :: d
+
+ real :: data1(10) = [(i, i = 1, 10)]
+ REAL :: data(-4:5,-4:5) = reshape ([(real(i), i = 1, 100)], [10,10])
+
+! PR41113
+ CALL S1(d%data, 10, sum (d%data))
+ CALL S1(data1, 10, sum (data1))
+
+! PR41117
+ DO i=-4,5
+    CALL S1(data(:,i), 10, sum (data(:,i)))
+ ENDDO
+
+! With the fix for PR41113/7 this is the only time that _internal_pack
+! was called.  The final part of the fix for PR43072 put paid to it too.
+ DO i=-4,5
+    CALL S1(data(-2:,i), 8, sum (data(-2:,i)))
+ ENDDO
+ DO i=-4,4
+    CALL S1(data(:,i:i+1), 20, sum (reshape (data(:,i:i+1), [20])))
+ ENDDO
+ DO i=-4,5
+    CALL S1(data(2,i), 1, data(2,i))
+ ENDDO
+END SUBROUTINE S2
+
+ call s2
+end
+
index 9ce53f443543e9ce3dc2948a2d3623c3db2c7b69..2b44db5a805eda6fb4ff05ec0094fe9e1e369482 100644 (file)
@@ -1,5 +1,5 @@
 ! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! During the discussion of the fix for PR43072, in which unnecessary
 ! calls to internal PACK/UNPACK were being generated, the following,
index 4468ff159b942026ff278e5291974493712c6ef9..cb6de2ebf614d06bcc3dcad78976bd11e76ded34 100644 (file)
@@ -46,14 +46,3 @@ contains
   end subroutine scalar2
 
 end program test
-
-! { dg-final { scan-tree-dump-times "scalar2 \\(slr1" 1 "original" } }
-
-! { dg-final { scan-tree-dump-times "= es1 != 0B" 1 "original" } }
-! { dg-final { scan-tree-dump-times "assumed_shape2 \\(es1" 0 "original" } }
-! { dg-final { scan-tree-dump-times "explicit_shape2 \\(es1" 1 "original" } }
-
-! { dg-final { scan-tree-dump-times "= as1 != 0B" 2 "original" } }
-! { dg-final { scan-tree-dump-times "assumed_shape2 \\(as1" 0 "original" } }
-! { dg-final { scan-tree-dump-times "explicit_shape2 \\(as1" 0 "original" } }
-
diff --git a/gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90 b/gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90
new file mode 100644 (file)
index 0000000..0e08ed3
--- /dev/null
@@ -0,0 +1,59 @@
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
+!
+! PR fortran/41907
+!
+program test
+  implicit none
+  call scalar1 ()
+  call assumed_shape1 ()
+  call explicit_shape1 ()
+contains
+
+  ! Calling functions
+  subroutine scalar1 (slr1)
+    integer, optional :: slr1
+    call scalar2 (slr1)
+  end subroutine scalar1
+
+  subroutine assumed_shape1 (as1)
+    integer, dimension(:), optional :: as1
+    call assumed_shape2 (as1)
+    call explicit_shape2 (as1)
+  end subroutine assumed_shape1
+
+  subroutine explicit_shape1 (es1)
+    integer, dimension(5), optional :: es1
+    call assumed_shape2 (es1)
+    call explicit_shape2 (es1)
+  end subroutine explicit_shape1
+
+
+  ! Called functions
+  subroutine assumed_shape2 (as2)
+    integer, dimension(:),optional :: as2
+    if (present (as2)) STOP 1
+  end subroutine assumed_shape2
+
+  subroutine explicit_shape2 (es2)
+    integer, dimension(5),optional :: es2
+    if (present (es2)) STOP 2
+  end subroutine explicit_shape2
+
+  subroutine scalar2 (slr2)
+    integer, optional :: slr2
+    if (present (slr2)) STOP 3
+  end subroutine scalar2
+
+end program test
+
+! { dg-final { scan-tree-dump-times "scalar2 \\(slr1" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "= es1 != 0B" 1 "original" } }
+! { dg-final { scan-tree-dump-times "assumed_shape2 \\(es1" 0 "original" } }
+! { dg-final { scan-tree-dump-times "explicit_shape2 \\(es1" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "= as1 != 0B" 2 "original" } }
+! { dg-final { scan-tree-dump-times "assumed_shape2 \\(as1" 0 "original" } }
+! { dg-final { scan-tree-dump-times "explicit_shape2 \\(as1" 0 "original" } }
+
index fe334883a3e55a7a256cd3efa507ee63760b9a2d..3570b9719ebb3a30edcb8666680d628961430933 100644 (file)
@@ -1,5 +1,5 @@
-! { dg-do run }
-! { dg-options "-fdump-tree-original" }
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! PR fortran/39505
 ! 
diff --git a/gcc/testsuite/gfortran.dg/no_arg_check_2a.f90 b/gcc/testsuite/gfortran.dg/no_arg_check_2a.f90
new file mode 100644 (file)
index 0000000..dc4adcb
--- /dev/null
@@ -0,0 +1,121 @@
+! { dg-do run }
+!
+! PR fortran/39505
+! 
+! Test NO_ARG_CHECK
+! Copied from assumed_type_2.f90
+!
+
+module mod
+  use iso_c_binding, only: c_loc, c_ptr, c_bool
+  implicit none
+  interface my_c_loc
+    function my_c_loc1(x) bind(C)
+      import c_ptr
+!GCC$ attributes NO_ARG_CHECK :: x
+      type(*) :: x
+      type(c_ptr) :: my_c_loc1
+    end function
+  end interface my_c_loc
+contains
+  subroutine sub_scalar (arg1, presnt)
+     integer(8), target, optional :: arg1
+     logical :: presnt
+     type(c_ptr) :: cpt
+!GCC$ attributes NO_ARG_CHECK :: arg1
+     if (presnt .neqv. present (arg1)) STOP 1
+     cpt = c_loc (arg1)
+  end subroutine sub_scalar
+
+  subroutine sub_array_assumed (arg3)
+!GCC$ attributes NO_ARG_CHECK :: arg3
+     logical(1), target :: arg3(*)
+     type(c_ptr) :: cpt
+     cpt = c_loc (arg3)
+  end subroutine sub_array_assumed
+end module
+
+use mod
+use iso_c_binding, only: c_int, c_null_ptr
+implicit none
+type t1
+  integer :: a
+end type t1
+type :: t2
+  sequence
+  integer :: b
+end type t2
+type, bind(C) :: t3
+  integer(c_int) :: c
+end type t3
+
+integer            :: scalar_int
+real, allocatable  :: scalar_real_alloc
+character, pointer :: scalar_char_ptr
+
+integer            :: array_int(3)
+real, allocatable  :: array_real_alloc(:,:)
+character, pointer :: array_char_ptr(:,:)
+
+type(t1)              :: scalar_t1
+type(t2), allocatable :: scalar_t2_alloc
+type(t3), pointer     :: scalar_t3_ptr
+
+type(t1)              :: array_t1(4)
+type(t2), allocatable :: array_t2_alloc(:,:)
+type(t3), pointer     :: array_t3_ptr(:,:)
+
+class(t1), allocatable :: scalar_class_t1_alloc
+class(t1), pointer     :: scalar_class_t1_ptr
+
+class(t1), allocatable :: array_class_t1_alloc(:,:)
+class(t1), pointer     :: array_class_t1_ptr(:,:)
+
+scalar_char_ptr => null()
+scalar_t3_ptr => null()
+
+call sub_scalar (presnt=.false.)
+call sub_scalar (scalar_real_alloc, .false.)
+call sub_scalar (scalar_char_ptr, .false.)
+call sub_scalar (null (), .false.)
+call sub_scalar (scalar_t2_alloc, .false.)
+call sub_scalar (scalar_t3_ptr, .false.)
+
+allocate (scalar_real_alloc, scalar_char_ptr, scalar_t3_ptr)
+allocate (scalar_class_t1_alloc, scalar_class_t1_ptr, scalar_t2_alloc)
+allocate (array_real_alloc(3:5,2:4), array_char_ptr(-2:2,2))
+allocate (array_t2_alloc(3:5,2:4), array_t3_ptr(-2:2,2))
+allocate (array_class_t1_alloc(3,3), array_class_t1_ptr(4,4))
+
+call sub_scalar (scalar_int, .true.)
+call sub_scalar (scalar_real_alloc, .true.)
+call sub_scalar (scalar_char_ptr, .true.)
+call sub_scalar (array_int(2), .true.)
+call sub_scalar (array_real_alloc(3,2), .true.)
+call sub_scalar (array_char_ptr(0,1), .true.)
+call sub_scalar (scalar_t1, .true.)
+call sub_scalar (scalar_t2_alloc, .true.)
+call sub_scalar (scalar_t3_ptr, .true.)
+call sub_scalar (array_t1(2), .true.)
+call sub_scalar (array_t2_alloc(3,2), .true.)
+call sub_scalar (array_t3_ptr(0,1), .true.)
+call sub_scalar (array_class_t1_alloc(2,1), .true.)
+call sub_scalar (array_class_t1_ptr(3,3), .true.)
+
+call sub_array_assumed (array_int)
+call sub_array_assumed (array_real_alloc)
+call sub_array_assumed (array_char_ptr)
+call sub_array_assumed (array_t1)
+call sub_array_assumed (array_t2_alloc)
+call sub_array_assumed (array_t3_ptr)
+call sub_array_assumed (array_class_t1_alloc)
+call sub_array_assumed (array_class_t1_ptr)
+
+deallocate (scalar_char_ptr, scalar_class_t1_ptr, array_char_ptr)
+deallocate (array_class_t1_ptr, array_t3_ptr)
+contains
+  subroutine sub(x)
+    integer :: x(:)
+    call sub_array_assumed (x)
+  end subroutine sub
+end
index f176b841fc0c8d1234947f939bf038136ab86a2e..e7c9126b35c744bacfccea27c7e90a1b6a79b890 100644 (file)
@@ -1,5 +1,5 @@
-! { dg-do run }
-! { dg-options "-fdump-tree-original" }
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
 !
 ! PR fortran/49074
 ! ICE on defined assignment with class arrays.
diff --git a/gcc/testsuite/gfortran.dg/typebound_assignment_5a.f03 b/gcc/testsuite/gfortran.dg/typebound_assignment_5a.f03
new file mode 100644 (file)
index 0000000..b55b42b
--- /dev/null
@@ -0,0 +1,39 @@
+! { dg-do run }
+!
+! PR fortran/49074
+! ICE on defined assignment with class arrays.
+
+      module foo
+        type bar
+          integer :: i
+
+          contains
+
+          generic :: assignment (=) => assgn_bar
+          procedure, private :: assgn_bar
+        end type bar
+
+        contains
+
+        elemental subroutine assgn_bar (a, b)
+          class (bar), intent (inout) :: a
+          class (bar), intent (in) :: b
+
+          select type (b)
+          type is (bar)
+            a%i = b%i
+          end select
+
+          return
+        end subroutine assgn_bar
+      end module foo
+
+      program main
+        use foo
+
+        type (bar), allocatable :: foobar(:)
+
+        allocate (foobar(2))
+        foobar = [bar(1), bar(2)]
+        if (any(foobar%i /= [1, 2])) STOP 1
+      end program
index 1dbdb0cd2c00fcefe4dd602ceabb060f9d1b5924..40cd2d0b11674345575de3f00a3bd751538b7369 100644 (file)
@@ -1,5 +1,4 @@
 ! { dg-do run }
-! { dg-options "-fdump-tree-original" }
 !
 ! PR fortran/56136
 ! ICE on defined assignment with class arrays.
@@ -37,6 +36,3 @@
         IF (ANY(A(2::2)%I /= (/ ((50+2*I, I=1,SIZE(A)/4), J=1,2) /))) STOP 3
       END PROGRAM
 
-! { dg-final { scan-tree-dump-times "_gfortran_internal_pack" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_internal_unpack" 1 "original" } }
-
diff --git a/gcc/testsuite/gfortran.dg/typebound_assignment_6a.f03 b/gcc/testsuite/gfortran.dg/typebound_assignment_6a.f03
new file mode 100644 (file)
index 0000000..2dab4c7
--- /dev/null
@@ -0,0 +1,42 @@
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
+!
+! PR fortran/56136
+! ICE on defined assignment with class arrays.
+!
+! Original testcase by Alipasha <alipash.celeris@gmail.com>
+
+      MODULE A_TEST_M
+        TYPE :: A_TYPE
+          INTEGER :: I
+          CONTAINS
+          GENERIC :: ASSIGNMENT (=) => ASGN_A
+          PROCEDURE, PRIVATE :: ASGN_A
+        END TYPE
+
+        CONTAINS
+
+        ELEMENTAL SUBROUTINE ASGN_A (A, B)
+          CLASS (A_TYPE), INTENT (INOUT) :: A
+          CLASS (A_TYPE), INTENT (IN) :: B
+          A%I = B%I
+        END SUBROUTINE
+      END MODULE A_TEST_M
+      
+      PROGRAM ASGN_REALLOC_TEST
+        USE A_TEST_M
+        TYPE (A_TYPE), ALLOCATABLE :: A(:)
+        INTEGER :: I, J
+
+        ALLOCATE (A(100))
+        A = (/ (A_TYPE(I), I=1,SIZE(A)) /)
+        A(1:50) = A(51:100)
+        IF (ANY(A%I /= (/ ((50+I, I=1,SIZE(A)/2), J=1,2) /))) STOP 1
+        A(::2) = A(1:50)        ! pack/unpack
+        IF (ANY(A( ::2)%I /= (/ (50+I, I=1,SIZE(A)/2) /))) STOP 2
+        IF (ANY(A(2::2)%I /= (/ ((50+2*I, I=1,SIZE(A)/4), J=1,2) /))) STOP 3
+      END PROGRAM
+
+! { dg-final { scan-tree-dump-times "_gfortran_internal_pack" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_internal_unpack" 1 "original" } }
+