Skip to content

Commit 263e312

Browse files
committed
[flang][OpenMP] Add basic support to lower loop to MLIR
Adds initial support for lowering the `loop` directive to MLIR. The PR includes basic suport and testing for the following clauses: * `collapse` * `order` * `private` * `reduction`
1 parent 164fc2f commit 263e312

File tree

6 files changed

+146
-17
lines changed

6 files changed

+146
-17
lines changed

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2051,6 +2051,52 @@ static void genStandaloneDo(lower::AbstractConverter &converter,
20512051
llvm::omp::Directive::OMPD_do, dsp);
20522052
}
20532053

2054+
static void genLoopClauses(
2055+
lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
2056+
const List<Clause> &clauses, mlir::Location loc,
2057+
mlir::omp::LoopOperands &clauseOps,
2058+
llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSyms) {
2059+
ClauseProcessor cp(converter, semaCtx, clauses);
2060+
cp.processOrder(clauseOps);
2061+
cp.processReduction(loc, clauseOps, reductionSyms);
2062+
cp.processTODO<clause::Bind, clause::Lastprivate>(
2063+
loc, llvm::omp::Directive::OMPD_loop);
2064+
}
2065+
2066+
static void genLoopOp(lower::AbstractConverter &converter,
2067+
lower::SymMap &symTable,
2068+
semantics::SemanticsContext &semaCtx,
2069+
lower::pft::Evaluation &eval, mlir::Location loc,
2070+
const ConstructQueue &queue,
2071+
ConstructQueue::const_iterator item) {
2072+
mlir::omp::LoopOperands loopClauseOps;
2073+
llvm::SmallVector<const semantics::Symbol *> loopReductionSyms;
2074+
genLoopClauses(converter, semaCtx, item->clauses, loc, loopClauseOps,
2075+
loopReductionSyms);
2076+
2077+
DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
2078+
/*shouldCollectPreDeterminedSymbols=*/true,
2079+
/*useDelayedPrivatization=*/true, &symTable);
2080+
dsp.processStep1(&loopClauseOps);
2081+
2082+
mlir::omp::LoopNestOperands loopNestClauseOps;
2083+
llvm::SmallVector<const semantics::Symbol *> iv;
2084+
genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc,
2085+
loopNestClauseOps, iv);
2086+
2087+
EntryBlockArgs loopArgs;
2088+
loopArgs.priv.syms = dsp.getDelayedPrivSymbols();
2089+
loopArgs.priv.vars = loopClauseOps.privateVars;
2090+
loopArgs.reduction.syms = loopReductionSyms;
2091+
loopArgs.reduction.vars = loopClauseOps.reductionVars;
2092+
2093+
auto loopOp =
2094+
genWrapperOp<mlir::omp::LoopOp>(converter, loc, loopClauseOps, loopArgs);
2095+
genLoopNestOp(converter, symTable, semaCtx, eval, loc, queue, item,
2096+
loopNestClauseOps, iv, {{loopOp, loopArgs}},
2097+
llvm::omp::Directive::OMPD_loop, dsp);
2098+
}
2099+
20542100
static void genStandaloneParallel(lower::AbstractConverter &converter,
20552101
lower::SymMap &symTable,
20562102
semantics::SemanticsContext &semaCtx,
@@ -2479,7 +2525,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
24792525
genStandaloneDo(converter, symTable, semaCtx, eval, loc, queue, item);
24802526
break;
24812527
case llvm::omp::Directive::OMPD_loop:
2482-
TODO(loc, "Unhandled directive " + llvm::omp::getOpenMPDirectiveName(dir));
2528+
genLoopOp(converter, symTable, semaCtx, eval, loc, queue, item);
24832529
break;
24842530
case llvm::omp::Directive::OMPD_masked:
24852531
genMaskedOp(converter, symTable, semaCtx, eval, loc, queue, item);

flang/test/Lower/OpenMP/Todo/loop-directive.f90

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
! This test checks lowering of OpenMP loop 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: omp.declare_reduction @[[RED:add_reduction_i32]] : i32
7+
! CHECK: omp.private {type = private} @[[DUMMY_PRIV:.*test_privateEdummy_private.*]] : !fir.ref<i32>
8+
! CHECK: omp.private {type = private} @[[I_PRIV:.*test_no_clausesEi.*]] : !fir.ref<i32>
9+
10+
! CHECK-LABEL: func.func @_QPtest_no_clauses
11+
subroutine test_no_clauses()
12+
integer :: i, j, dummy = 1
13+
14+
! CHECK: omp.loop private(@[[I_PRIV]] %{{.*}}#0 -> %[[ARG:.*]] : !fir.ref<i32>) {
15+
! CHECK: omp.loop_nest (%[[IV:.*]]) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
16+
! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]]
17+
! CHECK: fir.store %[[IV]] to %[[ARG_DECL]]#1 : !fir.ref<i32>
18+
! CHECK: }
19+
! CHECK: }
20+
!$omp loop
21+
do i=1,10
22+
dummy = dummy + 1
23+
end do
24+
!$omp end loop
25+
end subroutine
26+
27+
! CHECK-LABEL: func.func @_QPtest_collapse
28+
subroutine test_collapse()
29+
integer :: i, j, dummy = 1
30+
! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
31+
! CHECK: omp.loop_nest (%{{.*}}, %{{.*}}) : i32 {{.*}} {
32+
! CHECK: }
33+
! CHECK: }
34+
!$omp loop collapse(2)
35+
do i=1,10
36+
do j=2,20
37+
dummy = dummy + 1
38+
end do
39+
end do
40+
!$omp end loop
41+
end subroutine
42+
43+
! CHECK-LABEL: func.func @_QPtest_private
44+
subroutine test_private()
45+
integer :: i, dummy = 1
46+
! CHECK: omp.loop private(@[[DUMMY_PRIV]] %{{.*}}#0 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
47+
! CHECK: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
48+
! CHECK: }
49+
! CHECK: }
50+
!$omp loop private(dummy)
51+
do i=1,10
52+
dummy = dummy + 1
53+
end do
54+
!$omp end loop
55+
end subroutine
56+
57+
58+
! CHECK-LABEL: func.func @_QPtest_order
59+
subroutine test_order()
60+
integer :: i, dummy = 1
61+
! CHECK: omp.loop order(reproducible:concurrent) private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
62+
! CHECK: }
63+
!$omp loop order(concurrent)
64+
do i=1,10
65+
dummy = dummy + 1
66+
end do
67+
!$omp end loop
68+
end subroutine
69+
70+
! CHECK-LABEL: func.func @_QPtest_reduction
71+
subroutine test_reduction()
72+
integer :: i, dummy = 1
73+
74+
! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}} : !{{.*}}) reduction
75+
! CHECK-SAME: (@[[RED]] %{{.*}}#0 -> %{{.*}} : !{{.*}}) {
76+
! CHECK: }
77+
!$omp loop reduction(+:dummy)
78+
do i=1,10
79+
dummy = dummy + 1
80+
end do
81+
!$omp end loop
82+
end subroutine

mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,10 @@ def LoopOp : OpenMP_Op<"loop", traits = [
422422
$reduction_syms) attr-dict
423423
}];
424424

425+
let builders = [
426+
OpBuilder<(ins CArg<"const LoopOperands &">:$clauses)>
427+
];
428+
425429
let hasVerifier = 1;
426430
let hasRegionVerifier = 1;
427431
}

mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ void mlir::configureOpenMPToLLVMConversionLegality(
238238
omp::ParallelOp, omp::PrivateClauseOp, omp::SectionOp, omp::SectionsOp,
239239
omp::SimdOp, omp::SingleOp, omp::TargetDataOp, omp::TargetOp,
240240
omp::TaskgroupOp, omp::TaskloopOp, omp::TaskOp, omp::TeamsOp,
241-
omp::WsloopOp>([&](Operation *op) {
241+
omp::WsloopOp, omp::LoopOp>([&](Operation *op) {
242242
return std::all_of(op->getRegions().begin(), op->getRegions().end(),
243243
[&](Region &region) {
244244
return typeConverter.isLegal(&region);
@@ -284,6 +284,7 @@ void mlir::populateOpenMPToLLVMConversionPatterns(LLVMTypeConverter &converter,
284284
RegionOpConversion<omp::TargetOp>, RegionOpConversion<omp::TaskgroupOp>,
285285
RegionOpConversion<omp::TaskloopOp>, RegionOpConversion<omp::TaskOp>,
286286
RegionOpConversion<omp::TeamsOp>, RegionOpConversion<omp::WsloopOp>,
287+
RegionOpConversion<omp::LoopOp>,
287288
RegionOpWithVarOperandsConversion<omp::AtomicUpdateOp>>(converter);
288289
}
289290

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,17 @@ LogicalResult LoopWrapperInterface::verifyImpl() {
19521952
// LoopOp
19531953
//===----------------------------------------------------------------------===//
19541954

1955+
void LoopOp::build(OpBuilder &builder, OperationState &state,
1956+
const LoopOperands &clauses) {
1957+
MLIRContext *ctx = builder.getContext();
1958+
1959+
LoopOp::build(builder, state, clauses.bindKind, clauses.privateVars,
1960+
makeArrayAttr(ctx, clauses.privateSyms), clauses.order,
1961+
clauses.orderMod, clauses.reductionVars,
1962+
makeDenseBoolArrayAttr(ctx, clauses.reductionByref),
1963+
makeArrayAttr(ctx, clauses.reductionSyms));
1964+
}
1965+
19551966
LogicalResult LoopOp::verify() {
19561967
return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
19571968
getReductionByref());

0 commit comments

Comments
 (0)