static bool classof(const OMPClause *) { return true; }
};
+/// Class that handles pre-initialization statement for some clauses, like
+/// 'shedule', 'firstprivate' etc.
+class OMPClauseWithPreInit {
+ friend class OMPClauseReader;
+ /// Pre-initialization statement for the clause.
+ Stmt *PreInit;
+protected:
+ /// Set pre-initialization statement for the clause.
+ void setPreInitStmt(Stmt *S) { PreInit = S; }
+ OMPClauseWithPreInit(const OMPClause *This) : PreInit(nullptr) {
+ assert(get(This) && "get is not tuned.");
+ }
+
+public:
+ /// Get pre-initialization statement for the clause.
+ const Stmt *getPreInitStmt() const { return PreInit; }
+ /// Get pre-initialization statement for the clause.
+ Stmt *getPreInitStmt() { return PreInit; }
+ static OMPClauseWithPreInit *get(OMPClause *C);
+ static const OMPClauseWithPreInit *get(const OMPClause *C);
+};
+
/// \brief This represents clauses with the list of variables like 'private',
/// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the
/// '#pragma omp ...' directives.
/// In this example directive '#pragma omp for' has 'schedule' clause with
/// arguments 'static' and '3'.
///
-class OMPScheduleClause : public OMPClause {
+class OMPScheduleClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
/// \brief Location of '('.
SourceLocation LParenLoc;
SourceLocation KindLoc;
/// \brief Location of ',' (if any).
SourceLocation CommaLoc;
- /// \brief Chunk size and a reference to pseudo variable for combined
- /// directives.
- enum { CHUNK_SIZE, HELPER_CHUNK_SIZE, NUM_EXPRS };
- Stmt *ChunkSizes[NUM_EXPRS];
+ /// \brief Chunk size.
+ Expr *ChunkSize;
/// \brief Set schedule kind.
///
///
/// \param E Chunk size.
///
- void setChunkSize(Expr *E) { ChunkSizes[CHUNK_SIZE] = E; }
- /// \brief Set helper chunk size.
- ///
- /// \param E Helper chunk size.
- ///
- void setHelperChunkSize(Expr *E) { ChunkSizes[HELPER_CHUNK_SIZE] = E; }
+ void setChunkSize(Expr *E) { ChunkSize = E; }
public:
/// \brief Build 'schedule' clause with schedule kind \a Kind and chunk size
OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation KLoc, SourceLocation CommaLoc,
SourceLocation EndLoc, OpenMPScheduleClauseKind Kind,
- Expr *ChunkSize, Expr *HelperChunkSize,
+ Expr *ChunkSize, Stmt *HelperChunkSize,
OpenMPScheduleClauseModifier M1, SourceLocation M1Loc,
OpenMPScheduleClauseModifier M2, SourceLocation M2Loc)
- : OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
- Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) {
- ChunkSizes[CHUNK_SIZE] = ChunkSize;
- ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize;
+ : OMPClause(OMPC_schedule, StartLoc, EndLoc), OMPClauseWithPreInit(this),
+ LParenLoc(LParenLoc), Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc),
+ ChunkSize(ChunkSize) {
+ setPreInitStmt(HelperChunkSize);
Modifiers[FIRST] = M1;
Modifiers[SECOND] = M2;
ModifiersLoc[FIRST] = M1Loc;
///
explicit OMPScheduleClause()
: OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()),
- Kind(OMPC_SCHEDULE_unknown) {
- ChunkSizes[CHUNK_SIZE] = nullptr;
- ChunkSizes[HELPER_CHUNK_SIZE] = nullptr;
+ OMPClauseWithPreInit(this), Kind(OMPC_SCHEDULE_unknown),
+ ChunkSize(nullptr) {
Modifiers[FIRST] = OMPC_SCHEDULE_MODIFIER_unknown;
Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown;
}
SourceLocation getCommaLoc() { return CommaLoc; }
/// \brief Get chunk size.
///
- Expr *getChunkSize() { return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]); }
+ Expr *getChunkSize() { return ChunkSize; }
/// \brief Get chunk size.
///
- Expr *getChunkSize() const {
- return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]);
- }
- /// \brief Get helper chunk size.
- ///
- Expr *getHelperChunkSize() {
- return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
- }
- /// \brief Get helper chunk size.
- ///
- Expr *getHelperChunkSize() const {
- return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
- }
+ const Expr *getChunkSize() const { return ChunkSize; }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_schedule;
}
child_range children() {
- return child_range(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1);
+ return child_range(reinterpret_cast<Stmt **>(&ChunkSize),
+ reinterpret_cast<Stmt **>(&ChunkSize) + 1);
}
};
/// In this example directive '#pragma omp distribute' has 'dist_schedule'
/// clause with arguments 'static' and '3'.
///
-class OMPDistScheduleClause : public OMPClause {
+class OMPDistScheduleClause : public OMPClause, public OMPClauseWithPreInit {
friend class OMPClauseReader;
/// \brief Location of '('.
SourceLocation LParenLoc;
SourceLocation KindLoc;
/// \brief Location of ',' (if any).
SourceLocation CommaLoc;
- /// \brief Chunk size and a reference to pseudo variable for combined
- /// directives.
- enum { CHUNK_SIZE, HELPER_CHUNK_SIZE, NUM_EXPRS };
- Stmt *ChunkSizes[NUM_EXPRS];
+ /// \brief Chunk size.
+ Expr *ChunkSize;
/// \brief Set schedule kind.
///
///
/// \param E Chunk size.
///
- void setChunkSize(Expr *E) { ChunkSizes[CHUNK_SIZE] = E; }
- /// \brief Set helper chunk size.
- ///
- /// \param E Helper chunk size.
- ///
- void setHelperChunkSize(Expr *E) { ChunkSizes[HELPER_CHUNK_SIZE] = E; }
+ void setChunkSize(Expr *E) { ChunkSize = E; }
public:
/// \brief Build 'dist_schedule' clause with schedule kind \a Kind and chunk
SourceLocation KLoc, SourceLocation CommaLoc,
SourceLocation EndLoc,
OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize,
- Expr *HelperChunkSize)
- : OMPClause(OMPC_dist_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
- Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) {
- ChunkSizes[CHUNK_SIZE] = ChunkSize;
- ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize;
+ Stmt *HelperChunkSize)
+ : OMPClause(OMPC_dist_schedule, StartLoc, EndLoc),
+ OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Kind(Kind),
+ KindLoc(KLoc), CommaLoc(CommaLoc), ChunkSize(ChunkSize) {
+ setPreInitStmt(HelperChunkSize);
}
/// \brief Build an empty clause.
///
explicit OMPDistScheduleClause()
: OMPClause(OMPC_dist_schedule, SourceLocation(), SourceLocation()),
- Kind(OMPC_DIST_SCHEDULE_unknown) {
- ChunkSizes[CHUNK_SIZE] = nullptr;
- ChunkSizes[HELPER_CHUNK_SIZE] = nullptr;
- }
+ OMPClauseWithPreInit(this), Kind(OMPC_DIST_SCHEDULE_unknown),
+ ChunkSize(nullptr) {}
/// \brief Get kind of the clause.
///
SourceLocation getCommaLoc() { return CommaLoc; }
/// \brief Get chunk size.
///
- Expr *getChunkSize() {
- return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]);
- }
+ Expr *getChunkSize() { return ChunkSize; }
/// \brief Get chunk size.
///
- Expr *getChunkSize() const {
- return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]);
- }
- /// \brief Get helper chunk size.
- ///
- Expr *getHelperChunkSize() {
- return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
- }
- /// \brief Get helper chunk size.
- ///
- Expr *getHelperChunkSize() const {
- return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
- }
+ const Expr *getChunkSize() const { return ChunkSize; }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_dist_schedule;
}
child_range children() {
- return child_range(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1);
+ return child_range(reinterpret_cast<Stmt **>(&ChunkSize),
+ reinterpret_cast<Stmt **>(&ChunkSize) + 1);
}
};
bool
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
TRY_TO(TraverseStmt(C->getChunkSize()));
- TRY_TO(TraverseStmt(C->getHelperChunkSize()));
+ TRY_TO(TraverseStmt(C->getPreInitStmt()));
return true;
}
bool RecursiveASTVisitor<Derived>::VisitOMPDistScheduleClause(
OMPDistScheduleClause *C) {
TRY_TO(TraverseStmt(C->getChunkSize()));
- TRY_TO(TraverseStmt(C->getHelperChunkSize()));
+ TRY_TO(TraverseStmt(C->getPreInitStmt()));
return true;
}
llvm_unreachable("unknown OMPClause");
}
+OMPClauseWithPreInit *OMPClauseWithPreInit::get(OMPClause *C) {
+ auto *Res = OMPClauseWithPreInit::get(const_cast<const OMPClause *>(C));
+ return Res ? const_cast<OMPClauseWithPreInit *>(Res) : nullptr;
+}
+
+const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
+ switch (C->getClauseKind()) {
+ case OMPC_schedule:
+ return static_cast<const OMPScheduleClause *>(C);
+ case OMPC_dist_schedule:
+ return static_cast<const OMPDistScheduleClause *>(C);
+ case OMPC_default:
+ case OMPC_proc_bind:
+ case OMPC_if:
+ case OMPC_final:
+ case OMPC_num_threads:
+ case OMPC_safelen:
+ case OMPC_simdlen:
+ case OMPC_collapse:
+ case OMPC_private:
+ case OMPC_firstprivate:
+ case OMPC_lastprivate:
+ case OMPC_shared:
+ case OMPC_reduction:
+ case OMPC_linear:
+ case OMPC_aligned:
+ case OMPC_copyin:
+ case OMPC_copyprivate:
+ case OMPC_ordered:
+ case OMPC_nowait:
+ case OMPC_untied:
+ case OMPC_mergeable:
+ case OMPC_threadprivate:
+ case OMPC_flush:
+ case OMPC_read:
+ case OMPC_write:
+ case OMPC_update:
+ case OMPC_capture:
+ case OMPC_seq_cst:
+ case OMPC_depend:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_map:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
+ case OMPC_defaultmap:
+ case OMPC_unknown:
+ break;
+ }
+
+ return nullptr;
+}
+
void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
assert(VL.size() == varlist_size() &&
"Number of private copies is not the same as the preallocated buffer");
OS << ": ";
}
OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
- if (Node->getChunkSize()) {
+ if (auto *E = Node->getChunkSize()) {
OS << ", ";
- Node->getChunkSize()->printPretty(OS, nullptr, Policy);
+ if (Node->getPreInitStmt()) {
+ cast<OMPCapturedExprDecl>(
+ cast<DeclRefExpr>(E->IgnoreImpCasts())->getDecl())
+ ->getInit()
+ ->IgnoreImpCasts()
+ ->printPretty(OS, nullptr, Policy);
+ } else
+ E->printPretty(OS, nullptr, Policy);
}
OS << ")";
}
OS << (I == Node->varlist_begin() ? StartSym : ',');
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*I)) {
if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
- CED->getInit()->printPretty(OS, nullptr, Policy, 0);
+ CED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy, 0);
else
DRE->getDecl()->printQualifiedName(OS);
} else
void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) {
OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName(
OMPC_dist_schedule, Node->getDistScheduleKind());
- if (Node->getChunkSize()) {
+ if (auto *E = Node->getChunkSize()) {
OS << ", ";
- Node->getChunkSize()->printPretty(OS, nullptr, Policy);
+ if (Node->getPreInitStmt()) {
+ cast<OMPCapturedExprDecl>(
+ cast<DeclRefExpr>(E->IgnoreImpCasts())->getDecl())
+ ->getInit()
+ ->IgnoreImpCasts()
+ ->printPretty(OS, nullptr, Policy);
+ } else
+ E->printPretty(OS, nullptr, Policy);
}
OS << ")";
}
#define OPENMP_CLAUSE(Name, Class) \
void Visit##Class(const Class *C);
#include "clang/Basic/OpenMPKinds.def"
+ void VistOMPClauseWithPreInit(const OMPClauseWithPreInit *C);
};
+void OMPClauseProfiler::VistOMPClauseWithPreInit(
+ const OMPClauseWithPreInit *C) {
+ if (auto *S = C->getPreInitStmt())
+ Profiler->VisitStmt(S);
+}
+
void OMPClauseProfiler::VisitOMPIfClause(const OMPIfClause *C) {
if (C->getCondition())
Profiler->VisitStmt(C->getCondition());
void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) {
- if (C->getChunkSize()) {
- Profiler->VisitStmt(C->getChunkSize());
- if (C->getHelperChunkSize()) {
- Profiler->VisitStmt(C->getChunkSize());
- }
- }
+ VistOMPClauseWithPreInit(C);
+ if (auto *S = C->getChunkSize())
+ Profiler->VisitStmt(S);
}
void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *C) {
void OMPClauseProfiler::VisitOMPDistScheduleClause(
const OMPDistScheduleClause *C) {
- if (C->getChunkSize()) {
- Profiler->VisitStmt(C->getChunkSize());
- if (C->getHelperChunkSize()) {
- Profiler->VisitStmt(C->getChunkSize());
- }
- }
+ VistOMPClauseWithPreInit(C);
+ if (auto *S = C->getChunkSize())
+ Profiler->VisitStmt(S);
}
void OMPClauseProfiler::VisitOMPDefaultmapClause(const OMPDefaultmapClause *) {}
//
//===----------------------------------------------------------------------===//
+#include "CGCleanup.h"
#include "CGOpenMPRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
using namespace clang;
using namespace CodeGen;
+namespace {
+/// Lexical scope for OpenMP executable constructs, that handles correct codegen
+/// for captured expressions.
+class OMPLexicalScope {
+ CodeGenFunction::LexicalScope Scope;
+ void emitPreInitStmt(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
+ for (const auto *C : S.clauses()) {
+ if (auto *CPI = OMPClauseWithPreInit::get(C)) {
+ if (auto *PreInit = cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
+ for (const auto *I : PreInit->decls())
+ CGF.EmitVarDecl(cast<VarDecl>(*I));
+ }
+ }
+ }
+ }
+
+ class PostUpdateCleanup final : public EHScopeStack::Cleanup {
+ const OMPExecutableDirective &S;
+
+ public:
+ PostUpdateCleanup(const OMPExecutableDirective &S) : S(S) {}
+
+ void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
+ if (!CGF.HaveInsertPoint())
+ return;
+ (void)S;
+ // TODO: add cleanups for clauses that require post update.
+ }
+ };
+
+public:
+ OMPLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
+ : Scope(CGF, S.getSourceRange()) {
+ emitPreInitStmt(CGF, S);
+ CGF.EHStack.pushCleanup<PostUpdateCleanup>(NormalAndEHCleanup, S);
+ }
+};
+} // namespace
+
llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) {
auto &C = getContext();
llvm::Value *Size = nullptr;
}
void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
- LexicalScope Scope(*this, S.getSourceRange());
+ OMPLexicalScope Scope(*this, S);
// Emit parallel region as a standalone region.
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
OMPPrivateScope PrivateScope(CGF);
};
} // namespace
-static std::pair<llvm::Value * /*Chunk*/, ScheduleKindModifiersTy>
-emitScheduleClause(CodeGenFunction &CGF, const OMPLoopDirective &S,
- bool OuterRegion) {
- // Detect the loop schedule kind and chunk.
- auto ScheduleKind = OMPC_SCHEDULE_unknown;
- OpenMPScheduleClauseModifier M1 = OMPC_SCHEDULE_MODIFIER_unknown;
- OpenMPScheduleClauseModifier M2 = OMPC_SCHEDULE_MODIFIER_unknown;
- llvm::Value *Chunk = nullptr;
- if (const auto *C = S.getSingleClause<OMPScheduleClause>()) {
- ScheduleKind = C->getScheduleKind();
- M1 = C->getFirstScheduleModifier();
- M2 = C->getSecondScheduleModifier();
- if (const auto *Ch = C->getChunkSize()) {
- if (auto *ImpRef = cast_or_null<DeclRefExpr>(C->getHelperChunkSize())) {
- if (OuterRegion)
- CGF.EmitVarDecl(*cast<VarDecl>(ImpRef->getDecl()));
- else
- Ch = ImpRef;
- }
- if (!C->getHelperChunkSize() || !OuterRegion) {
- Chunk = CGF.EmitScalarExpr(Ch);
- Chunk = CGF.EmitScalarConversion(Chunk, Ch->getType(),
- S.getIterationVariable()->getType(),
- S.getLocStart());
- }
- }
- }
- return std::make_pair(Chunk, ScheduleKindModifiersTy(ScheduleKind, M1, M2));
-}
-
bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
// Emit the loop iteration variable.
auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
(void)LoopScope.Privatize();
// Detect the loop schedule kind and chunk.
- llvm::Value *Chunk;
- OpenMPScheduleClauseKind ScheduleKind;
- auto ScheduleInfo =
- emitScheduleClause(*this, S, /*OuterRegion=*/false);
- Chunk = ScheduleInfo.first;
- ScheduleKind = ScheduleInfo.second.Kind;
- const OpenMPScheduleClauseModifier M1 = ScheduleInfo.second.M1;
- const OpenMPScheduleClauseModifier M2 = ScheduleInfo.second.M2;
+ llvm::Value *Chunk = nullptr;
+ OpenMPScheduleClauseKind ScheduleKind = OMPC_SCHEDULE_unknown;
+ OpenMPScheduleClauseModifier M1 = OMPC_SCHEDULE_MODIFIER_unknown;
+ OpenMPScheduleClauseModifier M2 = OMPC_SCHEDULE_MODIFIER_unknown;
+ if (auto *C = S.getSingleClause<OMPScheduleClause>()) {
+ ScheduleKind = C->getScheduleKind();
+ M1 = C->getFirstScheduleModifier();
+ M2 = C->getSecondScheduleModifier();
+ if (const auto *Ch = C->getChunkSize()) {
+ Chunk = EmitScalarExpr(Ch);
+ Chunk = EmitScalarConversion(Chunk, Ch->getType(),
+ S.getIterationVariable()->getType(),
+ S.getLocStart());
+ }
+ }
const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
const bool Ordered = S.getSingleClause<OMPOrderedClause>() != nullptr;
}
void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
- LexicalScope Scope(*this, S.getSourceRange());
bool HasLastprivates = false;
- auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) {
- HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
- };
- CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen,
- S.hasCancel());
+ {
+ OMPLexicalScope Scope(*this, S);
+ auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) {
+ HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen,
+ S.hasCancel());
+ }
// Emit an implicit barrier at the end.
if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) {
}
void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
- LexicalScope Scope(*this, S.getSourceRange());
bool HasLastprivates = false;
- auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) {
- HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
- };
- CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
+ {
+ OMPLexicalScope Scope(*this, S);
+ auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) {
+ HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
+ };
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
+ }
// Emit an implicit barrier at the end.
if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) {
return LVal;
}
-OpenMPDirectiveKind
-CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
+void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
auto *CS = dyn_cast<CompoundStmt>(Stmt);
bool HasLastprivates = false;
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
OMPD_unknown);
}
- return OMPD_sections;
}
void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
- LexicalScope Scope(*this, S.getSourceRange());
- OpenMPDirectiveKind EmittedAs = EmitSections(S);
+ {
+ OMPLexicalScope Scope(*this, S);
+ EmitSections(S);
+ }
// Emit an implicit barrier at the end.
if (!S.getSingleClause<OMPNowaitClause>()) {
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), EmittedAs);
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
+ OMPD_sections);
}
}
void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
- LexicalScope Scope(*this, S.getSourceRange());
+ OMPLexicalScope Scope(*this, S);
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
};
AssignmentOps.append(C->assignment_ops().begin(),
C->assignment_ops().end());
}
- LexicalScope Scope(*this, S.getSourceRange());
- // Emit code for 'single' region along with 'copyprivate' clauses
- auto &&CodeGen = [&S](CodeGenFunction &CGF) {
- CodeGenFunction::OMPPrivateScope SingleScope(CGF);
- (void)CGF.EmitOMPFirstprivateClause(S, SingleScope);
- CGF.EmitOMPPrivateClause(S, SingleScope);
- (void)SingleScope.Privatize();
+ bool HasFirstprivates;
+ {
+ OMPLexicalScope Scope(*this, S);
+ // Emit code for 'single' region along with 'copyprivate' clauses
+ auto &&CodeGen = [&S, &HasFirstprivates](CodeGenFunction &CGF) {
+ CodeGenFunction::OMPPrivateScope SingleScope(CGF);
+ HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope);
+ CGF.EmitOMPPrivateClause(S, SingleScope);
+ (void)SingleScope.Privatize();
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- };
- CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
- CopyprivateVars, DestExprs, SrcExprs,
- AssignmentOps);
- // Emit an implicit barrier at the end (to avoid data race if no 'nowait'
- // clause was specified and no 'copyprivate' clause).
- if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ };
+ CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
+ CopyprivateVars, DestExprs,
+ SrcExprs, AssignmentOps);
+ }
+ // Emit an implicit barrier at the end (to avoid data race on firstprivate
+ // init or if no 'nowait' clause was specified and no 'copyprivate' clause).
+ if ((!S.getSingleClause<OMPNowaitClause>() || HasFirstprivates) &&
+ CopyprivateVars.empty()) {
CGM.getOpenMPRuntime().emitBarrierCall(
*this, S.getLocStart(),
S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
}
void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
- LexicalScope Scope(*this, S.getSourceRange());
+ OMPLexicalScope Scope(*this, S);
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
};
}
void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
- LexicalScope Scope(*this, S.getSourceRange());
+ OMPLexicalScope Scope(*this, S);
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
};
const OMPParallelForDirective &S) {
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'for' directive.
- LexicalScope Scope(*this, S.getSourceRange());
- (void)emitScheduleClause(*this, S, /*OuterRegion=*/true);
+ OMPLexicalScope Scope(*this, S);
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitOMPWorksharingLoop(S);
};
const OMPParallelForSimdDirective &S) {
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'for' directive.
- LexicalScope Scope(*this, S.getSourceRange());
- (void)emitScheduleClause(*this, S, /*OuterRegion=*/true);
+ OMPLexicalScope Scope(*this, S);
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitOMPWorksharingLoop(S);
};
const OMPParallelSectionsDirective &S) {
// Emit directive as a combined directive that consists of two implicit
// directives: 'parallel' with 'sections' directive.
- LexicalScope Scope(*this, S.getSourceRange());
+ OMPLexicalScope Scope(*this, S);
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
- (void)CGF.EmitSections(S);
+ CGF.EmitSections(S);
};
emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen);
}
void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
// Emit outlined function for task construct.
- LexicalScope Scope(*this, S.getSourceRange());
+ OMPLexicalScope Scope(*this, S);
auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
auto *I = CS->getCapturedDecl()->param_begin();
void CodeGenFunction::EmitOMPTaskgroupDirective(
const OMPTaskgroupDirective &S) {
- LexicalScope Scope(*this, S.getSourceRange());
+ OMPLexicalScope Scope(*this, S);
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
};
void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
if (!S.getAssociatedStmt())
return;
- LexicalScope Scope(*this, S.getSourceRange());
+ OMPLexicalScope Scope(*this, S);
auto *C = S.getSingleClause<OMPSIMDClause>();
auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF) {
if (C) {
}
}
- LexicalScope Scope(*this, S.getSourceRange());
+ OMPLexicalScope Scope(*this, S);
auto &&CodeGen = [&S, Kind, IsSeqCst, CS](CodeGenFunction &CGF) {
CGF.EmitStopPoint(CS);
EmitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.isPostfixUpdate(), S.getX(),
}
void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) {
- LexicalScope Scope(*this, S.getSourceRange());
+ OMPLexicalScope Scope(*this, S);
const CapturedStmt &CS = *cast<CapturedStmt>(S.getAssociatedStmt());
llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Address UB, Address ST, Address IL,
llvm::Value *Chunk);
/// \brief Emit code for sections directive.
- OpenMPDirectiveKind EmitSections(const OMPExecutableDirective &S);
+ void EmitSections(const OMPExecutableDirective &S);
public:
}
}
-static DeclRefExpr *buildCapture(Sema &S, IdentifierInfo *Id,
- Expr *CaptureExpr) {
+static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
+ Expr *CaptureExpr) {
ASTContext &C = S.getASTContext();
Expr *Init = CaptureExpr->IgnoreImpCasts();
QualType Ty = Init->getType();
S.CurContext->addHiddenDecl(CED);
S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false,
/*TypeMayContainAuto=*/true);
- return buildDeclRefExpr(S, CED, Ty.getNonReferenceType(), SourceLocation());
+ return CED;
+}
+
+static DeclRefExpr *buildCapture(Sema &S, IdentifierInfo *Id,
+ Expr *CaptureExpr) {
+ auto *CD = buildCaptureDecl(S, Id, CaptureExpr);
+ return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
+ SourceLocation());
+}
+
+static DeclRefExpr *buildCapture(Sema &S, StringRef Name, Expr *CaptureExpr) {
+ auto *CD =
+ buildCaptureDecl(S, &S.getASTContext().Idents.get(Name), CaptureExpr);
+ return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
+ SourceLocation());
}
StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
}
}
DSAStack->setForceVarCapturing(/*V=*/false);
- } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective()) &&
- (Clause->getClauseKind() == OMPC_schedule ||
- Clause->getClauseKind() == OMPC_dist_schedule)) {
+ } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) {
// Mark all variables in private list clauses as used in inner region.
// Required for proper codegen of combined directives.
// TODO: add processing for other clauses.
- if (auto *SC = dyn_cast<OMPScheduleClause>(Clause)) {
- if (SC->getHelperChunkSize())
- MarkDeclarationsReferencedInExpr(SC->getHelperChunkSize());
- } else if (auto *DSC = dyn_cast<OMPDistScheduleClause>(Clause)) {
- if (DSC->getHelperChunkSize())
- MarkDeclarationsReferencedInExpr(DSC->getHelperChunkSize());
+ if (auto *C = OMPClauseWithPreInit::get(Clause)) {
+ if (auto *S = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
+ for (auto *D : S->decls())
+ MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D));
+ }
}
}
if (Clause->getClauseKind() == OMPC_schedule)
return nullptr;
}
Expr *ValExpr = ChunkSize;
- Expr *HelperValExpr = nullptr;
+ Stmt *HelperValStmt = nullptr;
if (ChunkSize) {
if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
!ChunkSize->isInstantiationDependent() &&
return nullptr;
}
} else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) {
- HelperValExpr =
- buildCapture(*this, &Context.Idents.get(".chunk."), ValExpr);
+ ValExpr = buildCapture(*this, ".chunk.", ValExpr);
+ Decl *D = cast<DeclRefExpr>(ValExpr)->getDecl();
+ HelperValStmt =
+ new (Context) DeclStmt(DeclGroupRef::Create(Context, &D,
+ /*NumDecls=*/1),
+ SourceLocation(), SourceLocation());
+ ValExpr = DefaultLvalueConversion(ValExpr).get();
}
}
}
return new (Context)
OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
- ValExpr, HelperValExpr, M1, M1Loc, M2, M2Loc);
+ ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
}
OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
return nullptr;
}
Expr *ValExpr = ChunkSize;
- Expr *HelperValExpr = nullptr;
+ Stmt *HelperValStmt = nullptr;
if (ChunkSize) {
if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
!ChunkSize->isInstantiationDependent() &&
return nullptr;
}
} else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) {
- HelperValExpr =
- buildCapture(*this, &Context.Idents.get(".chunk."), ValExpr);
+ ValExpr = buildCapture(*this, ".chunk.", ValExpr);
+ Decl *D = cast<DeclRefExpr>(ValExpr)->getDecl();
+ HelperValStmt =
+ new (Context) DeclStmt(DeclGroupRef::Create(Context, &D,
+ /*NumDecls=*/1),
+ SourceLocation(), SourceLocation());
+ ValExpr = DefaultLvalueConversion(ValExpr).get();
}
}
}
return new (Context)
OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
- Kind, ValExpr, HelperValExpr);
+ Kind, ValExpr, HelperValStmt);
}
OMPClause *Sema::ActOnOpenMPDefaultmapClause(
const ASTReader::RecordData &Record, unsigned &Idx)
: Reader(R), Context(C), Record(Record), Idx(Idx) { }
#define OPENMP_CLAUSE(Name, Class) \
- void Visit##Class(Class *S);
+ void Visit##Class(Class *C);
#include "clang/Basic/OpenMPKinds.def"
OMPClause *readClause();
+ void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C);
};
}
return C;
}
+void OMPClauseReader::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) {
+ C->setPreInitStmt(Reader->Reader.ReadSubStmt());
+}
+
void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) {
C->setNameModifier(static_cast<OpenMPDirectiveKind>(Record[Idx++]));
C->setNameModifierLoc(Reader->ReadSourceLocation(Record, Idx));
}
void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
C->setScheduleKind(
static_cast<OpenMPScheduleClauseKind>(Record[Idx++]));
C->setFirstScheduleModifier(
C->setSecondScheduleModifier(
static_cast<OpenMPScheduleClauseModifier>(Record[Idx++]));
C->setChunkSize(Reader->Reader.ReadSubExpr());
- C->setHelperChunkSize(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
C->setFirstScheduleModifierLoc(Reader->ReadSourceLocation(Record, Idx));
C->setSecondScheduleModifierLoc(Reader->ReadSourceLocation(Record, Idx));
}
void OMPClauseReader::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
C->setDistScheduleKind(
static_cast<OpenMPDistScheduleClauseKind>(Record[Idx++]));
C->setChunkSize(Reader->Reader.ReadSubExpr());
- C->setHelperChunkSize(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
C->setDistScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx));
C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx));
D->setCond(Reader.ReadSubExpr());
D->setInit(Reader.ReadSubExpr());
D->setInc(Reader.ReadSubExpr());
- if (isOpenMPWorksharingDirective(D->getDirectiveKind())) {
+ if (isOpenMPWorksharingDirective(D->getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(D->getDirectiveKind())) {
D->setIsLastIterVariable(Reader.ReadSubExpr());
D->setLowerBoundVariable(Reader.ReadSubExpr());
D->setUpperBoundVariable(Reader.ReadSubExpr());
void Visit##Class(Class *S);
#include "clang/Basic/OpenMPKinds.def"
void writeClause(OMPClause *C);
+ void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C);
};
}
Writer->Writer.AddSourceLocation(C->getLocEnd(), Record);
}
+void OMPClauseWriter::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) {
+ Writer->Writer.AddStmt(C->getPreInitStmt());
+}
+
void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) {
Record.push_back(C->getNameModifier());
Writer->Writer.AddSourceLocation(C->getNameModifierLoc(), Record);
}
void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
Record.push_back(C->getScheduleKind());
Record.push_back(C->getFirstScheduleModifier());
Record.push_back(C->getSecondScheduleModifier());
Writer->Writer.AddStmt(C->getChunkSize());
- Writer->Writer.AddStmt(C->getHelperChunkSize());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
Writer->Writer.AddSourceLocation(C->getFirstScheduleModifierLoc(), Record);
Writer->Writer.AddSourceLocation(C->getSecondScheduleModifierLoc(), Record);
}
void OMPClauseWriter::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
Record.push_back(C->getDistScheduleKind());
Writer->Writer.AddStmt(C->getChunkSize());
- Writer->Writer.AddStmt(C->getHelperChunkSize());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
Writer->Writer.AddSourceLocation(C->getDistScheduleKindLoc(), Record);
Writer->Writer.AddSourceLocation(C->getCommaLoc(), Record);
Writer.AddStmt(D->getCond());
Writer.AddStmt(D->getInit());
Writer.AddStmt(D->getInc());
- if (isOpenMPWorksharingDirective(D->getDirectiveKind())) {
+ if (isOpenMPWorksharingDirective(D->getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(D->getDirectiveKind())) {
Writer.AddStmt(D->getIsLastIterVariable());
Writer.AddStmt(D->getLowerBoundVariable());
Writer.AddStmt(D->getUpperBoundVariable());
// CHECK: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEF_LOC_2]])
// CHECK: call {{.*}}void @__kmpc_push_num_threads([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID]], i32 1)
// CHECK: call {{.*}}void {{.*}} @__kmpc_fork_call(
-// CHECK: call {{.*}} [[S_TY_CONSTR]]([[S_TY]]* [[S_TEMP:%.+]], [[INTPTR_T_TY]] [[INTPTR_T_TY_ATTR]]23)
+// CHECK: invoke {{.*}} [[S_TY_CONSTR]]([[S_TY]]* [[S_TEMP:%.+]], [[INTPTR_T_TY]] [[INTPTR_T_TY_ATTR]]23)
// CHECK: [[S_CHAR_OP:%.+]] = invoke{{.*}} i8 [[S_TY_CHAR_OP]]([[S_TY]]* [[S_TEMP]])
// CHECK: [[RES:%.+]] = sext {{.*}}i8 [[S_CHAR_OP]] to i32
// CHECK: call {{.*}}void @__kmpc_push_num_threads([[IDENT_T_TY]]* [[DEF_LOC_2]], i32 [[GTID]], i32 [[RES]])
-// CHECK: call {{.*}} [[S_TY_DESTR]]([[S_TY]]* [[S_TEMP]])
+// CHECK: {{(invoke|call)}} {{.*}} [[S_TY_DESTR]]([[S_TY]]* [[S_TEMP]])
// CHECK: call {{.*}}void {{.*}} @__kmpc_fork_call(
// CHECK: ret [[INT_TY]] 0
// CHECK: }
#define OPENMP_CLAUSE(Name, Class) \
void Visit##Class(const Class *C);
#include "clang/Basic/OpenMPKinds.def"
+ void VisitOMPClauseWithPreInit(const OMPClauseWithPreInit *C);
};
+void OMPClauseEnqueue::VisitOMPClauseWithPreInit(
+ const OMPClauseWithPreInit *C) {
+ Visitor->AddStmt(C->getPreInitStmt());
+}
+
void OMPClauseEnqueue::VisitOMPIfClause(const OMPIfClause *C) {
Visitor->AddStmt(C->getCondition());
}
void OMPClauseEnqueue::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
void OMPClauseEnqueue::VisitOMPScheduleClause(const OMPScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
Visitor->AddStmt(C->getChunkSize());
- Visitor->AddStmt(C->getHelperChunkSize());
}
void OMPClauseEnqueue::VisitOMPOrderedClause(const OMPOrderedClause *C) {
}
void OMPClauseEnqueue::VisitOMPDistScheduleClause(
const OMPDistScheduleClause *C) {
+ VisitOMPClauseWithPreInit(C);
Visitor->AddStmt(C->getChunkSize());
- Visitor->AddStmt(C->getHelperChunkSize());
-}
-void OMPClauseEnqueue::VisitOMPDefaultmapClause(const OMPDefaultmapClause *C) {
}
+void OMPClauseEnqueue::VisitOMPDefaultmapClause(
+ const OMPDefaultmapClause * /*C*/) {}
}
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {