Re: [PATCH] Fortran: fix argument passing to CONTIGUOUS, TARGET dummy [PR97592]

2023-12-17 Thread Paul Richard Thomas
Hi Harald,

It might be a simple patch but I have to confess it took a while for me to
get my head around the difference between gfc_is_not_contiguous and
!gfc_is_simply_contigous :-(

Yes, this is OK for mainline and, after a short delay, for 13-branch.

Thanks for the patch

Paul


On Sat, 16 Dec 2023 at 18:28, Harald Anlauf  wrote:

> Dear all,
>
> the attached simple patch fixes a (9+) regression for passing
> to a CONTIGUOUS,TARGET dummy an *effective argument* that is
> contiguous, although the actual argument is not simply-contiguous
> (it is a pointer without the CONTIGOUS attribute in the PR).
>
> Since a previous attempt for a patch lead to regressions in
> gfortran.dg/bind-c-contiguous-3.f90, which is rather dense,
> I decided to enhance the current testcase with various
> combinations of actual and dummy arguments that allow to
> study whether a _gfortran_internal_pack is generated in
> places where we want to.  (_gfortran_internal_pack does not
> create a temporary when no packing is needed).
>
> Regtested on x86_64-pc-linux-gnu.  OK for mainline?
>
> I would like to backport this - after a grace period - to
> at least 13-branch.  Any objections here?
>
> Thanks,
> Harald
>
>


[PATCH] Fortran: fix argument passing to CONTIGUOUS,TARGET dummy [PR97592]

2023-12-16 Thread Harald Anlauf
Dear all,

the attached simple patch fixes a (9+) regression for passing
to a CONTIGUOUS,TARGET dummy an *effective argument* that is
contiguous, although the actual argument is not simply-contiguous
(it is a pointer without the CONTIGOUS attribute in the PR).

Since a previous attempt for a patch lead to regressions in
gfortran.dg/bind-c-contiguous-3.f90, which is rather dense,
I decided to enhance the current testcase with various
combinations of actual and dummy arguments that allow to
study whether a _gfortran_internal_pack is generated in
places where we want to.  (_gfortran_internal_pack does not
create a temporary when no packing is needed).

Regtested on x86_64-pc-linux-gnu.  OK for mainline?

I would like to backport this - after a grace period - to
at least 13-branch.  Any objections here?

Thanks,
Harald

From d8765bd669e501781672c0bec976b2f5fd7acff6 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Sat, 16 Dec 2023 19:14:55 +0100
Subject: [PATCH] Fortran: fix argument passing to CONTIGUOUS,TARGET dummy
 [PR97592]

gcc/fortran/ChangeLog:

	PR fortran/97592
	* trans-expr.cc (gfc_conv_procedure_call): For a contiguous dummy
	with the TARGET attribute, the effective argument may still be
	contiguous even if the actual argument is not simply-contiguous.
	Allow packing to be decided at runtime by _gfortran_internal_pack.

gcc/testsuite/ChangeLog:

	PR fortran/97592
	* gfortran.dg/contiguous_15.f90: New test.
---
 gcc/fortran/trans-expr.cc   |   4 +-
 gcc/testsuite/gfortran.dg/contiguous_15.f90 | 234 
 2 files changed, 237 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.dg/contiguous_15.f90

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index f4185db5b7f..218fede6a82 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -7124,7 +7124,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
 	 INTENT_IN, fsym->attr.pointer);
 		}
 	  else if (fsym && fsym->attr.contiguous
-		   && !gfc_is_simply_contiguous (e, false, true)
+		   && (fsym->attr.target
+			   ? gfc_is_not_contiguous (e)
+			   : !gfc_is_simply_contiguous (e, false, true))
 		   && gfc_expr_is_variable (e))
 		{
 		  gfc_conv_subref_array_arg (, e, nodesc_arg,
diff --git a/gcc/testsuite/gfortran.dg/contiguous_15.f90 b/gcc/testsuite/gfortran.dg/contiguous_15.f90
new file mode 100644
index 000..424eb080fd1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/contiguous_15.f90
@@ -0,0 +1,234 @@
+! { dg-do run }
+! { dg-additional-options "-fdump-tree-original" }
+!
+! PR fortran/97592 - fix argument passing to CONTIGUOUS,TARGET dummy
+!
+! { dg-final { scan-tree-dump-times "_gfortran_internal_pack \\(_2d" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_internal_pack \\(" 3 "original" } }
+!
+! N.B.: there is no reliable count of _gfortran_internal_pack on temporaries parm.*
+
+program pr97592
+  implicit none
+  integer :: i, k
+  integer, target  :: a(10)
+  integer, pointer :: p1(:), p2(:), tgt(:), expect(:)
+  integer, pointer, contiguous :: cp(:)
+  integer, allocatable, target :: b(:)
+
+  !--
+  ! Code from original PR
+  !--
+  call RemappingTest ()
+
+  !-
+  ! Additional 1-d tests
+  !-
+  a = [(i, i=1,size(a))]
+  b = a
+
+  ! Set p1 to an actually contiguous pointer
+  p1(13:) => a(3::2)
+  print *, lbound (p1), ubound (p1), is_contiguous (p1)
+
+  ! non-contiguous pointer actual argument
+  expect => p1
+  call chk_cont (p1)
+
+  expect => p1
+  call chk_tgt_cont (p1)
+
+  expect => p1
+  call chk_ptr  (p1, p2)
+  if (any (p2 /= p1)) stop 1
+
+  expect => p1
+  call chk_tgt  (p1, p2)
+  if (any (p2 /= p1)) stop 2
+
+  ! non-contiguous target actual argument
+  expect => b(3::2)
+  call chk_tgt_cont (b(3::2))
+
+  expect => b(3::2)
+  call chk_tgt (b(3::2), p2)
+  if (any (p2 /= p1)) stop 3
+
+  expect => b(3::2)
+  call chk_ptr  (b(3::2), p2)
+  if (any (p2 /= p1)) stop 4
+
+  ! Set p1 to an actually contiguous pointer
+  cp(17:) => a(3:9:1)
+  p1 => cp
+  print *, lbound (cp), ubound (cp), is_contiguous (cp)
+  print *, lbound (p1), ubound (p1), is_contiguous (p1)
+
+  expect => p1
+  call chk_tgt  (p1, p2)
+  if (any (p2 /= cp)) stop 31
+
+  expect => cp
+  call chk_tgt  (cp, p2)
+  if (any (p2 /= cp)) stop 32
+
+  expect => cp
+  call chk_tgt_cont (cp, p2)
+  if (any (p2 /= cp)) stop 33
+
+  expect => cp
+  call chk_tgt_expl (cp, p2, size (cp))
+  if (any (p2 /= cp)) stop 34
+
+  ! See F2018:15.5.2.4 and F2018:C.10.4
+  expect => p1
+  call chk_tgt_cont (p1, p2)
+! print *, p2
+  if (any (p2 /= cp)) stop 35
+
+  expect => p1
+  call chk_tgt_expl (p1, p2, size (p1))
+  if (any (p2 /= cp)) stop 36
+
+  expect => cp
+  call chk_ptr_cont (