diff mbox series

fortran, openmp: PR fortran/93660 Fix ICE when coarrays used with 'omp declare simd'

Message ID 414d9b58-84fb-c2ba-8a36-f46cd8817334@codesourcery.com
State New
Headers show
Series fortran, openmp: PR fortran/93660 Fix ICE when coarrays used with 'omp declare simd' | expand

Commit Message

Kwok Cheung Yeung Sept. 10, 2020, 10:51 p.m. UTC
Hello

The ICE from the test case in PR93660 is due to the hidden caf_token and 
caf_offset parameters generated by the Fortran front end due to the use of coarrays:

  <function_decl 0x7ffff74e7400 f
     type <function_type 0x7ffff74ed1f8
         ...
         arg-types <tree_list 0x7ffff74e6a28 value <pointer_type 0x7ffff74ed000>
             chain <tree_list 0x7ffff731db18 value <void_type 0x7ffff731ef18 void>>>
     ...
     arguments <parm_decl 0x7ffff74d4400 x
         type <pointer_type 0x7ffff74ed000 type <integer_type 0x7ffff74e9a80 
integer(kind=4)>
             ...
         readonly used unsigned DI passed-by-reference simd_coarray_1.f90:16:0 
size <integer_cst 0x7ffff7309bb8 64> unit-size <integer_cst 0x7ffff7309bd0 8>
         align:64 warn_if_not_align:0 context <function_decl 0x7ffff74e7400 f> 
arg-type <pointer_type 0x7ffff74ed000>
         chain <parm_decl 0x7ffff74d4480 caf_token.2 type <pointer_type 
0x7ffff732b498>
             readonly unsigned DI simd_coarray_1.f90:16:0 size <integer_cst 
0x7ffff7309bb8 64> unit-size <integer_cst 0x7ffff7309bd0 8>
             align:64 warn_if_not_align:0 context <function_decl 0x7ffff74e7400 
f> arg-type <pointer_type 0x7ffff74ed000> chain <parm_decl 0x7ffff74d4500 
caf_offset.3>>>
     struct-function 0x7ffff74e8210 chain <function_decl 0x7ffff74e7800 
_caf_init.15>>

simd_clone_vector_of_formal_parm_types prefers to use the TYPE_ARG_TYPES of a 
function decl if available, but they do not contain entries for the hidden caf_* 
parameters. Replacements are therefore not generated for them, and the ICE 
occurs in ipa_simd_modify_function_body due to an assert firing when a 
replacement is not found for these hidden arguments.

This patch fixes this by choosing between TYPE_ARG_TYPES and DECL_ARGUMENT types 
depending on which one provides more types, preferring TYPE_ARG_TYPES if equal 
to remain closer to the previous behaviour. I tried simply always preferring 
DECL_ARGUMENT types, but that causes issues with the tests in g++.dg/gomp/.

Tested with no regressions in the gomp/ tests for gcc, g++ and gfortran, and no 
regressions in libgomp with Nvidia offloading.

Okay for trunk?

Thanks

Kwok
commit e842728189edc14c3f8b7c0a93cb51b007f20220
Author: Kwok Cheung Yeung <kcy@codesourcery.com>
Date:   Thu Sep 10 13:59:51 2020 -0700

    Fix ICE when coarrays used with the OpenMP 'declare simd' directive
    
    The ICE occurs when Fortran coarrays are used in conjunction with the
    'omp declare simd' directive, and the '-fopenmp' and '-fcoarray=lib' flags
    are used.
    
    2020-09-10  Kwok Cheung Yeung  <kcy@codesourcery.com>
    	    Tobias Burnus  <tobias@codesourcery.com>
    
    	gcc/
    	PR fortran/93660
    	* omp-simd-clone.c (simd_clone_vector_of_formal_parm_types): Choose
    	method of acquiring types that will result in a larger number of
    	types.
    
    	gcc/testsuite/
    	PR fortran/93660
    	* gfortran.dg/gomp/pr93660.f90: New.
    
    	libgomp/
    	PR fortran/93660
    	* testsuite/libgomp.fortran/coarray-simd.f90: New.

Comments

Jakub Jelinek Sept. 11, 2020, 7:31 a.m. UTC | #1
On Thu, Sep 10, 2020 at 11:51:51PM +0100, Kwok Cheung Yeung wrote:
> simd_clone_vector_of_formal_parm_types prefers to use the TYPE_ARG_TYPES of
> a function decl if available, but they do not contain entries for the hidden
> caf_* parameters. Replacements are therefore not generated for them, and the
> ICE occurs in ipa_simd_modify_function_body due to an assert firing when a
> replacement is not found for these hidden arguments.

