llvm-project
dfc43d30 - [flang] Fix references to a LOCAL variable of an enclosing DO CONCURRENT (#238647)

Commit
10 days ago
[flang] Fix references to a LOCAL variable of an enclosing DO CONCURRENT (#238647) A `REDUCE` locality-spec on a nested `DO CONCURRENT` that names a variable with `LOCAL` or `LOCAL_INIT` locality in the enclosing `DO CONCURRENT` crashes lowering: ```fortran subroutine s(n, nz, work) integer :: n, nz, work(nz), j, k, tmp do concurrent (k=1:nz) local(tmp) tmp = 0 do concurrent (j=1:n) reduce(max:tmp) tmp = max(tmp, j) end do work(k) = tmp end do end subroutine ``` ``` Assertion `detail::isPresent(Val) && "dyn_cast on a non-existent value"' failed. ... ReductionProcessor::processReductionArguments<fir::DeclareReductionOp, ...> FirConverter::handleLocalitySpecs ``` Related references to such a variable silently used the wrong storage: - a `VOLATILE` statement for it in a `BLOCK` gave the `BLOCK` its own copy; - a `BLOCK` that makes it implicitly `ASYNCHRONOUS` used the subprogram's variable; - a nested `LOCAL_INIT` copy was initialized from the subprogram's variable instead of the enclosing construct's copy (F2023 11.1.7.5), with delayed privatization (the default). ### Root cause - `ScopeHandler::MakeHostAssocSymbol` copies all flags of the host symbol. When the host is a construct entity of an enclosing `DO CONCURRENT`, those flags include that construct's locality. - `SymMap` keys a symbol with `LOCAL`/`LOCAL_INIT` locality on the symbol itself and every other symbol on its ultimate symbol. A host-associated name that inherited the flag got its own key: for a nested `REDUCE` entity that key is bound only after `processReductionArguments` runs (null address, the crash), and for a `VOLATILE` name in a `BLOCK` it got fresh storage. A host-associated name without the flag was keyed on the subprogram's variable, bypassing the enclosing construct's copy. - DO CONCURRENT delayed privatization looked up the original value from the ultimate symbol. ### Fix - **Semantics** (`resolve-names.cpp`): `MakeHostAssocSymbol` does not copy the `Locality*` flags. Locality belongs to the construct entity that owns the storage. - **Lowering** (`SymbolMap.h/.cpp`): `SymMap::getKey` walks the host-association chain and keys a symbol on the nearest `LOCAL`/`LOCAL_INIT` entity, falling back to the ultimate symbol as before. It replaces the previous key computation at all eight sites. - **Lowering** (`Support/Utils.cpp`): `privatizeSymbol` looks up a DO CONCURRENT locality entity's original value from its host symbol, so it reaches the enclosing construct's copy. The ultimate symbol still names the privatizer. ### Behavior changes beyond the crash - A `LOCAL` entity nested in a `LOCAL_INIT` entity no longer inherits `LOCAL_INIT`. It now gets a `local` locality op instead of `local_init`. Both conform, since a `LOCAL` variable starts undefined. - An OpenACC compute construct around an outer `LOCAL` / inner `REDUCE` DO CONCURRENT nest used to stop with "not yet implemented: lowering symbol to HLFIR". It now lowers. ### Tests - `flang/test/Lower/do_concurrent_nested_locality.f90` (new): inner `REDUCE` in an enclosing `LOCAL` and `LOCAL_INIT`, two `REDUCE` levels, `LOCAL_INIT` in `LOCAL`, `LOCAL` in `LOCAL_INIT`, and `BLOCK`s with an explicit `VOLATILE` statement and with implied `ASYNCHRONOUS`. It covers delayed and non-delayed privatization where they differ. - `flang/test/Semantics/symbol09.f90`: nested locality-specs and a `VOLATILE` name in a `BLOCK` carry only their own locality. `check-flang` passes. Assisted-by: AI
Author
Parents
Loading