Skip to content

Commit 7e48b5f

Browse files
committed
[flang][MLIR][OpenMP] Extend delayed privatization for arrays
One more step in delayed privatization, this PR extends support for arrays. In the delayed privatizer, a `fir.box_dims` operation is emitted to retrieve the array bounds and extents. The result of these `fir.box_dims` and the privatizer argument, are then used to create a new `ExtendedValue`.
1 parent 6c557cf commit 7e48b5f

File tree

3 files changed

+167
-2
lines changed

3 files changed

+167
-2
lines changed

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,31 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) {
388388
&allocRegion, /*insertPt=*/{}, symType, symLoc);
389389

390390
firOpBuilder.setInsertionPointToEnd(allocEntryBlock);
391-
symTable->addSymbol(*sym,
392-
fir::substBase(symExV, allocRegion.getArgument(0)));
391+
392+
fir::ExtendedValue localExV = symExV.match(
393+
[&](const fir::ArrayBoxValue &box) -> fir::ExtendedValue {
394+
auto idxTy = firOpBuilder.getIndexType();
395+
llvm::SmallVector<mlir::Value> extents;
396+
llvm::SmallVector<mlir::Value> lBounds;
397+
398+
for (unsigned dim = 0; dim < box.getExtents().size(); ++dim) {
399+
mlir::Value dimVal =
400+
firOpBuilder.createIntegerConstant(symLoc, idxTy, dim);
401+
fir::BoxDimsOp dimInfo = firOpBuilder.create<fir::BoxDimsOp>(
402+
symLoc, idxTy, idxTy, idxTy, allocRegion.getArgument(0),
403+
dimVal);
404+
extents.push_back(dimInfo.getExtent());
405+
lBounds.push_back(dimInfo.getLowerBound());
406+
}
407+
408+
return fir::ArrayBoxValue(allocRegion.getArgument(0), extents,
409+
lBounds);
410+
},
411+
[&](const auto &box) -> fir::ExtendedValue {
412+
return fir::substBase(symExV, allocRegion.getArgument(0));
413+
});
414+
415+
symTable->addSymbol(*sym, localExV);
393416
symTable->pushScope();
394417
cloneSymbol(sym);
395418
firOpBuilder.create<mlir::omp::YieldOp>(
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
! Test delayed privatization for allocatable arrays.
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 delayed_privatization_private(var1, l1)
9+
implicit none
10+
integer(8):: l1
11+
integer, allocatable, dimension(:) :: var1
12+
13+
!$omp parallel firstprivate(var1)
14+
var1(l1 + 1) = 10
15+
!$omp end parallel
16+
end subroutine
17+
18+
! CHECK-LABEL: omp.private {type = firstprivate}
19+
! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : [[TYPE:!fir.ref<!fir.box<!fir.heap<!fir.array<\?xi32>>>>]] alloc {
20+
21+
! CHECK-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]):
22+
! CHECK-NEXT: %[[PRIV_ALLOC:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<{{\?}}xi32>>> {bindc_name = "var1", pinned, uniq_name = "_QFdelayed_privatization_privateEvar1"}
23+
24+
! CHECK-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]]
25+
! CHECK-NEXT: %[[PRIV_ARG_BOX:.*]] = fir.box_addr %[[PRIV_ARG_VAL]]
26+
! CHECK-NEXT: %[[PRIV_ARG_ADDR:.*]] = fir.convert %[[PRIV_ARG_BOX]]
27+
! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64
28+
! CHECK-NEXT: %[[ALLOC_COND:.*]] = arith.cmpi ne, %[[PRIV_ARG_ADDR]], %[[C0]] : i64
29+
30+
! CHECK-NEXT: fir.if %[[ALLOC_COND]] {
31+
! CHECK-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]] : [[TYPE]]
32+
! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : index
33+
! CHECK-NEXT: %[[DIMS:.*]]:3 = fir.box_dims %[[PRIV_ARG_VAL]], %[[C0]]
34+
! CHECK-NEXT: fir.box_addr %[[PRIV_ARG_VAL]]
35+
! CHECK-NEXT: %[[C0_2:.*]] = arith.constant 0 : index
36+
! CHECK-NEXT: %[[CMP:.*]] = arith.cmpi sgt, %[[DIMS]]#1, %[[C0_2]] : index
37+
! CHECK-NEXT: %[[SELECT:.*]] = arith.select %[[CMP]], %[[DIMS]]#1, %[[C0_2]] : index
38+
! CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[SELECT]]
39+
! CHECK-NEXT: %[[SHAPE_SHIFT:.*]] = fir.shape_shift %[[DIMS]]#0, %[[SELECT]] : (index, index) -> !fir.shapeshift<1>
40+
! CHECK-NEXT: %[[EMBOX:.*]] = fir.embox %[[MEM]](%[[SHAPE_SHIFT]])
41+
! CHECK-NEXT: fir.store %[[EMBOX]] to %[[PRIV_ALLOC]]
42+
! CHECK-NEXT: } else {
43+
! CHECK-NEXT: %[[ZEROS:.*]] = fir.zero_bits
44+
! CHECK-NEXT: %[[C0_3:.*]] = arith.constant 0 : index
45+
! CHECK-NEXT: %[[SHAPE:.*]] = fir.shape %[[C0_3]] : (index) -> !fir.shape<1>
46+
! CHECK-NEXT: %[[EMBOX_2:.*]] = fir.embox %[[ZEROS]](%[[SHAPE]])
47+
! CHECK-NEXT: fir.store %[[EMBOX_2]] to %[[PRIV_ALLOC]]
48+
! CHECK-NEXT: }
49+
50+
! CHECK-NEXT: hlfir.declare
51+
! CHECK-NEXT: omp.yield
52+
53+
! CHECK-NEXT: } copy {
54+
! CHECK-NEXT: ^bb0(%[[PRIV_ORIG_ARG:.*]]: [[TYPE]], %[[PRIV_PRIV_ARG:.*]]: [[TYPE]]):
55+
! CHECK-NEXT: %[[PRIV_BASE_VAL:.*]] = fir.load %[[PRIV_PRIV_ARG]]
56+
! CHECK-NEXT: %[[PRIV_BASE_BOX:.*]] = fir.box_addr %[[PRIV_BASE_VAL]]
57+
! CHECK-NEXT: %[[PRIV_BASE_ADDR:.*]] = fir.convert %[[PRIV_BASE_BOX]]
58+
! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64
59+
! CHECK-NEXT: %[[COPY_COND:.*]] = arith.cmpi ne, %[[PRIV_BASE_ADDR]], %[[C0]] : i64
60+
61+
62+
! CHECK-NEXT: fir.if %[[COPY_COND]] {
63+
! CHECK-NEXT: %[[PRIV_ORIG_ARG_VAL:.*]] = fir.load %[[PRIV_ORIG_ARG]]
64+
! CHECK-NEXT: hlfir.assign %[[PRIV_ORIG_ARG_VAL]] to %[[PRIV_BASE_VAL]] temporary_lhs
65+
! CHECK-NEXT: }
66+
! CHECK-NEXT: omp.yield
67+
! CHECK-NEXT: }
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
! Test delayed privatization for arrays.
2+
3+
! RUN: split-file %s %t
4+
5+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \
6+
! RUN: -o - %t/one_dim_array.f90 2>&1 | FileCheck %s --check-prefix=ONE_DIM
7+
! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - \
8+
! RUN: %t/one_dim_array.f90 2>&1 | FileCheck %s --check-prefix=ONE_DIM
9+
10+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \
11+
! RUN: -o - %t/two_dim_array.f90 2>&1 | FileCheck %s --check-prefix=TWO_DIM
12+
! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %t/two_dim_array.f90 2>&1 |\
13+
! RUN: FileCheck %s --check-prefix=TWO_DIM
14+
15+
!--- one_dim_array.f90
16+
subroutine delayed_privatization_private(var1, l1, u1)
17+
implicit none
18+
integer(8):: l1, u1
19+
integer, dimension(l1:u1) :: var1
20+
21+
!$omp parallel firstprivate(var1)
22+
var1(l1 + 1) = 10
23+
!$omp end parallel
24+
end subroutine
25+
26+
! ONE_DIM-LABEL: omp.private {type = firstprivate}
27+
! ONE_DIM-SAME: @[[PRIVATIZER_SYM:.*]] : [[TYPE:!fir.box<!fir.array<\?xi32>>]] alloc {
28+
29+
! ONE_DIM-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]):
30+
31+
! ONE_DIM-NEXT: %[[C0:.*]] = arith.constant 0 : index
32+
! ONE_DIM-NEXT: %[[DIMS:.*]]:3 = fir.box_dims %[[PRIV_ARG]], %[[C0]] : ([[TYPE]], index) -> (index, index, index)
33+
! ONE_DIM-NEXT: %[[PRIV_ALLOCA:.*]] = fir.alloca !fir.array<{{\?}}xi32>, %[[DIMS]]#1 {bindc_name = "var1", pinned, uniq_name = "_QFdelayed_privatization_privateEvar1"}
34+
! ONE_DIM-NEXT: %[[SHAPE_SHIFT:.*]] = fir.shape_shift %[[DIMS]]#0, %[[DIMS]]#1 : (index, index) -> !fir.shapeshift<1>
35+
! ONE_DIM-NEXT: %[[PRIV_DECL:.*]]:2 = hlfir.declare %[[PRIV_ALLOCA]](%[[SHAPE_SHIFT]]) {uniq_name = "_QFdelayed_privatization_privateEvar1"}
36+
! ONE_DIM-NEXT: omp.yield(%[[PRIV_DECL]]#0 : [[TYPE]])
37+
38+
! ONE_DIM-NEXT: } copy {
39+
! ONE_DIM-NEXT: ^bb0(%[[PRIV_ORIG_ARG:.*]]: [[TYPE]], %[[PRIV_PRIV_ARG:.*]]: [[TYPE]]):
40+
! ONE_DIM-NEXT: hlfir.assign %[[PRIV_ORIG_ARG]] to %[[PRIV_PRIV_ARG]] temporary_lhs
41+
! ONE_DIM-NEXT: omp.yield(%[[PRIV_PRIV_ARG]] : [[TYPE]])
42+
! ONE_DIM-NEXT: }
43+
44+
!--- two_dim_array.f90
45+
subroutine delayed_privatization_private(var1, l1, u1, l2, u2)
46+
implicit none
47+
integer(8):: l1, u1, l2, u2
48+
integer, dimension(l1:u1, l2:u2) :: var1
49+
50+
!$omp parallel firstprivate(var1)
51+
var1(l1 + 1, u2) = 10
52+
!$omp end parallel
53+
end subroutine
54+
55+
! TWO_DIM-LABEL: omp.private {type = firstprivate}
56+
! TWO_DIM-SAME: @[[PRIVATIZER_SYM:.*]] : [[TYPE:!fir.box<!fir.array<\?x\?xi32>>]] alloc {
57+
58+
! TWO_DIM-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]):
59+
! TWO_DIM-NEXT: %[[C0:.*]] = arith.constant 0 : index
60+
! TWO_DIM-NEXT: %[[DIMS0:.*]]:3 = fir.box_dims %[[PRIV_ARG]], %[[C0]] : ([[TYPE]], index) -> (index, index, index)
61+
62+
! TWO_DIM-NEXT: %[[C1:.*]] = arith.constant 1 : index
63+
! TWO_DIM-NEXT: %[[DIMS1:.*]]:3 = fir.box_dims %[[PRIV_ARG]], %[[C1]] : ([[TYPE]], index) -> (index, index, index)
64+
65+
! TWO_DIM-NEXT: %[[PRIV_ALLOCA:.*]] = fir.alloca !fir.array<{{\?}}x{{\?}}xi32>, %[[DIMS0]]#1, %[[DIMS1]]#1 {bindc_name = "var1", pinned, uniq_name = "_QFdelayed_privatization_privateEvar1"}
66+
! TWO_DIM-NEXT: %[[SHAPE_SHIFT:.*]] = fir.shape_shift %[[DIMS0]]#0, %[[DIMS0]]#1, %[[DIMS1]]#0, %[[DIMS1]]#1 : (index, index, index, index) -> !fir.shapeshift<2>
67+
68+
! TWO_DIM-NEXT: %[[PRIV_DECL:.*]]:2 = hlfir.declare %[[PRIV_ALLOCA]](%[[SHAPE_SHIFT]]) {uniq_name = "_QFdelayed_privatization_privateEvar1"}
69+
! TWO_DIM-NEXT: omp.yield(%[[PRIV_DECL]]#0 : [[TYPE]])
70+
71+
! TWO_DIM-NEXT: } copy {
72+
! TWO_DIM-NEXT: ^bb0(%[[PRIV_ORIG_ARG:.*]]: [[TYPE]], %[[PRIV_PRIV_ARG:.*]]: [[TYPE]]):
73+
! TWO_DIM-NEXT: hlfir.assign %[[PRIV_ORIG_ARG]] to %[[PRIV_PRIV_ARG]] temporary_lhs
74+
! TWO_DIM-NEXT: omp.yield(%[[PRIV_PRIV_ARG]] : [[TYPE]])
75+
! TWO_DIM-NEXT: }

0 commit comments

Comments
 (0)