Skip to content

Commit e356893

Browse files
authored
[Flang][OpenMP] Support for lowering of taskloop construct to MLIR (#138646)
Added support for lowering of taskloop construct and its clauses(Private and Firstprivate) to MLIR.
1 parent 5781b5e commit e356893

File tree

10 files changed

+255
-61
lines changed

10 files changed

+255
-61
lines changed

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,6 +1804,21 @@ static void genTaskgroupClauses(lower::AbstractConverter &converter,
18041804
llvm::omp::Directive::OMPD_taskgroup);
18051805
}
18061806

1807+
static void genTaskloopClauses(lower::AbstractConverter &converter,
1808+
semantics::SemanticsContext &semaCtx,
1809+
const List<Clause> &clauses, mlir::Location loc,
1810+
mlir::omp::TaskloopOperands &clauseOps) {
1811+
1812+
ClauseProcessor cp(converter, semaCtx, clauses);
1813+
1814+
cp.processTODO<clause::Allocate, clause::Collapse, clause::Default,
1815+
clause::Final, clause::Grainsize, clause::If,
1816+
clause::InReduction, clause::Lastprivate, clause::Mergeable,
1817+
clause::Nogroup, clause::NumTasks, clause::Priority,
1818+
clause::Reduction, clause::Shared, clause::Untied>(
1819+
loc, llvm::omp::Directive::OMPD_taskloop);
1820+
}
1821+
18071822
static void genTaskwaitClauses(lower::AbstractConverter &converter,
18081823
semantics::SemanticsContext &semaCtx,
18091824
const List<Clause> &clauses, mlir::Location loc,
@@ -3256,8 +3271,30 @@ static mlir::omp::TaskloopOp genStandaloneTaskloop(
32563271
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
32573272
mlir::Location loc, const ConstructQueue &queue,
32583273
ConstructQueue::const_iterator item) {
3259-
TODO(loc, "Taskloop construct");
3260-
return nullptr;
3274+
mlir::omp::TaskloopOperands taskloopClauseOps;
3275+
genTaskloopClauses(converter, semaCtx, item->clauses, loc, taskloopClauseOps);
3276+
3277+
DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
3278+
/*shouldCollectPreDeterminedSymbols=*/true,
3279+
enableDelayedPrivatization, symTable);
3280+
dsp.processStep1(&taskloopClauseOps);
3281+
3282+
mlir::omp::LoopNestOperands loopNestClauseOps;
3283+
llvm::SmallVector<const semantics::Symbol *> iv;
3284+
genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc,
3285+
loopNestClauseOps, iv);
3286+
3287+
EntryBlockArgs taskloopArgs;
3288+
taskloopArgs.priv.syms = dsp.getDelayedPrivSymbols();
3289+
taskloopArgs.priv.vars = taskloopClauseOps.privateVars;
3290+
3291+
auto taskLoopOp = genWrapperOp<mlir::omp::TaskloopOp>(
3292+
converter, loc, taskloopClauseOps, taskloopArgs);
3293+
3294+
genLoopNestOp(converter, symTable, semaCtx, eval, loc, queue, item,
3295+
loopNestClauseOps, iv, {{taskLoopOp, taskloopArgs}},
3296+
llvm::omp::Directive::OMPD_taskloop, dsp);
3297+
return taskLoopOp;
32613298
}
32623299

32633300
//===----------------------------------------------------------------------===//

flang/test/Lower/OpenMP/Todo/taskloop-cancel.f90

Lines changed: 0 additions & 14 deletions
This file was deleted.

