Re: [RFC][PATCH 2/2] fortran: Add -fdoconcurrent-force-parallel flag [PR125717]

Harald Anlauf <[email protected]> Wed, 17 Jun 2026 22:32:34 +0200
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.fortran
Message-ID <[email protected]>
Am 17.06.26 um 11:09 AM schrieb Richard Biener:
> On Wed, Jun 17, 2026 at 10:57 AM Dhruv Chawla <[email protected]> wrote:
>>
>> On 17/06/26 14:03, Kyrylo Tkachov wrote:
>> Yes, that is what it turned out to be - a caller-allocated stack array
>> used as return storage for a callee (`compute` in the test case) got
>> hoisted outside the loop (as its address was loop-invariant for a
>> single thread), so multiple threads ended up writing to the same address
>> thus leading to garbage output. This doesn't occur in the pot3d function,
>> so it is safe to ignore this bug.
> 
> But it must be possible to classify a conservatively safe subset of
> do concurrent loops from inside the frontend?  I'd really prefer that.

I do also see the data race for the temporary for the array-valued
function result of compute with -fsanitize=thread, which does not
occur when I use an ordinary OpenMP do loop instead of do concurrent.

So how does OpenMP annotate the temporary (it should be PRIVATE)?
And can this be used to annotate frontend-generated temporaries
for the auto-parallelizer?

(BTW: the testcase runs a factor of 10 faster for me when I replace

      tmp(k) = tmp(k) + (-1.0_real64)**(j+1) / real( 2*j-1 )

by

      tmp(k) = tmp(k) + (-1)**(j+1) / real( 2*j-1, real64)

because the power of integer (-1) is expanded inline.)

> autopar is essentially unmaintained ... but clearly the can_be_parallel
> flag isn't correct for the IL as-is?  While I looked into autpar years
> ago I don't remember much in what guarantees it makes, but I think
> all of the safety is with the dependence analysis we skip with
> can_be_parallel annotated loops.

I think the loop is fine (Fortran-wise).

I also tried to use an explicit temporary and making compute
a subroutine, like

...
   real(real64), dimension(nsplit) :: mytmp
...
   do concurrent (i = 1:nsplit) local (mytmp)
      call compute( low(i), high(i) , mytmp)
      pi(i) = sum (mytmp)
   end do

This avoids frontend-generated temporaries, but still has the same
data race.

Cheers,
Harald