Skip to content

[flang][OpenMP] Host threadprivate variable is not being treated as such in subroutine #84561

Closed
@luporl

Description

@luporl

The test program below was expected to print 1 for all threads, but it is printing 1 only for one of the threads:

program main
  implicit none
  integer, save :: i = 0
  !$omp threadprivate(i)

  !$omp parallel
  call foo
  !$omp critical
  print *, i
  !$omp end critical
  !$omp end parallel

contains
  subroutine foo()
    !$omp single
    i = 1
    !$omp end single copyprivate(i)
  end subroutine
end program

foo's FIR is missing an omp.threadprivate operation and is using the original i variable instead:

  func.func private @_QFPfoo() attributes {fir.internal_proc, llvm.linkage = #llvm.linkage<internal>} {
    %0 = fir.address_of(@_QFEi) : !fir.ref<i32>
    %1:2 = hlfir.declare %0 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
    omp.single copyprivate(%1#0 -> @_copy_i32 : !fir.ref<i32>) {
      %c1_i32 = arith.constant 1 : i32
      hlfir.assign %c1_i32 to %1#0 : i32, !fir.ref<i32>
      omp.terminator
    }
    return
  }

By manually adding an omp.threadprivate operation (and using its result instead), the program works as expected:

  func.func private @_QFPfoo() attributes {fir.internal_proc, llvm.linkage = #llvm.linkage<internal>} {
    %0 = fir.address_of(@_QFEi) : !fir.ref<i32>
    %1:2 = hlfir.declare %0 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
    %2 = omp.threadprivate %1#1 : !fir.ref<i32> -> !fir.ref<i32>
    %3:2 = hlfir.declare %2 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
    omp.single copyprivate(%3#0 -> @_copy_i32 : !fir.ref<i32>) {
      %c1_i32 = arith.constant 1 : i32
      hlfir.assign %c1_i32 to %3#0 : i32, !fir.ref<i32>
      omp.terminator
    }
    return
  }

The issue doesn't seem related to copyprivate, as other similar programs also show the same behavior:

program main
  implicit none
  integer, save :: i = 0
  !$omp threadprivate(i)

  !$omp parallel
  call foo
  !$omp critical
  print *, i
  !$omp end critical
  !$omp end parallel

contains
  subroutine foo()
    i = 1
  end subroutine
end program

The issue also happens if the i = 1 line is wrapped inside a parallel directive.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions