Skip to content

Commit 78affa2

Browse files
author
Razvan Lupusoru
committed
[flang][acc] Lower do and do concurrent loops specially in acc regions
When OpenACC is enabled and Fortran loops are annotated with `acc loop`, they are lowered to `acc.loop` operation. And rest of the contained loops use the normal FIR lowering path. Hovever, the OpenACC specification has special provisions related to contained loops and their induction variable. In order to adhere to this, we convert all valid contained loops to `acc.loop` in order to store this information appropriately. The provisions in the spec that motivated this change (line numbers are from OpenACC 3.4): - 1353 Loop variables in Fortran do statements within a compute construct are predetermined to be private to the thread that executes the loop. - 3783 When do concurrent appears without a loop construct in a kernels construct it is treated as if it is annotated with loop auto. If it appears in a parallel construct or an accelerator routine then it is treated as if it is annotated with loop independent. By valid loops - we convert do loops and do concurrent loops which have induction variable. Loops which are unstructured are not handled.
1 parent 9878ef3 commit 78affa2

File tree

5 files changed

+716
-121
lines changed

5 files changed

+716
-121
lines changed

flang/include/flang/Lower/OpenACC.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct ProcedureDesignator;
4343

4444
namespace parser {
4545
struct AccClauseList;
46+
struct DoConstruct;
4647
struct OpenACCConstruct;
4748
struct OpenACCDeclarativeConstruct;
4849
struct OpenACCRoutineConstruct;
@@ -58,6 +59,7 @@ namespace lower {
5859

5960
class AbstractConverter;
6061
class StatementContext;
62+
class SymMap;
6163

6264
namespace pft {
6365
struct Evaluation;
@@ -114,14 +116,32 @@ void attachDeclarePostDeallocAction(AbstractConverter &, fir::FirOpBuilder &,
114116
void genOpenACCTerminator(fir::FirOpBuilder &, mlir::Operation *,
115117
mlir::Location);
116118

117-
int64_t getLoopCountForCollapseAndTile(const Fortran::parser::AccClauseList &);
119+
/// Used to obtain the number of contained loops to look for
120+
/// since this is dependent on number of tile operands and collapse
121+
/// clause.
122+
uint64_t getLoopCountForCollapseAndTile(const Fortran::parser::AccClauseList &);
118123

124+
/// Checks whether the current insertion point is inside OpenACC loop.
119125
bool isInOpenACCLoop(fir::FirOpBuilder &);
120126

127+
/// Checks whether the current insertion point is inside OpenACC compute construct.
128+
bool isInsideOpenACCComputeConstruct(fir::FirOpBuilder &);
129+
121130
void setInsertionPointAfterOpenACCLoopIfInside(fir::FirOpBuilder &);
122131

123132
void genEarlyReturnInOpenACCLoop(fir::FirOpBuilder &, mlir::Location);
124133

134+
/// Generates an OpenACC loop from a do construct in order to
135+
/// properly capture the loop bounds, parallelism determination mode,
136+
/// and to privatize the loop variables.
137+
/// When the conversion is rejected, nullptr is returned.
138+
mlir::Operation *genOpenACCLoopFromDoConstruct(
139+
AbstractConverter &converter,
140+
Fortran::semantics::SemanticsContext &semanticsContext,
141+
Fortran::lower::SymMap &localSymbols,
142+
const Fortran::parser::DoConstruct &doConstruct,
143+
pft::Evaluation &eval);
144+
125145
} // namespace lower
126146
} // namespace Fortran
127147

flang/lib/Lower/Bridge.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,10 +2164,35 @@ class FirConverter : public Fortran::lower::AbstractConverter {
21642164
/// - structured and unstructured concurrent loops
21652165
void genFIR(const Fortran::parser::DoConstruct &doConstruct) {
21662166
setCurrentPositionAt(doConstruct);
2167-
// Collect loop nest information.
2168-
// Generate begin loop code directly for infinite and while loops.
21692167
Fortran::lower::pft::Evaluation &eval = getEval();
21702168
bool unstructuredContext = eval.lowerAsUnstructured();
2169+
2170+
// Loops with induction variables inside OpenACC compute constructs
2171+
// need special handling to ensure that the IVs are privatized.
2172+
if (Fortran::lower::isInsideOpenACCComputeConstruct(*builder)) {
2173+
mlir::Operation* loopOp = Fortran::lower::genOpenACCLoopFromDoConstruct(
2174+
*this, bridge.getSemanticsContext(), localSymbols,
2175+
doConstruct, eval);
2176+
bool success = loopOp != nullptr;
2177+
if (success) {
2178+
// Sanity check that the builder insertion point is inside the newly
2179+
// generated loop.
2180+
assert(
2181+
loopOp->getRegion(0).isAncestor(
2182+
builder->getInsertionPoint()->getBlock()->getParent()) &&
2183+
"builder insertion point is not inside the newly generated loop");
2184+
2185+
// Loop body code.
2186+
auto iter = eval.getNestedEvaluations().begin();
2187+
for (auto end = --eval.getNestedEvaluations().end(); iter != end; ++iter)
2188+
genFIR(*iter, unstructuredContext);
2189+
return;
2190+
}
2191+
// Fall back to normal loop handling.
2192+
}
2193+
2194+
// Collect loop nest information.
2195+
// Generate begin loop code directly for infinite and while loops.
21712196
Fortran::lower::pft::Evaluation &doStmtEval =
21722197
eval.getFirstNestedEvaluation();
21732198
auto *doStmt = doStmtEval.getIf<Fortran::parser::NonLabelDoStmt>();
@@ -3121,7 +3146,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
31213146
Fortran::lower::pft::Evaluation *curEval = &getEval();
31223147

31233148
if (accLoop || accCombined) {
3124-
int64_t loopCount;
3149+
uint64_t loopCount;
31253150
if (accLoop) {
31263151
const Fortran::parser::AccBeginLoopDirective &beginLoopDir =
31273152
std::get<Fortran::parser::AccBeginLoopDirective>(accLoop->t);
@@ -3139,7 +3164,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
31393164

31403165
if (curEval->lowerAsStructured()) {
31413166
curEval = &curEval->getFirstNestedEvaluation();
3142-
for (int64_t i = 1; i < loopCount; i++)
3167+
for (uint64_t i = 1; i < loopCount; i++)
31433168
curEval = &*std::next(curEval->getNestedEvaluations().begin());
31443169
}
31453170
}

0 commit comments

Comments
 (0)