llvm / llvm/llvm-project

[flang][OpenMP] Reduction identifier matching an intrinsic name but bound to a user procedure aborts lowering

Open
#209,853 0 comments 0 reactions 1 assignee Claimed by @MattPD View on GitHub
flang:openmp
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

### Summary

A `reduction(:)` clause whose reduction identifier is one of the intrinsic reduction names (`max`, `min`, `iand`, `ior`, `ieor`) but resolves to a user procedure (with no `declare reduction`) is accepted by semantics and then aborts lowering with a "not yet implemented" TODO.

### Reproducer

```fortran
program p
integer :: x, i
interface max
procedure mymax
end interface
x = 0
!$omp parallel do reduction(max:x)
do i = 1, 10
x = i
end do
print *, x
contains
integer function mymax(a, b)
integer, intent(in) :: a, b
mymax = merge(a, b, a > b)
end function
end program
```

```
$ flang -fopenmp -c repro.f90
error: loc(...): flang/lib/Lower/Support/ReductionProcessor.cpp: not yet implemented: Lowering unrecognised reduction type
LLVM ERROR: aborting
```

### Other compilers

flang is the only compiler that aborts. On the same program:

| Compiler | Result | Compiler Explorer |
|----------|--------|-------------------|
| flang (trunk) | ICE: `not yet implemented: Lowering unrecognised reduction type` | https://flang.godbolt.org/z/Gxe7fP49x |
| gfortran (trunk) | clean error: `!$OMP DECLARE REDUCTION max not found` | https://gfortran.godbolt.org/z/hqv93GWGv |
| ifx (latest) | accepts, exit 0 | https://fortran.godbolt.org/z/ohfh7d4MK |
| nvfortran | accepts, exit 0 | https://fortran.godbolt.org/z/j5TW54bxh |
| Cray Fortran (CCE 20.0.0) | accepts, exit 0 | (not on Compiler Explorer) |

flang's `-fsyntax-only` accepts the program (semantics); the abort is in lowering, shown on Compiler Explorer via `-emit-hlfir`. So flang neither accepts the program nor emits a diagnostic; it aborts.

### Root cause

Semantics (`CheckReductionOperator::visitDesignator`, `flang/lib/Semantics/check-omp-structure.cpp`) accepts a procedure-designator reduction identifier if its name is one of `{max, min, iand, ior, ieor}`, or if it carries `UserReductionDetails`. It accepts by name.

Lowering (`flang/lib/Lower/Support/ReductionProcessor.cpp`) decides the reduction by the INTRINSIC attribute (`supportedIntrinsicProcReduction`). When the name is shadowed by a user procedure, the symbol is neither `INTRINSIC` nor a user-defined reduction, so lowering falls through to the TODO and aborts.

The gap: semantics accepts by name, lowering checks by attribute.

### Suggested fix

One of:
1. Tighten the semantic check so a procedure-designator reduction identifier that resolves to a non-intrinsic symbol without a `declare reduction` is rejected with a proper diagnostic, rather than accepted and later aborted in lowering.
2. Handle the case in lowering.

This is distinct from the related issues in this area:
- #191927 (open): a `declare reduction` whose identifier is an intrinsic procedure name, plus an accessibility statement, emits an incorrect semantic error. That case has a `declare reduction` and fails in semantics; this one has no `declare reduction` and aborts in lowering.
- #205893 (fixed): a user `declare reduction` shadowing an intrinsic name, where a visible declaration takes precedence.
- #68654 (fixed): a reduction identifier that renames the actual intrinsic (`use m, ren => max`), which now lowers correctly.

Here there is no `declare reduction`, and the name resolves to an ordinary user procedure. Surfaced during review of #207493 / #207494.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.