diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2019-11-04 09:59:11 -0500 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2019-11-04 16:09:25 -0500 |
commit | 8bbf2e37167d9ac08fa9d3c772d48ca7d9a6f8f6 (patch) | |
tree | b953ffda0932338af7cebd3e04afa6282a88ac19 /clang/lib/AST/StmtOpenMP.cpp | |
parent | adbf64ccc9e18278600ebaeadd8f0117eb8e64b1 (diff) | |
download | bcm5719-llvm-8bbf2e37167d9ac08fa9d3c772d48ca7d9a6f8f6.tar.gz bcm5719-llvm-8bbf2e37167d9ac08fa9d3c772d48ca7d9a6f8f6.zip |
[OPENMP50]Support for imperfectly nested loops.
Added support for imperfectly nested loops introduced in OpenMP 5.0.
Diffstat (limited to 'clang/lib/AST/StmtOpenMP.cpp')
-rw-r--r-- | clang/lib/AST/StmtOpenMP.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp index a93192b4857..12201ef9ec2 100644 --- a/clang/lib/AST/StmtOpenMP.cpp +++ b/clang/lib/AST/StmtOpenMP.cpp @@ -41,6 +41,74 @@ const Stmt *OMPExecutableDirective::getStructuredBlock() const { return getInnermostCapturedStmt()->getCapturedStmt(); } +Stmt *OMPLoopDirective::tryToFindNextInnerLoop(Stmt *CurStmt, + bool TryImperfectlyNestedLoops) { + Stmt *OrigStmt = CurStmt; + CurStmt = CurStmt->IgnoreContainers(); + // Additional work for imperfectly nested loops, introduced in OpenMP 5.0. + if (TryImperfectlyNestedLoops) { + if (auto *CS = dyn_cast<CompoundStmt>(CurStmt)) { + CurStmt = nullptr; + SmallVector<CompoundStmt *, 4> Statements(1, CS); + SmallVector<CompoundStmt *, 4> NextStatements; + while (!Statements.empty()) { + CS = Statements.pop_back_val(); + if (!CS) + continue; + for (Stmt *S : CS->body()) { + if (!S) + continue; + if (isa<ForStmt>(S) || isa<CXXForRangeStmt>(S)) { + // Only single loop construct is allowed. + if (CurStmt) { + CurStmt = OrigStmt; + break; + } + CurStmt = S; + continue; + } + S = S->IgnoreContainers(); + if (auto *InnerCS = dyn_cast_or_null<CompoundStmt>(S)) + NextStatements.push_back(InnerCS); + } + if (Statements.empty()) { + // Found single inner loop or multiple loops - exit. + if (CurStmt) + break; + Statements.swap(NextStatements); + } + } + if (!CurStmt) + CurStmt = OrigStmt; + } + } + return CurStmt; +} + +Stmt *OMPLoopDirective::getBody() { + // This relies on the loop form is already checked by Sema. + Stmt *Body = + getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(); + if (auto *For = dyn_cast<ForStmt>(Body)) { + Body = For->getBody(); + } else { + assert(isa<CXXForRangeStmt>(Body) && + "Expected canonical for loop or range-based for loop."); + Body = cast<CXXForRangeStmt>(Body)->getBody(); + } + for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { + Body = tryToFindNextInnerLoop(Body, /*TryImperfectlyNestedLoops=*/true); + if (auto *For = dyn_cast<ForStmt>(Body)) { + Body = For->getBody(); + } else { + assert(isa<CXXForRangeStmt>(Body) && + "Expected canonical for loop or range-based for loop."); + Body = cast<CXXForRangeStmt>(Body)->getBody(); + } + } + return Body; +} + void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) { assert(A.size() == getCollapsedNumber() && "Number of loop counters is not the same as the collapsed number"); |