So, isn't it a bug that TYPE_ARG_TYPES is inconsistent with DECL_ARGUMENTS
on the hidden arguments?  That looks like lying to the middle-end to me,
one doesn't have always a declaration with DECL_ARGUMENTS around, so
sometimes TYPE_ARG_TYPES is the only way to get at the argument types.
We had e.g. PR92305 in the past...

	Jakub
diff mbox series

Patch

diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
index 942fb97..e9084c7 100644
--- a/gcc/omp-simd-clone.c
+++ b/gcc/omp-simd-clone.c
@@ -86,23 +86,36 @@  simd_clone_struct_copy (struct cgraph_simd_clone *to,
 			* sizeof (struct cgraph_simd_clone_arg))));
 }
 
-/* Fill an empty vector ARGS with parameter types of function FNDECL.  This
-   uses TYPE_ARG_TYPES if available, otherwise falls back to types of
-   DECL_ARGUMENTS types.  */
+/* Fill an empty vector ARGS with parameter types of function FNDECL.
+   The parameters can be acquired using the TYPE_ARG_TYPES or the
+   DECL_ARGUMENTS types - whichever provides the larger number of types is
+   used.  These can differ if one or the other is not available, or if there
+   are hidden parameters (e.g. with Fortran coarrays).  In the event of a tie,
+   prefer using the TYPE_ARG_TYPES.  */
 
 static void
 simd_clone_vector_of_formal_parm_types (vec<tree> *args, tree fndecl)
 {
-  if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+  int arg_type_count = 0, decl_arg_count = 0;
+  tree t;
+
+  for (t = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); t; t = TREE_CHAIN (t))
+    arg_type_count++;
+  for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
+    decl_arg_count++;
+
+  gcc_assert (arg_type_count || decl_arg_count);
+
+  if (arg_type_count >= decl_arg_count)
+    push_function_arg_types (args, TREE_TYPE (fndecl));
+  else
     {
-      push_function_arg_types (args, TREE_TYPE (fndecl));
-      return;
+      push_function_arg_decls (args, fndecl);
+      unsigned int i;
+      tree arg;
+      FOR_EACH_VEC_ELT (*args, i, arg)
+	(*args)[i] = TREE_TYPE ((*args)[i]);
     }
-  push_function_arg_decls (args, fndecl);
-  unsigned int i;
-  tree arg;
-  FOR_EACH_VEC_ELT (*args, i, arg)
-    (*args)[i] = TREE_TYPE ((*args)[i]);
 }
 
 /* Given a simd function in NODE, extract the simd specific
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr93660.f90 b/gcc/testsuite/gfortran.dg/gomp/pr93660.f90
new file mode 100644
index 0000000..999ccb2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/pr93660.f90
@@ -0,0 +1,8 @@ 
+! { dg-do compile }
+! { dg-additional-options "-fcoarray=lib -lcaf_single" }
+
+integer function f(x)
+   integer :: x[*]
+   !$omp declare simd
+   f = x[1]
+end
diff --git a/libgomp/testsuite/libgomp.fortran/coarray-simd.f90 b/libgomp/testsuite/libgomp.fortran/coarray-simd.f90
new file mode 100644
index 0000000..debdf5d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/coarray-simd.f90
@@ -0,0 +1,51 @@ 
+! { dg-do run }
+! { dg-additional-options "-fcoarray=lib -lcaf_single" }
+
+program coarray_simd
+  implicit none
+  integer :: i, j
+  integer :: A(5)[*]
+  integer, allocatable :: B(:,:)[:,:], C(:,:)
+
+  A = [1,2,3,4,5]
+  if (any(f(A) /= [1,2,3,4,5])) stop 1
+
+  allocate(B(5,5)[1:5,7:*])
+  C = f2(B)
+  do i = 1, 5
+    do j = 1, 5
+      if (5 * B(j,i) /= C(j,i)) stop 2
+    end do
+  end do
+
+  C = f3(B)
+  do i = 1, 5
+    do j = 1, 5
+      if (99 * B(j,i) /= C(j,i)) stop 3
+    end do
+  end do
+contains
+  integer function f(x)
+    integer :: x(5)[*]
+    dimension :: f(5)
+    !$omp declare simd
+    f = x(:)[1]
+  end function
+
+  integer function f2(x)
+    integer, allocatable :: x(:,:)[:,:]
+    allocatable :: f2
+    dimension :: f2(:,:)
+    !$omp declare simd
+    f2 = x(:,:)[1,7] * 5
+  end function
+
+  integer function f3(x)
+    integer :: x(:,:)[1:5,*]
+    allocatable :: f3
+    dimension :: f3(:,:)
+    !$omp declare simd
+    f3 = x(:,:)[1,1] * 99
+  end function
+end
+