[PATCH] libgomp, fortran: Apply if clause to all sub-constructs in combined OpenMP constructs

Kwok Cheung Yeung kcy@codesourcery.com
Wed Jun 24 16:47:06 GMT 2020


Hello

There appears to be a bug in the handling of the 'if' clause (without a 
directive name modifier) for combined OpenMP constructs in the Fortran front-end:

static void
gfc_split_omp_clauses (gfc_code *code,
                        gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
{
...
  if (code->ext.omp_clauses != NULL)
    {
      if (mask & GFC_OMP_MASK_TARGET)
        {
          /* And this is copied to all.  */
          clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
            = code->ext.omp_clauses->if_expr;
        }

Currently, if 'target' is in the combined contruct, then the 'if' is applied to 
the 'parallel' construct, but there are combined constructs with 'target' but 
not 'parallel' (e.g. target teams distribute), which result in the 'if' not 
getting applied at all. This is also redundant, as the unmodified if is always 
applied to the 'parallel' construct if there is one.

The patch changes the behaviour to match what the common C/C++ FE does, which is 
to apply the 'if' to every applicable sub-construct in the combined construct. I 
have included a testcase to check that the if clauses have been applied 
correctly by the time it gets to the ME. I have also found a case that results 
in an ICE (using 'target parallel' with an 'if' clause) - I have commented out 
this out for now and filed it as PR 95869.

I have tested for regressions in the gfortran and libgomp testsuites. Okay for 
master/OG10?

Thanks

Kwok

-------------- next part --------------
commit 052993de7457af85d5749b2ab119ffcc65e341e5
Author: Kwok Cheung Yeung <kcy@codesourcery.com>
Date:   Thu Jun 18 12:40:16 2020 -0700

    libgomp, fortran: Apply if clause to all sub-constructs in combined OpenMP constructs
    
    The unmodified 'if' clause should be applied to all the sub-constructs that
    accept an 'if' clause in a combined OpenMP construct, and not just to the
    'parallel' sub-construct.
    
    2020-06-24  Kwok Cheung Yeung  <kcy@codesourcery.com>
    
    	gcc/fortran/
    	* trans-openmp.c (gfc_split_omp_clauses): Add if clause
    	to target and simd sub-constructs.
    
    	gcc/testsuite/
    	* gfortran.dg/gomp/combined-if.f90: New.

diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 7e2f625..67b7094 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -4748,7 +4748,7 @@ gfc_split_omp_clauses (gfc_code *code,
 	  clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
 	    = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
 	  /* And this is copied to all.  */
-	  clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
+	  clausesa[GFC_OMP_SPLIT_TARGET].if_expr
 	    = code->ext.omp_clauses->if_expr;
 	}
       if (mask & GFC_OMP_MASK_TEAMS)
@@ -4832,6 +4832,9 @@ gfc_split_omp_clauses (gfc_code *code,
 	  /* Duplicate collapse.  */
 	  clausesa[GFC_OMP_SPLIT_SIMD].collapse
 	    = code->ext.omp_clauses->collapse;
+	  /* And this is copied to all.  */
+	  clausesa[GFC_OMP_SPLIT_SIMD].if_expr
+	    = code->ext.omp_clauses->if_expr;
 	}
       if (mask & GFC_OMP_MASK_TASKLOOP)
 	{
diff --git a/gcc/testsuite/gfortran.dg/gomp/combined-if.f90 b/gcc/testsuite/gfortran.dg/gomp/combined-if.f90
new file mode 100644
index 0000000..383086c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/combined-if.f90
@@ -0,0 +1,110 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-omplower" }
+
+module combined_if
+  implicit none
+
+  integer, parameter :: N = 100
+  integer, parameter :: LIMIT = 60
+  integer :: i, j
+  integer, dimension(N) :: a = (/ (i, i = 1,N) /)
+contains
+  subroutine test_parallel_loop_simd
+    do j = 1, N
+      !$omp parallel do simd if(j .lt. LIMIT)
+      do i = 1, N
+        a(i) = a(i) + 1
+      end do
+    end do
+  end subroutine
+
+  ! TODO: This currently fails with an internal compiler error
+  ! (PR 95869)
+  !subroutine test_target_parallel
+  !  do j = 1, N
+  !    !$omp target parallel if(j .lt. LIMIT) map(tofrom: a(1:N))
+  !    do i = 1, N
+  !      a(i) = a(i) + 1
+  !    end do
+  !    !$omp end target parallel
+  !   end do
+  !end subroutine
+
+  subroutine test_target_parallel_loop
+    do j = 1, N
+      !$omp target parallel do if(j .lt. LIMIT) map(tofrom: a(1:N))
+      do i = 1, N
+        a(i) = a(i) + 1
+      end do
+    end do
+  end subroutine
+
+  subroutine test_target_parallel_loop_simd
+    do j = 1, N
+      !$omp target parallel do simd if(j .lt. LIMIT) map(tofrom: a(1:N))
+      do i = 1, N
+        a(i) = a(i) + 1
+      end do
+    end do
+  end subroutine
+
+  subroutine test_target_simd
+    do j = 1, N
+      !$omp target simd if(j .lt. LIMIT) map(tofrom: a(1:N))
+      do i = 1, N
+        a(i) = a(i) + 1
+      end do
+    end do
+  end subroutine
+
+  subroutine test_target_teams
+    do j = 1, N
+      !$omp target teams if(j .lt. LIMIT) map(tofrom: a(1:N))
+      do i = 1, N
+        a(i) = a(i) + 1
+      end do
+      !$omp end target teams
+    end do
+  end subroutine
+
+  subroutine test_target_teams_distribute
+    do j = 1, N
+      !$omp target teams distribute if(j .lt. LIMIT) map(tofrom: a(1:N))
+      do i = 1, N
+        a(i) = a(i) + 1
+      end do
+    end do
+  end subroutine
+
+  subroutine test_target_teams_distibute_simd
+    do j = 1, N
+      !$omp target teams distribute simd if(j .lt. LIMIT) map(tofrom: a(1:N))
+      do i = 1, N
+        a(i) = a(i) + 1
+      end do
+    end do
+  end subroutine
+
+  subroutine test_target_teams_distribute_parallel_loop
+    do j = 1, N
+      !$omp target teams distribute parallel do if(j .lt. LIMIT) map(tofrom: a(1:N))
+      do i = 1, N
+        a(i) = a(i) + 1
+      end do
+    end do
+  end subroutine
+    
+  subroutine test_target_teams_distribute_parallel_loop_simd
+    do j = 1, N
+      !$omp target teams distribute parallel do simd if(j .lt. LIMIT) map(tofrom: a(1:N))
+      do i = 1, N
+        a(i) = a(i) + 1
+      end do
+    end do
+  end subroutine
+
+end module
+
+! { dg-final { scan-tree-dump-times "(?n)#pragma omp target.* if\\(" 8 "omplower" } }
+! { dg-final { scan-tree-dump-times "(?n)#pragma omp simd.* if\\(" 7 "omplower" } }
+! { dg-final { scan-tree-dump-times "(?n)#pragma omp parallel.* if\\(" 5 "omplower" } }


More information about the Gcc-patches mailing list