> On 17 Jun 2026, at 10:22, Richard Biener <[email protected]> wrote:
> 
> On Wed, Jun 17, 2026 at 8:27 AM <[email protected]> wrote:
>> 
>> 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.
> 
> We generally do not what to have user-facing flags that say
> "it might generate wrong-code".  Instead we'd have asserting
> flags from the user, like -fdoconcurrent-are-parallelizable.  But
> as the underlying issue is not visible to the user this doesn't
> work in this case.
> 
> So please do not add such flag (flags need to be preserved
> forever).  Iff you really agree that you want it, use a
> --parm instead that we can freely remove.
> 
> But then, why not do this at the optimization phase of
> fortran and detect the problematic setup (temporaries
> it was, IIRC)?  Or even, when you detect them, mark
> them as to be localized?  Possibly both are not easily
> possible if there's function calls involved that might be
> inlined, exposing additional locals?

Drive by comment from me, but is the "wrong-code” risk here non-deterministic 
reassociation of FP operations?
So is this a fast-math-style wrong-code? Or does is it a more serious risk?
Thanks,
Kyrill

> 
>> 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