Skip to content

Commit 29f167a

Browse files
kiranchandramohanvdonaldsonschweitzpgiclementval
committed
[Flang][OpenMP] Fixes for unstructured OpenMP code
Since the FIR operations are mostly structured, it is only the functions that could contain multiple blocks inside an operation. This changes with OpenMP since OpenMP regions can contain multiple blocks. For unstructured code, the blocks are created in advance and belong to the top-level function. This caused code in OpenMP region to be placed under the function level. In this fix, if the OpenMP region is unstructured then new blocks are created inside it. Note1: This is part of upstreaming from the fir-dev branch of https://github.com/flang-compiler/f18-llvm-project. The code in this patch is a subset of the changes in flang-compiler#1178. Reviewed By: vdonaldson Differential Revision: https://reviews.llvm.org/D126293 Co-authored-by: Val Donaldson <[email protected]> Co-authored-by: Eric Schweitz <[email protected]> Co-authored-by: Valentin Clement <[email protected]>
1 parent 0bf3c38 commit 29f167a

File tree

2 files changed

+159
-17
lines changed

2 files changed

+159
-17
lines changed

flang/lib/Lower/OpenMP.cpp

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,35 @@ static mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
138138
return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize);
139139
}
140140

141+
/// Create empty blocks for the current region.
142+
/// These blocks replace blocks parented to an enclosing region.
143+
void createEmptyRegionBlocks(
144+
fir::FirOpBuilder &firOpBuilder,
145+
std::list<Fortran::lower::pft::Evaluation> &evaluationList) {
146+
auto *region = &firOpBuilder.getRegion();
147+
for (auto &eval : evaluationList) {
148+
if (eval.block) {
149+
if (eval.block->empty()) {
150+
eval.block->erase();
151+
eval.block = firOpBuilder.createBlock(region);
152+
} else {
153+
[[maybe_unused]] auto &terminatorOp = eval.block->back();
154+
assert((mlir::isa<mlir::omp::TerminatorOp>(terminatorOp) ||
155+
mlir::isa<mlir::omp::YieldOp>(terminatorOp)) &&
156+
"expected terminator op");
157+
}
158+
}
159+
if (eval.hasNestedEvaluations())
160+
createEmptyRegionBlocks(firOpBuilder, eval.getNestedEvaluations());
161+
}
162+
}
163+
141164
/// Create the body (block) for an OpenMP Operation.
142165
///
143166
/// \param [in] op - the operation the body belongs to.
144167
/// \param [inout] converter - converter to use for the clauses.
145168
/// \param [in] loc - location in source code.
169+
/// \param [in] eval - current PFT node/evaluation.
146170
/// \oaran [in] clauses - list of clauses to process.
147171
/// \param [in] args - block arguments (induction variable[s]) for the
148172
//// region.
@@ -151,14 +175,14 @@ static mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
151175
template <typename Op>
152176
static void
153177
createBodyOfOp(Op &op, Fortran::lower::AbstractConverter &converter,
154-
mlir::Location &loc,
178+
mlir::Location &loc, Fortran::lower::pft::Evaluation &eval,
155179
const Fortran::parser::OmpClauseList *clauses = nullptr,
156180
const SmallVector<const Fortran::semantics::Symbol *> &args = {},
157181
bool outerCombined = false) {
158-
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
159-
// If arguments for the region are provided then create the block with those
160-
// arguments. Also update the symbol's address with the mlir argument values.
161-
// e.g. For loops the arguments are the induction variable. And all further
182+
auto &firOpBuilder = converter.getFirOpBuilder();
183+
// If an argument for the region is provided then create the block with that
184+
// argument. Also update the symbol's address with the mlir argument value.
185+
// e.g. For loops the argument is the induction variable. And all further
162186
// uses of the induction variable should use this mlir value.
163187
if (args.size()) {
164188
std::size_t loopVarTypeSize = 0;
@@ -184,7 +208,10 @@ createBodyOfOp(Op &op, Fortran::lower::AbstractConverter &converter,
184208
auto &block = op.getRegion().back();
185209
firOpBuilder.setInsertionPointToStart(&block);
186210

187-
// Insert the terminator.
211+
if (eval.lowerAsUnstructured())
212+
createEmptyRegionBlocks(firOpBuilder, eval.getNestedEvaluations());
213+
214+
// Ensure the block is well-formed by inserting terminators.
188215
if constexpr (std::is_same_v<Op, omp::WsLoopOp>) {
189216
mlir::ValueRange results;
190217
firOpBuilder.create<mlir::omp::YieldOp>(loc, results);
@@ -369,7 +396,7 @@ createCombinedParallelOp(Fortran::lower::AbstractConverter &converter,
369396
allocateOperands, allocatorOperands, /*reduction_vars=*/ValueRange(),
370397
/*reductions=*/nullptr, procBindKindAttr);
371398

372-
createBodyOfOp<omp::ParallelOp>(parallelOp, converter, currentLocation,
399+
createBodyOfOp<omp::ParallelOp>(parallelOp, converter, currentLocation, eval,
373400
&opClauseList, /*iv=*/{},
374401
/*isCombined=*/true);
375402
}
@@ -461,26 +488,27 @@ genOMP(Fortran::lower::AbstractConverter &converter,
461488
allocateOperands, allocatorOperands, /*reduction_vars=*/ValueRange(),
462489
/*reductions=*/nullptr, procBindKindAttr);
463490
createBodyOfOp<omp::ParallelOp>(parallelOp, converter, currentLocation,
464-
&opClauseList);
491+
eval, &opClauseList);
465492
} else if (blockDirective.v == llvm::omp::OMPD_master) {
466493
auto masterOp =
467494
firOpBuilder.create<mlir::omp::MasterOp>(currentLocation, argTy);
468-
createBodyOfOp<omp::MasterOp>(masterOp, converter, currentLocation);
495+
createBodyOfOp<omp::MasterOp>(masterOp, converter, currentLocation, eval);
469496
} else if (blockDirective.v == llvm::omp::OMPD_single) {
470497
auto singleOp = firOpBuilder.create<mlir::omp::SingleOp>(
471498
currentLocation, allocateOperands, allocatorOperands, nowaitAttr);
472-
createBodyOfOp<omp::SingleOp>(singleOp, converter, currentLocation);
499+
createBodyOfOp<omp::SingleOp>(singleOp, converter, currentLocation, eval);
473500
} else if (blockDirective.v == llvm::omp::OMPD_ordered) {
474501
auto orderedOp = firOpBuilder.create<mlir::omp::OrderedRegionOp>(
475502
currentLocation, /*simd=*/nullptr);
476-
createBodyOfOp<omp::OrderedRegionOp>(orderedOp, converter, currentLocation);
503+
createBodyOfOp<omp::OrderedRegionOp>(orderedOp, converter, currentLocation,
504+
eval);
477505
} else if (blockDirective.v == llvm::omp::OMPD_task) {
478506
auto taskOp = firOpBuilder.create<mlir::omp::TaskOp>(
479507
currentLocation, ifClauseOperand, finalClauseOperand, untiedAttr,
480508
mergeableAttr, /*in_reduction_vars=*/ValueRange(),
481509
/*in_reductions=*/nullptr, priorityClauseOperand, allocateOperands,
482510
allocatorOperands);
483-
createBodyOfOp(taskOp, converter, currentLocation, &opClauseList);
511+
createBodyOfOp(taskOp, converter, currentLocation, eval, &opClauseList);
484512
} else {
485513
TODO(converter.getCurrentLocation(), "Unhandled block directive");
486514
}
@@ -644,7 +672,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
644672
wsLoopOp.nowaitAttr(firOpBuilder.getUnitAttr());
645673
}
646674

647-
createBodyOfOp<omp::WsLoopOp>(wsLoopOp, converter, currentLocation,
675+
createBodyOfOp<omp::WsLoopOp>(wsLoopOp, converter, currentLocation, eval,
648676
&wsLoopOpClauseList, iv);
649677
}
650678

@@ -688,7 +716,7 @@ genOMP(Fortran::lower::AbstractConverter &converter,
688716
firOpBuilder.getContext(), global.sym_name()));
689717
}
690718
}();
691-
createBodyOfOp<omp::CriticalOp>(criticalOp, converter, currentLocation);
719+
createBodyOfOp<omp::CriticalOp>(criticalOp, converter, currentLocation, eval);
692720
}
693721

