Skip to content

Commit bbadbf7

Browse files
authored
[flang][OpenMP] Delayed privatization for variables with equivalence association (#100531)
Handles variables that are storage associated via `equivalence`. The problem is that these variables are declared as `fir.ptr`s while their privatized storage is declared as `fir.ref` which was triggering a validation error in the OpenMP dialect.
1 parent 3611c0b commit bbadbf7

File tree

3 files changed

+87
-3
lines changed

3 files changed

+87
-3
lines changed

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -549,9 +549,20 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
549549
symTable->addSymbol(*sym, localExV);
550550
symTable->pushScope();
551551
cloneSymbol(sym);
552-
firOpBuilder.create<mlir::omp::YieldOp>(
553-
hsb.getAddr().getLoc(),
554-
symTable->shallowLookupSymbol(*sym).getAddr());
552+
mlir::Value cloneAddr = symTable->shallowLookupSymbol(*sym).getAddr();
553+
mlir::Type cloneType = cloneAddr.getType();
554+
555+
// A `convert` op is required for variables that are storage associated
556+
// via `equivalence`. The problem is that these variables are declared as
557+
// `fir.ptr`s while their privatized storage is declared as `fir.ref`,
558+
// therefore we convert to proper symbol type.
559+
mlir::Value yieldedValue =
560+
(symType == cloneType) ? cloneAddr
561+
: firOpBuilder.createConvert(
562+
cloneAddr.getLoc(), symType, cloneAddr);
563+
564+
firOpBuilder.create<mlir::omp::YieldOp>(hsb.getAddr().getLoc(),
565+
yieldedValue);
555566
symTable->popScope();
556567
}
557568

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
! Test delayed privatization for variables that are storage associated via `EQUIVALENCE`.
2+
3+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \
4+
! RUN: -o - %s 2>&1 | FileCheck %s
5+
! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 \
6+
! RUN: | FileCheck %s
7+
8+
subroutine private_common
9+
real x, y
10+
equivalence (x,y)
11+
!$omp parallel firstprivate(x)
12+
x = 3.14
13+
!$omp end parallel
14+
end subroutine
15+
16+
! CHECK: omp.private {type = firstprivate} @[[X_PRIVATIZER:.*]] : ![[X_TYPE:fir.ptr<f32>]] alloc {
17+
! CHECK: ^bb0(%{{.*}}: ![[X_TYPE]]):
18+
! CHECK: %[[PRIV_ALLOC:.*]] = fir.alloca f32 {bindc_name = "x", {{.*}}}
19+
! CHECK: %[[PRIV_DECL:.*]]:2 = hlfir.declare %[[PRIV_ALLOC]] {{{.*}}} : (![[PRIV_TYPE:fir.ref<f32>]]) -> ({{.*}})
20+
! CHECK: %[[PRIV_CONV:.*]] = fir.convert %[[PRIV_DECL]]#0 : (![[PRIV_TYPE]]) -> ![[X_TYPE]]
21+
! CHECK: omp.yield(%[[PRIV_CONV]] : ![[X_TYPE]])
22+
! CHECK: } copy {
23+
! CHECK: ^bb0(%[[ORIG_PTR:.*]]: ![[X_TYPE]], %[[PRIV_REF:.*]]: ![[X_TYPE]]):
24+
! CHECK: %[[ORIG_VAL:.*]] = fir.load %[[ORIG_PTR]] : !fir.ptr<f32>
25+
! CHECK: hlfir.assign %[[ORIG_VAL]] to %[[PRIV_REF]] temporary_lhs : f32, ![[X_TYPE]]
26+
! CHECK: omp.yield(%[[PRIV_REF]] : ![[X_TYPE]])
27+
! CHECK: }
28+
29+
! CHECK: func.func @_QPprivate_common() {
30+
! CHECK: omp.parallel private(@[[X_PRIVATIZER]] %{{.*}}#0 -> %[[PRIV_ARG:.*]] : ![[X_TYPE]]) {
31+
! CHECK: %[[REG_DECL:.*]]:2 = hlfir.declare %[[PRIV_ARG]] {{{.*}}} : (![[X_TYPE]]) -> ({{.*}})
32+
! CHECK: %[[CST:.*]] = arith.constant {{.*}}
33+
! CHECK: hlfir.assign %[[CST]] to %[[REG_DECL]]#0 : {{.*}}
34+
! CHECK: omp.terminator
35+
! CHECK: }
36+
! CHECK: return
37+
! CHECK: }

mlir/test/Target/LLVMIR/openmp-private.mlir

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,39 @@ omp.declare_reduction @reducer.part : !llvm.ptr init {
234234
^bb0(%arg0: !llvm.ptr):
235235
omp.yield
236236
}
237+
238+
// -----
239+
240+
llvm.func @_QPequivalence() {
241+
%0 = llvm.mlir.constant(1 : i64) : i64
242+
%1 = llvm.alloca %0 x !llvm.array<4 x i8> : (i64) -> !llvm.ptr
243+
%2 = llvm.mlir.constant(0 : index) : i64
244+
%3 = llvm.getelementptr %1[0, %2] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.array<4 x i8>
245+
omp.parallel private(@_QFequivalenceEx_firstprivate_ptr_f32 %3 -> %arg0 : !llvm.ptr) {
246+
%4 = llvm.mlir.constant(3.140000e+00 : f32) : f32
247+
llvm.store %4, %arg0 : f32, !llvm.ptr
248+
omp.terminator
249+
}
250+
llvm.return
251+
}
252+
253+
omp.private {type = firstprivate} @_QFequivalenceEx_firstprivate_ptr_f32 : !llvm.ptr alloc {
254+
^bb0(%arg0: !llvm.ptr):
255+
%0 = llvm.mlir.constant(1 : i64) : i64
256+
%1 = llvm.alloca %0 x f32 {bindc_name = "x", pinned} : (i64) -> !llvm.ptr
257+
omp.yield(%1 : !llvm.ptr)
258+
} copy {
259+
^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
260+
%0 = llvm.load %arg0 : !llvm.ptr -> f32
261+
llvm.store %0, %arg1 : f32, !llvm.ptr
262+
omp.yield(%arg1 : !llvm.ptr)
263+
}
264+
265+
// CHECK: define internal void @_QPequivalence..omp_par
266+
// CHECK-NOT: define {{.*}} @{{.*}}
267+
// CHECK: %[[PRIV_ALLOC:.*]] = alloca float, i64 1, align 4
268+
// CHECK: %[[HOST_VAL:.*]] = load float, ptr %{{.*}}, align 4
269+
// Test that we initialize the firstprivate variable.
270+
// CHECK: store float %[[HOST_VAL]], ptr %[[PRIV_ALLOC]], align 4
271+
// Test that we inlined the body of the parallel region.
272+
// CHECK: store float 0x{{.*}}, ptr %[[PRIV_ALLOC]], align 4

0 commit comments

Comments
 (0)