[PATCH] Fortran: Added support for locality specs in DO CONCURRENT (Fortran 2018/23)
Tobias Burnus
tburnus@baylibre.com
Mon Jan 13 08:18:26 GMT 2025
Hi,
On 9/25/24 3:18 AM, Andre Vehreschild wrote:
>> @@ -3089,7 +3099,15 @@ typedef struct gfc_code
>> gfc_inquire *inquire;
>> gfc_wait *wait;
>> gfc_dt *dt;
>> - gfc_forall_iterator *forall_iterator;
>> +
>> + struct
>> + {
>> + gfc_forall_iterator *forall_iterator;
>> + gfc_expr_list *locality[LOCALITY_NUM];
>> + bool default_none;
>> + }
>> + concur;
>
> I am more than unhappy about that construct. Because every concurrent
> loop has
> a forall_iterator, but not every forall_iterator is a concurrent loop. I
> therefore propose to move the forall_iterator out of the struct and
> only have
> the concurrent specific elements in the struct. This would also reduce
> the
> changes significantly.
First, regarding the naming, Fortran 2018 had:
FORALL forall-header
[do-stmt …]
CONCURRENT forall-header
Thus, both do-concurrent and forall used both a forall-header.
Since Fortran 2023, there is now:
FORALL concurrent-header
etc.
Thus, in Fortran 2024 both use a concurrent-header.
* * *
On the technical side:
DO CONCURRENT (i = 1:5) mask(.true.) local(x) default(none)
This has two parts:
* A forall_iterator: 'i = 1:5' and one 'mask' expression
* A locality spec: default(none) local(x)
The forall-header is saved on mainline as:
new_st.expr1 = mask;
new_st.ext.forall_iterator = head;
Since Fortran 2018 (and for this patch) we additionally have to save
for 'do concurrent' somehow a boolean ('default(none)') and a list of
symbols (with knowledge about in which locality they appeared).
Storing the forall-header iterator in <gfc_code>.ext.forall_iterator
sounds fine, but where to put locality other data?
The most sensible place is to put it also into <gfc_code>.ext, but as
the latter is a union, we need to ensure that both the iterator *and*
the locality data is available. - Thus, we create a struct for
'do concurrent'. But as the forall-header / concurrent-header is identical,
it makes sense to also use the same struct for FORALL and not to duplicate
code here.
IMHO the current code is fine.
* * *
On 1/7/25 12:06 PM, Jerry D wrote:
> cannot understand why moving the forall_iterator from the
> sub-structure 'concur' back to where it was at the 'ext' sub-structure
> of typedef struct gfc_code. 'ext' is a union. I suspected there is an
> overlap going on there such that something is getting overwritten or
> optimized away.
Well, as mentioned, a DO CONCURRENT can have both. Assume a simple do-concurrent loop:
DO, concurrent (I = 0:4)
This will fill code.ext.forall_iterator, which is fine. When this being resolved
in resolve.cc, for checking the iterator, the access goes to
code.ext.forall_iterator
which is fine - this will work for the example above.
As next step, the locality is checked, accessing
code.ext.concurr.*
but that variable shares the memory (union!) with code.ext.forall_iterator. Thus,
accessing locality[0] will be identical to
static_cast<gfc_expr_list *>(code.ext.forall_iterator)
and this has a very high chance to crash.
When using 'do concurrent(i=0:5) local(x)', the code.ext.forall_iterator
would be already overridden during parsing.
* * *
I hope that helps!
Tobias
More information about the Fortran
mailing list