Skip to content

Commit 69253a2

Browse files
committed
[Flang][OpenMP] Add lowering support for DO SIMD
This patch adds support for lowering 'DO SIMD' constructs to MLIR. SIMD information is now stored in an `omp.simd` loop wrapper, which is currently ignored by the OpenMP dialect to LLVM IR translation stage. The end result is that runtime behavior of compiled 'DO SIMD' constructs does not change after this patch, so 'DO SIMD' still runs like 'DO' (i.e. SIMD width = 1). However, all of the required information is now present in the resulting MLIR representation. To avoid confusion, the previous wsloop-simd.f90 lit test is renamed to wsloop-schedule.f90 and a new wsloop-simd.f90 test is created to check the addition of SIMD clauses to the `omp.simd` operation produced when a 'DO SIMD' construct is lowered to MLIR.
1 parent 938a35a commit 69253a2

File tree

10 files changed

+155
-90
lines changed

10 files changed

+155
-90
lines changed

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,19 +1986,44 @@ static void genCompositeDoSimd(lower::AbstractConverter &converter,
19861986
const ConstructQueue &queue,
19871987
ConstructQueue::iterator item,
19881988
DataSharingProcessor &dsp) {
1989-
ClauseProcessor cp(converter, semaCtx, item->clauses);
1990-
cp.processTODO<clause::Aligned, clause::Allocate, clause::Linear,
1991-
clause::Safelen, clause::Simdlen>(loc,
1992-
llvm::omp::OMPD_do_simd);
1993-
// TODO: Add support for vectorization - add vectorization hints inside loop
1994-
// body.
1995-
// OpenMP standard does not specify the length of vector instructions.
1996-
// Currently we safely assume that for !$omp do simd pragma the SIMD length
1997-
// is equal to 1 (i.e. we generate standard workshare loop).
1998-
// When support for vectorization is enabled, then we need to add handling of
1999-
// if clause. Currently if clause can be skipped because we always assume
2000-
// SIMD length = 1.
2001-
genStandaloneDo(converter, symTable, semaCtx, eval, loc, queue, item, dsp);
1989+
lower::StatementContext stmtCtx;
1990+
1991+
// Clause processing.
1992+
mlir::omp::WsloopClauseOps wsloopClauseOps;
1993+
llvm::SmallVector<const semantics::Symbol *> wsloopReductionSyms;
1994+
llvm::SmallVector<mlir::Type> wsloopReductionTypes;
1995+
genWsloopClauses(converter, semaCtx, stmtCtx, item->clauses, loc,
1996+
wsloopClauseOps, wsloopReductionTypes, wsloopReductionSyms);
1997+
1998+
mlir::omp::SimdClauseOps simdClauseOps;
1999+
genSimdClauses(converter, semaCtx, item->clauses, loc, simdClauseOps);
2000+
2001+
mlir::omp::LoopNestClauseOps loopNestClauseOps;
2002+
llvm::SmallVector<const semantics::Symbol *> iv;
2003+
genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc,
2004+
loopNestClauseOps, iv);
2005+
2006+
// Operation creation.
2007+
// TODO: Add private variables to entry block arguments.
2008+
auto wsloopOp = genWrapperOp<mlir::omp::WsloopOp>(
2009+
converter, loc, wsloopClauseOps, wsloopReductionTypes);
2010+
2011+
// TODO: Populate entry block arguments with reduction and private variables.
2012+
auto simdOp = genWrapperOp<mlir::omp::SimdOp>(converter, loc, simdClauseOps,
2013+
/*blockArgTypes=*/{});
2014+
2015+
// Construct wrapper entry block list and associated symbols. It is important
2016+
// that the symbol and block argument order match, so that the symbol-value
2017+
// bindings created are correct.
2018+
// TODO: Add omp.wsloop private and omp.simd private and reduction args.
2019+
auto wrapperArgs = llvm::to_vector(llvm::concat<mlir::BlockArgument>(
2020+
wsloopOp.getRegion().getArguments(), simdOp.getRegion().getArguments()));
2021+
2022+
assert(wsloopReductionSyms.size() == wrapperArgs.size() &&
2023+
"Number of symbols and wrapper block arguments must match");
2024+
genLoopNestOp(converter, symTable, semaCtx, eval, loc, queue, item,
2025+
loopNestClauseOps, iv, wsloopReductionSyms, wrapperArgs,
2026+
llvm::omp::Directive::OMPD_do_simd, dsp);
20022027
}
20032028

