From: Dhruv Chawla <[email protected]>

This flag causes the frontend to emit annot_expr_parallel_kind for
do-concurrent loops, bypassing the PR83064 fix which would emit
annot_expr_ivdep_kind. This flag is meant to be a temporary fix, and
it along with patch 1 of this series recovers most of the performance gap
between flang and gfortran for SPEC2026 pot3d_s (speeding it up roughly
5x), modulo libgomp performance issues.

Bootstrapped and regtested on aarch64-linux-gnu.

Signed-off-by: Dhruv Chawla <[email protected]>

gcc/fortran/ChangeLog:

        PR fortran/125717
        * invoke.texi: Document the option.
        * lang.opt: Add -fdoconcurrent-force-parallel.
        * trans-stmt.cc (gfc_trans_forall_loop): Emit
        annot_expr_parallel_kind when flag_doconcurrent_force_parallel
        is set.

gcc/testsuite/ChangeLog:

        * gfortran.dg/lto/do_concurrent_16_0.f90: New test.
---
 gcc/fortran/invoke.texi                       |  9 +++-
 gcc/fortran/lang.opt                          |  4 ++
 gcc/fortran/trans-stmt.cc                     |  9 ++--
 .../gfortran.dg/lto/do_concurrent_16_0.f90    | 53 +++++++++++++++++++
 4 files changed, 71 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/lto/do_concurrent_16_0.f90

diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 69c4fa69cc6..55a3fe3487b 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -191,7 +191,8 @@ and warnings}.
 -fbounds-check -ftail-call-workaround -ftail-call-workaround=@var{n}
 -fcheck-array-temporaries
 -fcheck=<all|array-temps|bits|bounds|do|mem|pointer|recursion>
--fcoarray=<none|single|shared|lib> -fexternal-blas -fexternal-blas64 -ff2c
+-fcoarray=<none|single|shared|lib> -fdoconcurrent-force-parallel
+-fexternal-blas -fexternal-blas64 -ff2c
 -ffrontend-loop-interchange -ffrontend-optimize
 -finit-character=@var{n} -finit-integer=@var{n} -finit-local-zero
 -finit-derived -finit-logical=<true|false>
@@ -2070,6 +2071,12 @@ size and also compilation time may become excessive.  If 
that is the
 case, it may be better to disable this option.  Instances of packing
 can be found by using @option{-Warray-temporaries}.
 
+@opindex fdoconcurrent-force-parallel
+@item -fdoconcurrent-force-parallel
+This option forces parallelization of do-concurrent loops, bypassing the
+usual validity analysis done by the compiler. This can introduce correctness
+issues, so it should be used with caution.
+
 @opindex fexternal-blas
 @item -fexternal-blas
 This option makes @command{gfortran} generate calls to BLAS functions
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 6266d7f71bd..f90128a2cf3 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -554,6 +554,10 @@ fdefault-real-16
 Fortran Var(flag_default_real_16)
 Set the default real kind to an 16 byte wide type.
 
+fdoconcurrent-force-parallel
+Fortran Var(flag_doconcurrent_force_parallel)
+Force auto-parallelization of do-concurrent loops.
+
 fdollar-ok
 Fortran Var(flag_dollar_ok)
 Allow dollar signs in entity names.
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 0b1a8fa6b14..b89a9347394 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -4390,11 +4390,14 @@ gfc_trans_forall_loop (forall_info *forall_tmp, tree 
body,
                              count, build_int_cst (TREE_TYPE (count), 0));
 
       /* PR 83064 means that we cannot use annot_expr_parallel_kind until
-       the autoparallelizer can handle this.  */
+       the autoparallelizer can handle this.  For now, use a flag to bypass
+       the ivdep analysis for cases where the bug doesn't manifest itself.  */
+      annot_expr_kind kind = annot_expr_ivdep_kind;
+      if (flag_doconcurrent_force_parallel && forall_tmp->do_concurrent)
+       kind = annot_expr_parallel_kind;
       if (forall_tmp->do_concurrent || iter->annot.ivdep)
        cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
-                      build_int_cst (integer_type_node,
-                                     annot_expr_ivdep_kind),
+                      build_int_cst (integer_type_node, kind),
                       integer_zero_node);
 
       if (iter->annot.unroll && cond != error_mark_node)
diff --git a/gcc/testsuite/gfortran.dg/lto/do_concurrent_16_0.f90 
b/gcc/testsuite/gfortran.dg/lto/do_concurrent_16_0.f90
new file mode 100644
index 00000000000..7b0419854cd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/lto/do_concurrent_16_0.f90
@@ -0,0 +1,53 @@
+! { dg-lto-do link }
+! { dg-require-effective-target pthread }
+! { dg-lto-options { { -O2 -flto -fdoconcurrent-force-parallel 
-ftree-parallelize-loops=2 -fdump-tree-parloops2-details } } }
+!
+! Testcase taken from PR fortran/83064
+
+program main
+    use, intrinsic :: iso_fortran_env
+    implicit none
+
+    integer, parameter :: nsplit = 4
+    integer(int64), parameter :: ne = 100000
+    integer(int64) :: stride, low(nsplit), high(nsplit), edof(ne), i
+    real(real64), dimension(nsplit) :: pi
+
+    edof(1::4) = 1
+    edof(2::4) = 2
+    edof(3::4) = 3
+    edof(4::4) = 4
+
+    stride = ceiling(real(ne)/nsplit)
+    do i = 1, nsplit
+        high(i) = stride*i
+    end do
+    do i = 2, nsplit
+        low(i) = high(i-1) + 1
+    end do
+    low(1) = 1
+    high(nsplit) = ne
+
+    pi = 0
+    do concurrent (i = 1:nsplit)
+        pi(i) = sum(compute( low(i), high(i) ))
+    end do
+    print *, "PI", 4*sum(pi)
+
+contains
+
+    pure function compute( low, high ) result( tmp )
+        integer(int64), intent(in) :: low, high
+        real(real64), dimension(nsplit) :: tmp
+        integer(int64) :: j, k
+
+        tmp = 0
+        do j = low, high
+            k = edof(j)
+            tmp(k) = tmp(k) + (-1.0_real64)**(j+1) / real( 2*j-1 )
+        end do
+    end function
+
+end program main
+
+! { dg-final { scan-ltrans-tree-dump "parallelizing \[^\n\r\]*loop" 
"parloops2" } }
-- 
2.43.0

Reply via email to