flang/test/Lower/OpenMP/Todo/taskloop.f90

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
! This test checks lowering of OpenMP masked taskloop Directive.
2+
3+
! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
4+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
5+
6+
! CHECK-LABEL: omp.private {type = private}
7+
! CHECK-SAME: @[[I_PRIVATE:.*]] : i32
8+
9+
! CHECK-LABEL: omp.private
10+
! CHECK-SAME: {type = firstprivate} @[[J_FIRSTPRIVATE:.*]] : i32
11+
! CHECK-SAME: copy {
12+
! CHECK: hlfir.assign
13+
14+
! CHECK-LABEL: func.func @_QPtest_masked_taskloop() {
15+
! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope
16+
! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_masked_taskloopEi"}
17+
! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]]
18+
! CHECK-SAME: {uniq_name = "_QFtest_masked_taskloopEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
19+
! CHECK: %[[ALLOCA_J:.*]] = fir.address_of(@_QFtest_masked_taskloopEj) : !fir.ref<i32>
20+
! CHECK: %[[DECL_J:.*]]:2 = hlfir.declare %[[ALLOCA_J]] {uniq_name = "_QFtest_masked_taskloopEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
21+
! CHECK: omp.masked {
22+
! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
23+
! CHECK: %[[C10_I32:.*]] = arith.constant 10 : i32
24+
! CHECK: %[[C1_I32_0:.*]] = arith.constant 1 : i32
25+
! CHECK: omp.taskloop private(
26+
! CHECK-SAME: @[[J_FIRSTPRIVATE]] %[[DECL_J]]#0 -> %[[ARG0:.*]], @[[I_PRIVATE]] %[[DECL_I]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>, !fir.ref<i32>) {
27+
! CHECK: omp.loop_nest (%arg2) : i32 = (%[[C1_I32]]) to (%[[C10_I32]]) inclusive step (%[[C1_I32_0]]) {
28+
! CHECK: %[[VAL1:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFtest_masked_taskloopEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
29+
! CHECK: %[[VAL2:.*]]:2 = hlfir.declare %[[ARG1]] {uniq_name = "_QFtest_masked_taskloopEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
30+
! CHECK: hlfir.assign %arg2 to %[[VAL2]]#0 : i32, !fir.ref<i32>
31+
! CHECK: %[[LOAD_J:.*]] = fir.load %[[VAL1]]#0 : !fir.ref<i32>
32+
! CHECK: %[[C1_I32_1:.*]] = arith.constant 1 : i32
33+
! CHECK: %[[RES_J:.*]] = arith.addi %[[LOAD_J]], %[[C1_I32_1]] : i32
34+
! CHECK: hlfir.assign %[[RES_J]] to %[[VAL1]]#0 : i32, !fir.ref<i32>
35+
! CHECK: omp.yield
36+
! CHECK: }
37+
! CHECK: }
38+
! CHECK: omp.terminator
39+
! CHECK: }
40+
! CHECK: return
41+
! CHECK: }
42+
! CHECK: fir.global internal @_QFtest_masked_taskloopEj : i32 {
43+
! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
44+
! CHECK: fir.has_value %[[C1_I32]] : i32
45+
! CHECK: }
46+
47+
48+
subroutine test_masked_taskloop
49+
integer :: i, j = 1
50+
!$omp masked taskloop
51+
do i=1,10
52+
j = j + 1
53+
end do
54+
!$omp end masked taskloop
55+
end subroutine

flang/test/Lower/OpenMP/master_taskloop.f90

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
! This test checks lowering of OpenMP parallel masked taskloop Directive.
2+
3+
! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
4+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
5+
6+
! CHECK-LABEL: omp.private {type = private}
7+
! CHECK-SAME: @[[I_PRIVATE:.*]] : i32
8+
! CHECK-LABEL: func.func @_QPtest_parallel_master_taskloop() {
9+
! CHECK: %[[VAL0:.*]] = fir.dummy_scope : !fir.dscope
10+
! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFtest_parallel_master_taskloopEi"}
11+
! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFtest_parallel_master_taskloopEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
12+
! CHECK: %[[ADDR_J:.*]] = fir.address_of(@_QFtest_parallel_master_taskloopEj) : !fir.ref<i32>
13+
! CHECK: %[[DECL_J:.*]]:2 = hlfir.declare %[[ADDR_J]] {uniq_name = "_QFtest_parallel_master_taskloopEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
14+
! CHECK: omp.parallel {
15+
! CHECK: omp.masked {
16+
! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
17+
! CHECK: %[[C10_I32:.*]] = arith.constant 10 : i32
18+
! CHECK: %[[C1_I32_0:.*]] = arith.constant 1 : i32
19+
! CHECK: omp.taskloop private(@[[I_PRIVATE]] %[[DECL_I]]#0 -> %[[ARG0:.*]] : !fir.ref<i32>) {
20+
! CHECK: omp.loop_nest (%[[ARG1:.*]]) : i32 = (%[[C1_I32]]) to (%[[C10_I32]]) inclusive step (%c1_i32_0) {
21+
! CHECK: %[[VAL1:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFtest_parallel_master_taskloopEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
22+
! CHECK: hlfir.assign %[[ARG1]] to %[[VAL1]]#0 : i32, !fir.ref<i32>
23+
! CHECK: %[[LOAD_J:.*]] = fir.load %[[DECL_J]]#0 : !fir.ref<i32>
24+
! CHECK: %c1_i32_1 = arith.constant 1 : i32
25+
! CHECK: %[[RES_ADD:.*]] = arith.addi %[[LOAD_J]], %c1_i32_1 : i32
26+
! CHECK: hlfir.assign %[[RES_ADD]] to %[[DECL_J]]#0 : i32, !fir.ref<i32>
27+
! CHECK: omp.yield
28+
! CHECK: }
29+
! CHECK: }
30+
! CHECK: omp.terminator
31+
! CHECK: }
32+
! CHECK: omp.terminator
33+
! CHECK: }
34+
! CHECK: return
35+
! CHECK: }
36+
! CHECK: fir.global internal @_QFtest_parallel_master_taskloopEj : i32 {
37+
! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
38+
! CHECK: fir.has_value %[[C1_I32]] : i32
39+
! CHECK: }
40+
41+
subroutine test_parallel_master_taskloop
42+
integer :: i, j = 1
43+
!$omp parallel masked taskloop
44+
do i=1,10
45+
j = j + 1
46+
end do
47+
!$omp end parallel masked taskloop
48+
end subroutine

flang/test/Lower/OpenMP/parallel-master-taskloop.f90

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
! RUN: bbc -emit-hlfir -fopenmp -o - %s -fopenmp-version=50 2>&1 | FileCheck %s
2+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s -fopenmp-version=50 2>&1 | FileCheck %s
3+
4+
! CHECK-LABEL: omp.private {type = private}
5+
! CHECK-SAME: @[[I_PRIVATE:.*]] : i32
6+
7+
! CHECK-LABEL: func.func @_QPomp_taskloop() {
8+
! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope
9+
! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloopEi"}
10+
! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %1 {uniq_name = "_QFomp_taskloopEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
11+
! CHECK: omp.parallel {
12+
! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
13+
! CHECK: %[[C10_I32:.*]] = arith.constant 10 : i32
14+
! CHECK: %[[C1_I32_0:.*]] = arith.constant 1 : i32
15+
! CHECK: omp.taskloop private(@[[I_PRIVATE]] %2#0 -> %[[ARG0:.*]] : !fir.ref<i32>) {
16+
! CHECK: omp.loop_nest (%[[ARG1:.*]]) : i32 = (%[[C1_I32]]) to (%[[C10_I32]]) inclusive step (%[[C1_I32_0]]) {
17+
! CHECK: %[[IDX:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFomp_taskloopEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
18+
! CHECK: hlfir.assign %[[ARG1]] to %[[IDX]]#0 : i32, !fir.ref<i32>
19+
! CHECK: omp.cancel cancellation_construct_type(taskgroup)
20+
! CHECK: omp.yield
21+
! CHECK: }
22+
! CHECK: }
23+
! CHECK: omp.terminator
24+
! CHECK: }
25+
! CHECK: return
26+
! CHECK: }
27+
28+
subroutine omp_taskloop
29+
integer :: i
30+
!$omp parallel
31+
!$omp taskloop
32+
do i = 1, 10
33+
!$omp cancel taskgroup
34+
end do
35+
!$omp end taskloop
36+
!$omp end parallel
37+
end subroutine omp_taskloop

flang/test/Lower/OpenMP/taskloop.f90

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
2+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
3+
4+
! CHECK-LABEL: omp.private
5+
! CHECK-SAME: {type = private} @[[I_PRIVATE_TEST2:.*]] : i32
6+
7+
! CHECK-LABEL: omp.private
8+
! CHECK-SAME: {type = private} @[[RES_PRIVATE_TEST2:.*]] : i32
9+
10+
! CHECK-LABEL: omp.private
11+
! CHECK-SAME: {type = private} @[[I_PRIVATE:.*]] : i32
12+
13+
! CHECK-LABEL: omp.private
14+
! CHECK-SAME: {type = firstprivate} @[[RES_FIRSTPRIVATE:.*]] : i32
15+
! CHECK-SAME: copy {
16+
! CHECK: hlfir.assign
17+
18+
! CHECK-LABEL: func.func @_QPomp_taskloop
19+
! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloopEi"}
20+
! CHECK: %[[I_VAL:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFomp_taskloopEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
21+
! CHECK: %[[ALLOCA_RES:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_taskloopEres"}
22+
! CHECK: %[[RES_VAL:.*]]:2 = hlfir.declare %[[ALLOCA_RES]] {uniq_name = "_QFomp_taskloopEres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
23+
! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
24+
! CHECK: %[[C10_I32:.*]] = arith.constant 10 : i32
25+
! CHECK: %[[C1_I32_0:.*]] = arith.constant 1 : i32
26+
! CHECK: omp.taskloop private(@[[RES_FIRSTPRIVATE]] %[[RES_VAL]]#0 -> %[[PRIV_RES:.*]], @[[I_PRIVATE]] %[[I_VAL]]#0 -> %[[PRIV_I:.*]] : !fir.ref<i32>, !fir.ref<i32>) {
27+
! CHECK: omp.loop_nest (%[[ARG2:.*]]) : i32 = (%[[C1_I32]]) to (%[[C10_I32]]) inclusive step (%[[C1_I32_0]]) {
28+
! CHECK: %[[RES_DECL:.*]]:2 = hlfir.declare %[[PRIV_RES]] {uniq_name = "_QFomp_taskloopEres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
29+
! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[PRIV_I]] {uniq_name = "_QFomp_taskloopEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
30+
! CHECK: hlfir.assign %[[ARG2]] to %[[I_DECL]]#0 : i32, !fir.ref<i32>
31+
! CHECK: %[[LOAD_RES:.*]] = fir.load %[[RES_DECL]]#0 : !fir.ref<i32>
32+
! CHECK: %[[C1_I32_1:.*]] = arith.constant 1 : i32
33+
! CHECK: %[[OUT_VAL:.*]] = arith.addi %[[LOAD_RES]], %[[C1_I32_1]] : i32
34+
! CHECK: hlfir.assign %[[OUT_VAL]] to %[[RES_DECL]]#0 : i32, !fir.ref<i32>
35+
! CHECK: omp.yield
36+
! CHECK: }
37+
! CHECK: }
38+
! CHECK: return
39+
! CHECK: }
40+
41+
subroutine omp_taskloop
42+
integer :: res, i
43+
!$omp taskloop
44+
do i = 1, 10
45+
res = res + 1
46+
end do
47+
!$omp end taskloop
48+
end subroutine omp_taskloop
49+
50+
51+
! CHECK-LABEL: func.func @_QPomp_taskloop_private
52+
! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloop_privateEi"}
53+
! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFomp_taskloop_privateEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
54+
! CHECK: %[[ALLOCA_RES:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_taskloop_privateEres"}
55+
! CHECK: %[[DECL_RES:.*]]:2 = hlfir.declare %[[ALLOCA_RES]] {uniq_name = "_QFomp_taskloop_privateEres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
56+
subroutine omp_taskloop_private
57+
integer :: res, i
58+
! CHECK: omp.taskloop private(@[[RES_PRIVATE_TEST2]] %[[DECL_RES]]#0 -> %[[ARG0:.*]], @[[I_PRIVATE_TEST2]] %[[DECL_I]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>, !fir.ref<i32>) {
59+
! CHECK: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}}) {
60+
! CHECK: %[[VAL1:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFomp_taskloop_privateEres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
61+
!$omp taskloop private(res)
62+
do i = 1, 10
63+
! CHECK: %[[LOAD_RES:.*]] = fir.load %[[VAL1]]#0 : !fir.ref<i32>
64+
! CHECK: %[[C1_I32_1:.*]] = arith.constant 1 : i32
65+
! CHECK: %[[ADD_VAL:.*]] = arith.addi %[[LOAD_RES]], %[[C1_I32_1]] : i32
66+
! CHECK: hlfir.assign %[[ADD_VAL]] to %[[VAL1]]#0 : i32, !fir.ref<i32>
67+
res = res + 1
68+
end do
69+
! CHECK: return
70+
! CHECK: }
71+
!$omp end taskloop
72+
end subroutine omp_taskloop_private

mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2785,16 +2785,16 @@ LogicalResult TaskgroupOp::verify() {
27852785
void TaskloopOp::build(OpBuilder &builder, OperationState &state,
27862786
const TaskloopOperands &clauses) {
27872787
MLIRContext *ctx = builder.getContext();
2788-
// TODO Store clauses in op: privateVars, privateSyms.
27892788
TaskloopOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
27902789
clauses.final, clauses.grainsizeMod, clauses.grainsize,
27912790
clauses.ifExpr, clauses.inReductionVars,
27922791
makeDenseBoolArrayAttr(ctx, clauses.inReductionByref),
27932792
makeArrayAttr(ctx, clauses.inReductionSyms),
27942793
clauses.mergeable, clauses.nogroup, clauses.numTasksMod,
2795-
clauses.numTasks, clauses.priority, /*private_vars=*/{},
2796-
/*private_syms=*/nullptr, clauses.reductionMod,
2797-
clauses.reductionVars,
2794+
clauses.numTasks, clauses.priority,
2795+
/*private_vars=*/clauses.privateVars,
2796+
/*private_syms=*/makeArrayAttr(ctx, clauses.privateSyms),
2797+
clauses.reductionMod, clauses.reductionVars,
27982798
makeDenseBoolArrayAttr(ctx, clauses.reductionByref),
27992799
makeArrayAttr(ctx, clauses.reductionSyms), clauses.untied);
28002800
}

0 commit comments

Comments
 (0)