20042029
static void genCompositeTaskloopSimd(

flang/test/Lower/OpenMP/Todo/omp-do-simd-aligned.f90

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

flang/test/Lower/OpenMP/Todo/omp-do-simd-linear.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
55
subroutine testDoSimdLinear(int_array)
66
integer :: int_array(*)
7-
!CHECK: not yet implemented: Unhandled clause LINEAR in DO SIMD construct
7+
!CHECK: not yet implemented: Unhandled clause LINEAR in DO construct
88
!$omp do simd linear(int_array)
99
do index_ = 1, 10
1010
end do

flang/test/Lower/OpenMP/Todo/omp-do-simd-safelen.f90

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

flang/test/Lower/OpenMP/Todo/omp-do-simd-simdlen.f90

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

flang/test/Lower/OpenMP/if-clause.f90

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ program main
3030
! CHECK: omp.wsloop
3131
! CHECK-NOT: if({{.*}})
3232
! CHECK-SAME: {
33+
! CHECK-NEXT: omp.simd
34+
! CHECK-NOT: if({{.*}})
35+
! CHECK-SAME: {
3336
! CHECK-NEXT: omp.loop_nest
3437
!$omp do simd
3538
do i = 1, 10
@@ -39,6 +42,8 @@ program main
3942
! CHECK: omp.wsloop
4043
! CHECK-NOT: if({{.*}})
4144
! CHECK-SAME: {
45+
! CHECK-NEXT: omp.simd
46+
! CHECK-SAME: if({{.*}})
4247
! CHECK-NEXT: omp.loop_nest
4348
!$omp do simd if(.true.)
4449
do i = 1, 10
@@ -48,6 +53,8 @@ program main
4853
! CHECK: omp.wsloop
4954
! CHECK-NOT: if({{.*}})
5055
! CHECK-SAME: {
56+
! CHECK-NEXT: omp.simd
57+
! CHECK-SAME: if({{.*}})
5158
! CHECK-NEXT: omp.loop_nest
5259
!$omp do simd if(simd: .true.)
5360
do i = 1, 10
@@ -122,6 +129,9 @@ program main
122129
! CHECK: omp.wsloop
123130
! CHECK-NOT: if({{.*}})
124131
! CHECK-SAME: {
132+
! CHECK-NEXT: omp.simd
133+
! CHECK-NOT: if({{.*}})
134+
! CHECK-SAME: {
125135
! CHECK-NEXT: omp.loop_nest
126136
!$omp parallel do simd
127137
do i = 1, 10
@@ -133,6 +143,8 @@ program main
133143
! CHECK: omp.wsloop
134144
! CHECK-NOT: if({{.*}})
135145
! CHECK-SAME: {
146+
! CHECK-NEXT: omp.simd
147+
! CHECK-SAME: if({{.*}})
136148
! CHECK-NEXT: omp.loop_nest
137149
!$omp parallel do simd if(.true.)
138150
do i = 1, 10
@@ -144,6 +156,8 @@ program main
144156
! CHECK: omp.wsloop
145157
! CHECK-NOT: if({{.*}})
146158
! CHECK-SAME: {
159+
! CHECK-NEXT: omp.simd
160+
! CHECK-SAME: if({{.*}})
147161
! CHECK-NEXT: omp.loop_nest
148162
!$omp parallel do simd if(parallel: .true.) if(simd: .false.)
149163
do i = 1, 10
@@ -155,6 +169,9 @@ program main
155169
! CHECK: omp.wsloop
156170
! CHECK-NOT: if({{.*}})
157171
! CHECK-SAME: {
172+
! CHECK-NEXT: omp.simd
173+
! CHECK-NOT: if({{.*}})
174+
! CHECK-SAME: {
158175
! CHECK-NEXT: omp.loop_nest
159176
!$omp parallel do simd if(parallel: .true.)
160177
do i = 1, 10
@@ -167,6 +184,8 @@ program main
167184
! CHECK: omp.wsloop
168185
! CHECK-NOT: if({{.*}})
169186
! CHECK-SAME: {
187+
! CHECK-NEXT: omp.simd
188+
! CHECK-SAME: if({{.*}})
170189
! CHECK-NEXT: omp.loop_nest
171190
!$omp parallel do simd if(simd: .true.)
172191
do i = 1, 10
@@ -355,6 +374,9 @@ program main
355374
! CHECK: omp.wsloop
356375
! CHECK-NOT: if({{.*}})
357376
! CHECK-SAME: {
377+
! CHECK-NEXT: omp.simd
378+
! CHECK-NOT: if({{.*}})
379+
! CHECK-SAME: {
358380
! CHECK-NEXT: omp.loop_nest
359381
!$omp target parallel do simd
360382
do i = 1, 10
@@ -368,6 +390,8 @@ program main
368390
! CHECK: omp.wsloop
369391
! CHECK-NOT: if({{.*}})
370392
! CHECK-SAME: {
393+
! CHECK-NEXT: omp.simd
394+
! CHECK-SAME: if({{.*}})
371395
! CHECK-NEXT: omp.loop_nest
372396
!$omp target parallel do simd if(.true.)
373397
do i = 1, 10
@@ -381,6 +405,8 @@ program main
381405
! CHECK: omp.wsloop
382406
! CHECK-NOT: if({{.*}})
383407
! CHECK-SAME: {
408+
! CHECK-NEXT: omp.simd
409+
! CHECK-SAME: if({{.*}})
384410
! CHECK-NEXT: omp.loop_nest
385411
!$omp target parallel do simd if(target: .true.) if(parallel: .false.) &
386412
!$omp& if(simd: .true.)
@@ -396,6 +422,9 @@ program main
396422
! CHECK: omp.wsloop
397423
! CHECK-NOT: if({{.*}})
398424
! CHECK-SAME: {
425+
! CHECK-NEXT: omp.simd
426+
! CHECK-NOT: if({{.*}})
427+
! CHECK-SAME: {
399428
! CHECK-NEXT: omp.loop_nest
400429
!$omp target parallel do simd if(target: .true.)
401430
do i = 1, 10
@@ -410,6 +439,8 @@ program main
410439
! CHECK: omp.wsloop
411440
! CHECK-NOT: if({{.*}})
412441
! CHECK-SAME: {
442+
! CHECK-NEXT: omp.simd
443+
! CHECK-SAME: if({{.*}})
413444
! CHECK-NEXT: omp.loop_nest
414445
!$omp target parallel do simd if(parallel: .true.) if(simd: .false.)
415446
do i = 1, 10

flang/test/Lower/OpenMP/loop-compound.f90

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ program main
2323
! DO SIMD
2424
! ----------------------------------------------------------------------------
2525
! CHECK: omp.wsloop
26+
! CHECK-NEXT: omp.simd
2627
! CHECK-NEXT: omp.loop_nest
2728
!$omp do simd
2829
do i = 1, 10
@@ -34,6 +35,7 @@ program main
3435
! ----------------------------------------------------------------------------
3536
! CHECK: omp.parallel
3637
! CHECK: omp.wsloop
38+
! CHECK-NEXT: omp.simd
3739
! CHECK-NEXT: omp.loop_nest
3840
!$omp parallel do simd
3941
do i = 1, 10
@@ -57,6 +59,7 @@ program main
5759
! CHECK: omp.target
5860
! CHECK: omp.parallel
5961
! CHECK: omp.wsloop
62+
! CHECK-NEXT: omp.simd
6063
! CHECK-NEXT: omp.loop_nest
6164
!$omp target parallel do simd
6265
do i = 1, 10
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
! This test checks lowering of OpenMP DO Directive(Worksharing) with
2+
! simd schedule modifier.
3+
4+
! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
5+
6+
program wsloop_dynamic
7+
integer :: i
8+
!CHECK-LABEL: func @_QQmain()
9+
10+
!$OMP PARALLEL
11+
!CHECK: omp.parallel {
12+
13+
!$OMP DO SCHEDULE(simd: runtime)
14+
!CHECK: %[[WS_LB:.*]] = arith.constant 1 : i32
15+
!CHECK: %[[WS_UB:.*]] = arith.constant 9 : i32
16+
!CHECK: %[[WS_STEP:.*]] = arith.constant 1 : i32
17+
!CHECK: omp.wsloop schedule(runtime, simd) nowait {
18+
!CHECK-NEXT: omp.loop_nest (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]]) {
19+
!CHECK: fir.store %[[I]] to %[[STORE:.*]]#1 : !fir.ref<i32>
20+
21+
do i=1, 9
22+
print*, i
23+
!CHECK: %[[RTBEGIN:.*]] = fir.call @_FortranAioBeginExternalListOutput
24+
!CHECK: %[[LOAD:.*]] = fir.load %[[STORE]]#0 : !fir.ref<i32>
25+
!CHECK: fir.call @_FortranAioOutputInteger32(%[[RTBEGIN]], %[[LOAD]]) {{.*}}: (!fir.ref<i8>, i32) -> i1
26+
!CHECK: fir.call @_FortranAioEndIoStatement(%[[RTBEGIN]]) {{.*}}: (!fir.ref<i8>) -> i32
27+
end do
28+
!CHECK: omp.yield
29+
!CHECK: }
30+
!CHECK: omp.terminator
31+
!CHECK: }
32+
!CHECK: omp.terminator
33+
!CHECK: }
34+
35+
!$OMP END DO NOWAIT
36+
!$OMP END PARALLEL
37+
end
Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,47 @@
1-
! This test checks lowering of OpenMP DO Directive(Worksharing) with
2-
! simd schedule modifier.
1+
! This test checks lowering of OpenMP DO SIMD composite constructs.
32

43
! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
4+
! RUN: %flang_fc1 -fopenmp -emit-hlfir %s -o - | FileCheck %s
55

6-
program wsloop_dynamic
7-
integer :: i
8-
!CHECK-LABEL: func @_QQmain()
6+
! CHECK-LABEL: func.func @_QPdo_simd_aligned(
7+
subroutine do_simd_aligned(A)
8+
use iso_c_binding
9+
type(c_ptr) :: A
10+
11+
! CHECK: omp.wsloop
12+
! CHECK-NOT: aligned({{.*}})
13+
! CHECK-SAME: {
14+
! CHECK-NEXT: omp.simd
15+
! CHECK-SAME: aligned({{.*}})
16+
!$omp do simd aligned(A)
17+
do index_ = 1, 10
18+
call c_test_call(A)
19+
end do
20+
!$omp end do simd
21+
end subroutine do_simd_aligned
922

10-
!$OMP PARALLEL
11-
!CHECK: omp.parallel {
23+
! CHECK-LABEL: func.func @_QPdo_simd_safelen(
24+
subroutine do_simd_safelen()
25+
! CHECK: omp.wsloop
26+
! CHECK-NOT: safelen({{.*}})
27+
! CHECK-SAME: {
28+
! CHECK-NEXT: omp.simd
29+
! CHECK-SAME: safelen({{.*}})
30+
!$omp do simd safelen(4)
31+
do index_ = 1, 10
32+
end do
33+
!$omp end do simd
34+
end subroutine do_simd_safelen
1235

13-
!$OMP DO SCHEDULE(simd: runtime)
14-
!CHECK: %[[WS_LB:.*]] = arith.constant 1 : i32
15-
!CHECK: %[[WS_UB:.*]] = arith.constant 9 : i32
16-
!CHECK: %[[WS_STEP:.*]] = arith.constant 1 : i32
17-
!CHECK: omp.wsloop schedule(runtime, simd) nowait {
18-
!CHECK-NEXT: omp.loop_nest (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]]) {
19-
!CHECK: fir.store %[[I]] to %[[STORE:.*]]#1 : !fir.ref<i32>
20-
21-
do i=1, 9
22-
print*, i
23-
!CHECK: %[[RTBEGIN:.*]] = fir.call @_FortranAioBeginExternalListOutput
24-
!CHECK: %[[LOAD:.*]] = fir.load %[[STORE]]#0 : !fir.ref<i32>
25-
!CHECK: fir.call @_FortranAioOutputInteger32(%[[RTBEGIN]], %[[LOAD]]) {{.*}}: (!fir.ref<i8>, i32) -> i1
26-
!CHECK: fir.call @_FortranAioEndIoStatement(%[[RTBEGIN]]) {{.*}}: (!fir.ref<i8>) -> i32
27-
end do
28-
!CHECK: omp.yield
29-
!CHECK: }
30-
!CHECK: omp.terminator
31-
!CHECK: }
32-
!CHECK: omp.terminator
33-
!CHECK: }
34-
35-
!$OMP END DO NOWAIT
36-
!$OMP END PARALLEL
37-
end
36+
! CHECK-LABEL: func.func @_QPdo_simd_simdlen(
37+
subroutine do_simd_simdlen()
38+
! CHECK: omp.wsloop
39+
! CHECK-NOT: simdlen({{.*}})
40+
! CHECK-SAME: {
41+
! CHECK-NEXT: omp.simd
42+
! CHECK-SAME: simdlen({{.*}})
43+
!$omp do simd simdlen(4)
44+
do index_ = 1, 10
45+
end do
46+
!$omp end do simd
47+
end subroutine do_simd_simdlen

mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,9 @@ static LogicalResult
899899
convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder,
900900
LLVM::ModuleTranslation &moduleTranslation) {
901901
auto wsloopOp = cast<omp::WsloopOp>(opInst);
902+
// FIXME: Here any other nested wrappers (e.g. omp.simd) are skipped, so
903+
// codegen for composite constructs like 'DO/FOR SIMD' will be the same as for
904+
// 'DO/FOR'.
902905
auto loopOp = cast<omp::LoopNestOp>(wsloopOp.getWrappedLoop());
903906

904907
llvm::ArrayRef<bool> isByRef = getIsByRef(wsloopOp.getReductionVarsByref());

0 commit comments

Comments
 (0)