[flang][OpenMP] Fix the use-associated bug in threadprivate directive lowering
authorPeixin Qiao <qiaopeixin@huawei.com>
Mon, 17 Oct 2022 11:46:18 +0000 (19:46 +0800)
committerPeixin Qiao <qiaopeixin@huawei.com>
Mon, 17 Oct 2022 11:46:18 +0000 (19:46 +0800)
The symbol may be used by use-association for multiple times such
as one in module specification part and one in module procedure.
Then in module procedure, the variable instantiation will be called
for multiple times. But we only need to threadprivatize it once and
use the threadprivatized value for the second time.

Fix #58379.

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D136035

flang/lib/Lower/OpenMP.cpp
flang/test/Lower/OpenMP/threadprivate-use-association-2.f90 [new file with mode: 0644]

index 82c04ab..adada64 100644 (file)
@@ -1774,6 +1774,12 @@ void Fortran::lower::genThreadprivateOp(
         currentLocation, symValue.getType(), symValue);
   } else {
     mlir::Value symValue = converter.getSymbolAddress(sym);
+    mlir::Operation *op = symValue.getDefiningOp();
+    // The symbol may be use-associated multiple times, and nothing needs to be
+    // done after the original symbol is mapped to the threadprivatized value
+    // for the first time. Use the threadprivatized value directly.
+    if (mlir::isa<mlir::omp::ThreadprivateOp>(op))
+      return;
     symThreadprivateValue = firOpBuilder.create<mlir::omp::ThreadprivateOp>(
         currentLocation, symValue.getType(), symValue);
   }
diff --git a/flang/test/Lower/OpenMP/threadprivate-use-association-2.f90 b/flang/test/Lower/OpenMP/threadprivate-use-association-2.f90
new file mode 100644 (file)
index 0000000..615885f
--- /dev/null
@@ -0,0 +1,39 @@
+! This test checks lowering of OpenMP Threadprivate Directive.
+! Test for threadprivate variable double use in use association.
+
+!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
+!RUN: bbc -emit-fir -fopenmp %s -o - | FileCheck %s
+
+! CHECK-LABEL: fir.global @_QMmEx : i32
+module m
+  integer :: x
+  !$omp threadprivate(x)
+end
+
+! CHECK-LABEL: func.func @_QMm2Ptest() {
+! CHECK:         %[[VAL_0:.*]] = fir.address_of(@_QMmEx) : !fir.ref<i32>
+! CHECK:         %[[VAL_1:.*]] = omp.threadprivate %[[VAL_0]] : !fir.ref<i32> -> !fir.ref<i32>
+! CHECK:         fir.call @_QPbar(%[[VAL_1]]) : (!fir.ref<i32>) -> ()
+! CHECK:         return
+! CHECK:       }
+!
+! CHECK-LABEL: func.func @_QMm2FtestPinternal_test() {
+! CHECK:         %[[VAL_0:.*]] = fir.address_of(@_QMmEx) : !fir.ref<i32>
+! CHECK:         %[[VAL_1:.*]] = omp.threadprivate %[[VAL_0]] : !fir.ref<i32> -> !fir.ref<i32>
+! CHECK:         fir.call @_QPbar(%[[VAL_1]]) : (!fir.ref<i32>) -> ()
+! CHECK:         return
+! CHECK:       }
+
+module m2
+  use m
+ contains
+  subroutine test()
+    use m
+    call bar(x)
+   contains
+    subroutine internal_test()
+      use m
+      call bar(x)
+    end
+  end
+end