Skip to content

Commit 4128cf3

Browse files
[flang][acc] Lower do and do concurrent loops specially in acc regions (#149614)
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 2a3f72e commit 4128cf3

File tree

7 files changed

+774
-121
lines changed

7 files changed

+774
-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
128+
/// construct.
129+
bool isInsideOpenACCComputeConstruct(fir::FirOpBuilder &);
130+
121131
void setInsertionPointAfterOpenACCLoopIfInside(fir::FirOpBuilder &);
122132

123133
void genEarlyReturnInOpenACCLoop(fir::FirOpBuilder &, mlir::Location);
124134

135+
/// Generates an OpenACC loop from a do construct in order to
136+
/// properly capture the loop bounds, parallelism determination mode,
137+
/// and to privatize the loop variables.
138+
/// When the conversion is rejected, nullptr is returned.
139+
mlir::Operation *genOpenACCLoopFromDoConstruct(
140+
AbstractConverter &converter,
141+
Fortran::semantics::SemanticsContext &semanticsContext,
142+
Fortran::lower::SymMap &localSymbols,
143+
const Fortran::parser::DoConstruct &doConstruct, 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
@@ -2167,10 +2167,35 @@ class FirConverter : public Fortran::lower::AbstractConverter {
21672167
/// - structured and unstructured concurrent loops
21682168
void genFIR(const Fortran::parser::DoConstruct &doConstruct) {
21692169
setCurrentPositionAt(doConstruct);
2170-
// Collect loop nest information.
2171-
// Generate begin loop code directly for infinite and while loops.
21722170
Fortran::lower::pft::Evaluation &eval = getEval();
21732171
bool unstructuredContext = eval.lowerAsUnstructured();
2172+
2173+
// Loops with induction variables inside OpenACC compute constructs
2174+
// need special handling to ensure that the IVs are privatized.
2175+
if (Fortran::lower::isInsideOpenACCComputeConstruct(*builder)) {
2176+
mlir::Operation *loopOp = Fortran::lower::genOpenACCLoopFromDoConstruct(
2177+
*this, bridge.getSemanticsContext(), localSymbols, doConstruct, eval);
2178+
bool success = loopOp != nullptr;
2179+
if (success) {
2180+
// Sanity check that the builder insertion point is inside the newly
2181+
// generated loop.
2182+
assert(
2183+
loopOp->getRegion(0).isAncestor(
2184+
builder->getInsertionPoint()->getBlock()->getParent()) &&
2185+
"builder insertion point is not inside the newly generated loop");
2186+
2187+
// Loop body code.
2188+
auto iter = eval.getNestedEvaluations().begin();
2189+
for (auto end = --eval.getNestedEvaluations().end(); iter != end;
2190+
++iter)
2191+
genFIR(*iter, unstructuredContext);
2192+
return;
2193+
}
2194+
// Fall back to normal loop handling.
2195+
}
2196+
2197+
// Collect loop nest information.
2198+
// Generate begin loop code directly for infinite and while loops.
21742199
Fortran::lower::pft::Evaluation &doStmtEval =
21752200
eval.getFirstNestedEvaluation();
21762201
auto *doStmt = doStmtEval.getIf<Fortran::parser::NonLabelDoStmt>();
@@ -3124,7 +3149,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
31243149
Fortran::lower::pft::Evaluation *curEval = &getEval();
31253150

31263151
if (accLoop || accCombined) {
3127-
int64_t loopCount;
3152+
uint64_t loopCount;
31283153
if (accLoop) {
31293154
const Fortran::parser::AccBeginLoopDirective &beginLoopDir =
31303155
std::get<Fortran::parser::AccBeginLoopDirective>(accLoop->t);
@@ -3142,7 +3167,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
31423167

31433168
if (curEval->lowerAsStructured()) {
31443169
curEval = &curEval->getFirstNestedEvaluation();
3145-
for (int64_t i = 1; i < loopCount; i++)
3170+
for (uint64_t i = 1; i < loopCount; i++)
31463171
curEval = &*std::next(curEval->getNestedEvaluations().begin());
31473172
}
31483173
}

0 commit comments

Comments
 (0)