694722
static void
@@ -700,7 +728,7 @@ genOMP(Fortran::lower::AbstractConverter &converter,
700728
auto currentLocation = converter.getCurrentLocation();
701729
mlir::omp::SectionOp sectionOp =
702730
firOpBuilder.create<mlir::omp::SectionOp>(currentLocation);
703-
createBodyOfOp<omp::SectionOp>(sectionOp, converter, currentLocation);
731+
createBodyOfOp<omp::SectionOp>(sectionOp, converter, currentLocation, eval);
704732
}
705733

706734
// TODO: Add support for reduction
@@ -757,14 +785,15 @@ genOMP(Fortran::lower::AbstractConverter &converter,
757785
currentLocation, /*reduction_vars*/ ValueRange(),
758786
/*reductions=*/nullptr, allocateOperands, allocatorOperands,
759787
/*nowait=*/nullptr);
760-
createBodyOfOp(sectionsOp, converter, currentLocation);
788+
createBodyOfOp(sectionsOp, converter, currentLocation, eval);
761789

762790
// Sections Construct
763791
} else if (dir == llvm::omp::Directive::OMPD_sections) {
764792
auto sectionsOp = firOpBuilder.create<mlir::omp::SectionsOp>(
765793
currentLocation, reductionVars, /*reductions = */ nullptr,
766794
allocateOperands, allocatorOperands, noWaitClauseOperand);
767-
createBodyOfOp<omp::SectionsOp>(sectionsOp, converter, currentLocation);
795+
createBodyOfOp<omp::SectionsOp>(sectionsOp, converter, currentLocation,
796+
eval);
768797
}
769798
}
770799

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
! Test unstructured code adjacent to and inside OpenMP constructs.
2+
3+
! RUN: bbc %s -fopenmp -o "-" | FileCheck %s
4+
5+
! CHECK-LABEL: func @_QPss1{{.*}} {
6+
! CHECK: br ^bb1
7+
! CHECK: ^bb1: // 2 preds: ^bb0, ^bb3
8+
! CHECK: cond_br %{{[0-9]*}}, ^bb2, ^bb4
9+
! CHECK: ^bb2: // pred: ^bb1
10+
! CHECK: cond_br %{{[0-9]*}}, ^bb4, ^bb3
11+
! CHECK: ^bb3: // pred: ^bb2
12+
! CHECK: @_FortranAioBeginExternalListOutput
13+
! CHECK: br ^bb1
14+
! CHECK: ^bb4: // 2 preds: ^bb1, ^bb2
15+
! CHECK: omp.master {
16+
! CHECK: @_FortranAioBeginExternalListOutput
17+
! CHECK: omp.terminator
18+
! CHECK: }
19+
! CHECK: @_FortranAioBeginExternalListOutput
20+
! CHECK: }
21+
subroutine ss1(n) ! unstructured code followed by a structured OpenMP construct
22+
do i = 1, 3
23+
if (i .eq. n) exit
24+
print*, 'ss1-A', i
25+
enddo
26+
!$omp master
27+
print*, 'ss1-B', i
28+
!$omp end master
29+
print*
30+
end
31+
32+
! CHECK-LABEL: func @_QPss2{{.*}} {
33+
! CHECK: omp.master {
34+
! CHECK: @_FortranAioBeginExternalListOutput
35+
! CHECK: br ^bb1
36+
! CHECK: ^bb1: // 2 preds: ^bb0, ^bb3
37+
! CHECK: cond_br %{{[0-9]*}}, ^bb2, ^bb4
38+
! CHECK: ^bb2: // pred: ^bb1
39+
! CHECK: cond_br %{{[0-9]*}}, ^bb4, ^bb3
40+
! CHECK: ^bb3: // pred: ^bb2
41+
! CHECK: @_FortranAioBeginExternalListOutput
42+
! CHECK: br ^bb1
43+
! CHECK: ^bb4: // 2 preds: ^bb1, ^bb2
44+
! CHECK: omp.terminator
45+
! CHECK: }
46+
! CHECK: @_FortranAioBeginExternalListOutput
47+
! CHECK: @_FortranAioBeginExternalListOutput
48+
! CHECK: }
49+
subroutine ss2(n) ! unstructured OpenMP construct; loop exit inside construct
50+
!$omp master
51+
print*, 'ss2-A', n
52+
do i = 1, 3
53+
if (i .eq. n) exit
54+
print*, 'ss2-B', i
55+
enddo
56+
!$omp end master
57+
print*, 'ss2-C', i
58+
print*
59+
end
60+
61+
! CHECK-LABEL: func @_QPss3{{.*}} {
62+
! CHECK: omp.parallel {
63+
! CHECK: br ^bb1
64+
! CHECK: ^bb1: // 2 preds: ^bb0, ^bb2
65+
! CHECK: cond_br %{{[0-9]*}}, ^bb2, ^bb3
66+
! CHECK: ^bb2: // pred: ^bb1
67+
! CHECK: omp.wsloop {{.*}} {
68+
! CHECK: @_FortranAioBeginExternalListOutput
69+
! CHECK: omp.yield
70+
! CHECK: }
71+
! CHECK: omp.wsloop {{.*}} {
72+
! CHECK: br ^bb1
73+
! CHECK: ^bb1: // 2 preds: ^bb0, ^bb3
74+
! CHECK: cond_br %{{[0-9]*}}, ^bb2, ^bb4
75+
! CHECK: ^bb2: // pred: ^bb1
76+
! CHECK: cond_br %{{[0-9]*}}, ^bb4, ^bb3
77+
! CHECK: ^bb3: // pred: ^bb2
78+
! CHECK: @_FortranAioBeginExternalListOutput
79+
! CHECK: br ^bb1
80+
! CHECK: ^bb4: // 2 preds: ^bb1, ^bb2
81+
! CHECK: omp.yield
82+
! CHECK: }
83+
! CHECK: br ^bb1
84+
! CHECK: ^bb3: // pred: ^bb1
85+
! CHECK: omp.terminator
86+
! CHECK: }
87+
! CHECK: }
88+
subroutine ss3(n) ! nested unstructured OpenMP constructs
89+
!$omp parallel
90+
do i = 1, 3
91+
!$omp do
92+
do k = 1, 3
93+
print*, 'ss3-A', k
94+
enddo
95+
!$omp end do
96+
!$omp do
97+
do j = 1, 3
98+
do k = 1, 3
99+
if (k .eq. n) exit
100+
print*, 'ss3-B', k
101+
enddo
102+
enddo
103+
!$omp end do
104+
enddo
105+
!$omp end parallel
106+
end
107+
108+
! CHECK-LABEL: func @_QQmain
109+
program p
110+
call ss1(2)
111+
call ss2(2)
112+
call ss3(2)
113+
end

0 commit comments

Comments
 (0)