Changeset View
Changeset View
Standalone View
Standalone View
clang/lib/AST/StmtOpenMP.cpp
//===--- StmtOpenMP.cpp - Classes for OpenMP directives -------------------===// | //===--- StmtOpenMP.cpp - Classes for OpenMP directives -------------------===// | ||||
Lint: Lint: clang-format not found in user's PATH; not linting file. | |||||
// | // | ||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
// See https://llvm.org/LICENSE.txt for license information. | // See https://llvm.org/LICENSE.txt for license information. | ||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// | // | ||||
Show All 19 Lines | bool OMPExecutableDirective::isStandaloneDirective() const { | ||||
// reasons they have empty synthetic structured block, to simplify codegen. | // reasons they have empty synthetic structured block, to simplify codegen. | ||||
if (isa<OMPTargetEnterDataDirective>(this) || | if (isa<OMPTargetEnterDataDirective>(this) || | ||||
isa<OMPTargetExitDataDirective>(this) || | isa<OMPTargetExitDataDirective>(this) || | ||||
isa<OMPTargetUpdateDirective>(this)) | isa<OMPTargetUpdateDirective>(this)) | ||||
return true; | return true; | ||||
return !hasAssociatedStmt() || !getAssociatedStmt(); | return !hasAssociatedStmt() || !getAssociatedStmt(); | ||||
} | } | ||||
Stmt *OMPExecutableDirective::ignoreCaptures() { | |||||
SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; | |||||
getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind()); | |||||
auto Result = getAssociatedStmt(); | |||||
for (auto ThisCaptureRegion : CaptureRegions) { | |||||
(void)ThisCaptureRegion; | |||||
Result = cast<CapturedStmt>(Result)->getCapturedStmt(); | |||||
} | |||||
return Result; | |||||
} | |||||
const Stmt *OMPExecutableDirective::getStructuredBlock() const { | const Stmt *OMPExecutableDirective::getStructuredBlock() const { | ||||
assert(!isStandaloneDirective() && | assert(!isStandaloneDirective() && | ||||
"Standalone Executable Directives don't have Structured Blocks."); | "Standalone Executable Directives don't have Structured Blocks."); | ||||
if (auto *LD = dyn_cast<OMPLoopDirective>(this)) | if (auto *LD = dyn_cast<OMPLoopDirective>(this)) | ||||
return LD->getBody(); | return LD->getBody(); | ||||
return getInnermostCapturedStmt()->getCapturedStmt(); | return ignoreCaptures(); | ||||
} | } | ||||
Stmt *OMPLoopDirective::tryToFindNextInnerLoop(Stmt *CurStmt, | Stmt *clang::getTopmostAssociatedStructuredBlock( | ||||
bool TryImperfectlyNestedLoops) { | Stmt *S, llvm::SmallVectorImpl<Stmt *> *PreInits) { | ||||
assert(S && "Must be a valid statement"); | |||||
while (true) { | |||||
S = S->IgnoreContainers(/* IgnoreCaptured */ true); | |||||
if (!isa<OMPExecutableDirective>(S) || | |||||
!isOpenMPLoopTransformationDirective( | |||||
cast<OMPExecutableDirective>(S)->getDirectiveKind())) | |||||
break; | |||||
if (auto *D = dyn_cast<OMPTileDirective>(S)) { | |||||
if (PreInits) { | |||||
auto PreInit = D->getPreInits(); | |||||
PreInits->append(PreInit.begin(), PreInit.end()); | |||||
} | |||||
S = D->getTransformedForStmt(); | |||||
continue; | |||||
} | |||||
llvm_unreachable("Unhandled loop transformation"); | |||||
} | |||||
return S; | |||||
} | |||||
Stmt *OMPLoopDirective::tryToFindNextInnerLoop( | |||||
Stmt *CurStmt, bool TryImperfectlyNestedLoops, | |||||
llvm::SmallVectorImpl<Stmt *> *PreInits) { | |||||
Stmt *OrigStmt = CurStmt; | Stmt *OrigStmt = CurStmt; | ||||
CurStmt = CurStmt->IgnoreContainers(); | CurStmt = getTopmostAssociatedStructuredBlock(CurStmt, PreInits); | ||||
// Additional work for imperfectly nested loops, introduced in OpenMP 5.0. | // Additional work for imperfectly nested loops, introduced in OpenMP 5.0. | ||||
if (TryImperfectlyNestedLoops) { | if (TryImperfectlyNestedLoops) { | ||||
if (auto *CS = dyn_cast<CompoundStmt>(CurStmt)) { | if (auto *CS = dyn_cast<CompoundStmt>(CurStmt)) { | ||||
CurStmt = nullptr; | CurStmt = nullptr; | ||||
SmallVector<CompoundStmt *, 4> Statements(1, CS); | SmallVector<CompoundStmt *, 4> Statements(1, CS); | ||||
SmallVector<CompoundStmt *, 4> NextStatements; | SmallVector<CompoundStmt *, 4> NextStatements; | ||||
while (!Statements.empty()) { | while (!Statements.empty()) { | ||||
CS = Statements.pop_back_val(); | CS = Statements.pop_back_val(); | ||||
Show All 24 Lines | if (auto *CS = dyn_cast<CompoundStmt>(CurStmt)) { | ||||
} | } | ||||
if (!CurStmt) | if (!CurStmt) | ||||
CurStmt = OrigStmt; | CurStmt = OrigStmt; | ||||
} | } | ||||
} | } | ||||
return CurStmt; | return CurStmt; | ||||
} | } | ||||
void OMPLoopDirective::collectAssociatedLoops( | |||||
llvm::SmallVectorImpl<Stmt *> &Loops, | |||||
llvm::SmallVectorImpl<Stmt *> &PreInits) { | |||||
Stmt *Body = ignoreCaptures()->IgnoreContainers(); | |||||
unsigned NumLoops = getCollapsedNumber(); | |||||
assert(NumLoops >= 1); | |||||
// For each nest level, find the loop and its body. | |||||
// The topmost loop must not be surrounded by other code. | |||||
for (unsigned Cnt = 0; Cnt < NumLoops; ++Cnt) { | |||||
Stmt *Loop = OMPLoopDirective::tryToFindNextInnerLoop( | |||||
Body, /*TryImperfectlyNestedLoops=*/(Cnt > 0), &PreInits); | |||||
Loops.push_back(Loop); | |||||
// Get body to look next loop in | |||||
if (auto *For = dyn_cast<ForStmt>(Loop)) { | |||||
Body = For->getBody(); | |||||
} else if (auto CXXFor = dyn_cast<CXXForRangeStmt>(Loop)) { | |||||
Body = CXXFor->getBody(); | |||||
} else | |||||
llvm_unreachable("Expected canonical for loop or range-based for loop."); | |||||
} | |||||
} | |||||
Stmt *OMPLoopDirective::getBody() { | Stmt *OMPLoopDirective::getBody() { | ||||
// This relies on the loop form is already checked by Sema. | // This relies on the loop form is already checked by Sema. | ||||
Stmt *Body = | Stmt *Body = getTopmostAssociatedStructuredBlock(ignoreCaptures(), nullptr); | ||||
getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(); | |||||
if (auto *For = dyn_cast<ForStmt>(Body)) { | if (auto *For = dyn_cast<ForStmt>(Body)) { | ||||
Body = For->getBody(); | Body = For->getBody(); | ||||
} else { | } else { | ||||
assert(isa<CXXForRangeStmt>(Body) && | assert(isa<CXXForRangeStmt>(Body) && | ||||
"Expected canonical for loop or range-based for loop."); | "Expected canonical for loop or range-based for loop."); | ||||
Body = cast<CXXForRangeStmt>(Body)->getBody(); | Body = cast<CXXForRangeStmt>(Body)->getBody(); | ||||
} | } | ||||
for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { | for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { | ||||
▲ Show 20 Lines • Show All 176 Lines • ▼ Show 20 Lines | OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C, | ||||
EmptyShell) { | EmptyShell) { | ||||
unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *)); | unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *)); | ||||
void *Mem = | void *Mem = | ||||
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + | C.Allocate(Size + sizeof(OMPClause *) * NumClauses + | ||||
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); | sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for)); | ||||
return new (Mem) OMPForDirective(CollapsedNum, NumClauses); | return new (Mem) OMPForDirective(CollapsedNum, NumClauses); | ||||
} | } | ||||
OMPTileDirective * | |||||
OMPTileDirective::Create(const ASTContext &C, SourceLocation StartLoc, | |||||
SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, | |||||
unsigned NumLoops, Stmt *AssociatedStmt, | |||||
Stmt *TransformedStmt) { | |||||
OMPTileDirective *Dir = CreateEmpty(C, Clauses.size(), NumLoops); | |||||
Dir->setLocStart(StartLoc); | |||||
Dir->setLocEnd(EndLoc); | |||||
Dir->setClauses(Clauses); | |||||
Dir->setAssociatedStmt(AssociatedStmt); | |||||
Dir->setTransformedStmt(TransformedStmt); | |||||
return Dir; | |||||
} | |||||
OMPTileDirective *OMPTileDirective::CreateEmpty(const ASTContext &C, | |||||
unsigned NumClauses, | |||||
unsigned NumLoops) { | |||||
void *Mem = C.Allocate(totalSizeToAlloc<OMPClause *, Stmt *>( | |||||
NumClauses, numLoopChildren(NumLoops, OMPD_tile))); | |||||
return new (Mem) OMPTileDirective({}, {}, NumClauses, NumLoops); | |||||
} | |||||
OMPForSimdDirective * | OMPForSimdDirective * | ||||
OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, | OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, | ||||
SourceLocation EndLoc, unsigned CollapsedNum, | SourceLocation EndLoc, unsigned CollapsedNum, | ||||
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, | ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, | ||||
const HelperExprs &Exprs) { | const HelperExprs &Exprs) { | ||||
unsigned Size = | unsigned Size = | ||||
llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *)); | llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *)); | ||||
void *Mem = | void *Mem = | ||||
▲ Show 20 Lines • Show All 2,012 Lines • Show Last 20 Lines |
clang-format not found in user's PATH; not linting file.