llvm / llvm/llvm-project

[Flang][OpenMP] Redundant finalization for firstprivate variables

Open
#208,363 0 comments 0 reactions 0 assignees View on GitHub
flang:openmp
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

## Summary

The count of finalization for firstprivate variables seems to be incorrect. It seems that redundant finalization of firstprivate variables occurs at the beginning of a parallel region.

* 7.4 List Item Privatization (OpenMP 6.0)

> Finalization of a list item of a finalizable type or subobjects of a list item of a finalizable type occurs at the end of the region.

* 7.5.6.3 When finalization occurs (Fortran 2023)

> When an intrinsic assignment statement is executed (10.2.1.3), if the variable is not an unallocated allocatable variable, it is finalized after evaluation of expr and before the definition of the variable. If the variable is an allocated allocatable variable, or has an allocated allocatable subobject, that would be deallocated by intrinsic assignment, the finalization occurs before the deallocation.
> When a pointer is deallocated its target is finalized. When an allocatable entity is deallocated, it is finalized unless it is the variable in an intrinsic assignment statement. If an error condition occurs during deallocation, it is processor dependent whether finalization occurs.

### Reproducer

* test.f90

```fortran
module m1
use omp_lib
type ty
integer::k
contains
final:: f
end type
contains
subroutine f(d)
type(ty)::d
print "(a,i2,1x,a,z16.16,a,i2)",' FINAL thread',omp_get_thread_num(),' addr=',loc(d),' values=',d
end
end

use m1
type(ty),allocatable:: var
allocate(var,source=ty(1))
call omp_set_num_threads(2)
print "('paralllel with firstprivate start addr=',z16.16)",loc(var)

!$omp parallel firstprivate(var)
if (var%k/=1) print *,1001,omp_get_thread_num()
print "(' assignment thread',i2,' addr=',z16.16)",omp_get_thread_num(),loc(var)
var=ty(2)
if (var%k/=2) print *,1002,omp_get_thread_num()
!$omp end parallel

if (var%k/=1) print *,1003,var%k
print *,'pass'
end
```

* commands

```console
$ flang --version
flang version 23.0.0git (https://github.com/llvm/llvm-project.git ecdd6403fd213f90243a3d354d4db3483b89471f)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /path/to/llvm/build/bin
Build config: +assertions
$ flang test.f90 -fopenmp && ./a.out
paralllel with firstprivate start addr=000055CA546C92A0
FINAL thread 0 addr=000055CA546CBBF0 values=**
FINAL thread 1 addr=00007FEB7C000C70 values= 0
assignment thread 1 addr=00007FEB7C000C70
FINAL thread 1 addr=00007FEB7C000C70 values= 1
FINAL thread 1 addr=00007FEB7C000C70 values= 2
assignment thread 0 addr=000055CA546CBBF0
FINAL thread 0 addr=000055CA546CBBF0 values= 1
FINAL thread 0 addr=000055CA546CBBF0 values= 2
pass
```

* execution result with annotations
```
paralllel with firstprivate start addr=000055CA546C92A0
FINAL thread 0 addr=000055CA546CBBF0 values=** ### Unexpected finalization of an uninitialized privatized variable
FINAL thread 1 addr=00007FEB7C000C70 values= 0 ### Unexpected finalization of an uninitialized privatized variable
assignment thread 1 addr=00007FEB7C000C70
FINAL thread 1 addr=00007FEB7C000C70 values= 1 ### Finalization just before assignment
FINAL thread 1 addr=00007FEB7C000C70 values= 2 ### Finalization after the parallel region
assignment thread 0 addr=000055CA546CBBF0
FINAL thread 0 addr=000055CA546CBBF0 values= 1 ### Finalization just before assignment
FINAL thread 0 addr=000055CA546CBBF0 values= 2 ### Finalization after the parallel region
pass
```

## Non-problematic Conditions

The issue does not occur under the following conditions:
* Changing the firstprivate variable to a private/lastprivate variable.

## Other Compilers

* GFortran
```console
$ gfortran --version
GNU Fortran (GCC) 15.2.0
Copyright (C) 2025 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gfortran test.f90 -fopenmp && ./a.out
paralllel with firstprivate start addr=0000000001A889A0
assignment thread 0 addr=0000000001A8A6B0
FINAL thread 0 addr=0000000001A8A6B0 values= 1
assignment thread 1 addr=00007F9014000B70
FINAL thread 1 addr=00007F9014000B70 values= 1
pass
```

* Intel Fortran
```console
$ ifx --version
ifx (IFX) 2025.3.2 20260112
Copyright (C) 1985-2026 Intel Corporation. All rights reserved.

$ ifx -O0 test.f90 -qopenmp && ./a.out
paralllel with firstprivate start addr=00007F50D95CFFE0
assignment thread 0 addr=00007F50D95CFFE0
FINAL thread 0 addr=00007F50D95CFFE0 values= 1
1001 1
assignment thread 1 addr=00007F50D95CFFE0
FINAL thread 1 addr=00007F50D95CFFE0 values= 2
1003 2
pass
```

Contributor guide

Open the contributing guide

Research direction

Start by compiling the provided test.f90 with flang -fopenmp and compare its finalization output with the shown GFortran behavior. Trace the OpenMP firstprivate handling and Fortran finalization behavior from this reproducer; done means no finalization occurs for an uninitialized privatized variable or immediately before assignment, while the program still prints pass.

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
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.