llvm / llvm/llvm-project

[flang][CUDA] Crash lowering !$cuf kernel do(n) over a mixed DO / DO CONCURRENT nest

Open
#224,355 1 comment 0 reactions 0 assignees View on GitHub
crash flang:ir
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

A `!$cuf kernel do(n)` directive whose loop nest mixes an ordinary counted DO
with an inner multi-index DO CONCURRENT is accepted by semantic analysis but
crashes the compiler during lowering:

```fortran
subroutine cuf_mixed(n, a)
integer :: n
integer, device :: a(n,n,n)
integer :: i, j, k
!$cuf kernel do(3) <<<*,*>>>
do i = 1, n
do concurrent (j=1:n, k=1:n)
a(k,j,i) = 1
end do
end do
end subroutine
```

```
$ bbc -fcuda -emit-hlfir cuf_mixed.cuf -o -
bbc: .../flang/lib/Lower/Bridge.cpp:4054: void (anonymous namespace)::FirConverter::genFIR(
const Fortran::parser::CUFKernelDoConstruct &):
Assertion `bounds && "Expected bounds on the loop construct"' failed.
```

(assertions-enabled build; with assertions off this dereferences an invalid
`std::get_if` result instead).

## Analysis

The semantic check (`DoConstructTightNesting`,
`flang/lib/Semantics/check-cuda.cpp`) counts a DO CONCURRENT's concurrent
control indices toward the required depth, so `do(3)` over
`do` + `do concurrent (j,k)` passes (1 + 2 indices). But the lowering's
bounds-gathering loop in `genFIR(CUFKernelDoConstruct)` branches once, up
front, on whether the *outer* construct is DO CONCURRENT: on the counted-DO
branch it then expects every nested level to be a counted DO with
`LoopControl::Bounds`, and asserts when the descent reaches the inner
DO CONCURRENT (whose loop control holds `LoopControl::Concurrent`, not
`Bounds`).

## Expected behavior

Either semantic analysis should reject a mixed counted-DO / DO CONCURRENT
nest under `!$cuf kernel do(n)` (if it is not meant to be supported), or
lowering should handle the inner DO CONCURRENT's concurrent controls the way
it already does when DO CONCURRENT is the outer construct. A compile-time
error is fine; an assertion failure is not.

## Versions

Reproduced on current main (`33cc9981`, which includes #223579, at
Bridge.cpp:4054) and on earlier revisions; pre-existing, not introduced by
#223579 (verified by A/B against the commit before it — same assert both
sides).

(Submitted with the help of AI.)

Contributor guide

Open the contributing guide

Research direction

Reproduce the failure with the bbc command in the issue, then read genFIR(CUFKernelDoConstruct) in flang/lib/Lower/Bridge.cpp and DoConstructTightNesting in flang/lib/Semantics/check-cuda.cpp. Trace how counted DO and DO CONCURRENT controls are gathered for mixed nests. Done means the example produces a compile-time diagnostic or lowers without an assertion or invalid std::get_if access.

Written by the indexing model from the issue text.

Assessment

Tech stack
fortran
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.