diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/OpenMPClause.cpp | 3 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 41 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 186 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 2 |
6 files changed, 210 insertions, 27 deletions
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index a28b9f3b6d6..52da57f633e 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -48,9 +48,10 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { return static_cast<const OMPReductionClause *>(C); case OMPC_linear: return static_cast<const OMPLinearClause *>(C); + case OMPC_if: + return static_cast<const OMPIfClause *>(C); case OMPC_default: case OMPC_proc_bind: - case OMPC_if: case OMPC_final: case OMPC_num_threads: case OMPC_safelen: diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index bcd2e96875e..2f3653f32d3 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -283,6 +283,7 @@ void OMPClauseProfiler::VistOMPClauseWithPostUpdate( } void OMPClauseProfiler::VisitOMPIfClause(const OMPIfClause *C) { + VistOMPClauseWithPreInit(C); if (C->getCondition()) Profiler->VisitStmt(C->getCondition()); } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index ba531b96ccf..f72eb8e4f1d 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -26,7 +26,7 @@ using namespace CodeGen; namespace { /// Lexical scope for OpenMP executable constructs, that handles correct codegen /// for captured expressions. -class OMPLexicalScope final : public CodeGenFunction::LexicalScope { +class OMPLexicalScope : public CodeGenFunction::LexicalScope { void emitPreInitStmt(CodeGenFunction &CGF, const OMPExecutableDirective &S) { for (const auto *C : S.clauses()) { if (auto *CPI = OMPClauseWithPreInit::get(C)) { @@ -54,10 +54,11 @@ class OMPLexicalScope final : public CodeGenFunction::LexicalScope { public: OMPLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S, - bool AsInlined = false) + bool AsInlined = false, bool EmitPreInitStmt = true) : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()), InlinedShareds(CGF) { - emitPreInitStmt(CGF, S); + if (EmitPreInitStmt) + emitPreInitStmt(CGF, S); if (AsInlined) { if (S.hasAssociatedStmt()) { auto *CS = cast<CapturedStmt>(S.getAssociatedStmt()); @@ -81,6 +82,22 @@ public: } }; +/// Lexical scope for OpenMP parallel construct, that handles correct codegen +/// for captured expressions. +class OMPParallelScope final : public OMPLexicalScope { + bool EmitPreInitStmt(const OMPExecutableDirective &S) { + OpenMPDirectiveKind Kind = S.getDirectiveKind(); + return !isOpenMPTargetExecutionDirective(Kind) && + isOpenMPParallelDirective(Kind); + } + +public: + OMPParallelScope(CodeGenFunction &CGF, const OMPExecutableDirective &S) + : OMPLexicalScope(CGF, S, + /*AsInlined=*/false, + /*EmitPreInitStmt=*/EmitPreInitStmt(S)) {} +}; + /// Private scope for OpenMP loop-based directives, that supports capturing /// of used expression from loop statement. class OMPLoopScope : public CodeGenFunction::RunCleanupsScope { @@ -1237,7 +1254,7 @@ static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, } } - OMPLexicalScope Scope(CGF, S); + OMPParallelScope Scope(CGF, S); llvm::SmallVector<llvm::Value *, 16> CapturedVars; CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars); CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getLocStart(), OutlinedFn, @@ -3409,17 +3426,17 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, CodeGenModule &CGM = CGF.CGM; const CapturedStmt &CS = *cast<CapturedStmt>(S.getAssociatedStmt()); - llvm::SmallVector<llvm::Value *, 16> CapturedVars; - CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); - llvm::Function *Fn = nullptr; llvm::Constant *FnID = nullptr; - // Check if we have any if clause associated with the directive. const Expr *IfCond = nullptr; - - if (auto *C = S.getSingleClause<OMPIfClause>()) { - IfCond = C->getCondition(); + // Check for the at most one if clause associated with the target region. + for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { + if (C->getNameModifier() == OMPD_unknown || + C->getNameModifier() == OMPD_target) { + IfCond = C->getCondition(); + break; + } } // Check if we have any device clause associated with the directive. @@ -3456,6 +3473,8 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID, IsOffloadEntry, CodeGen); OMPLexicalScope Scope(CGF, S); + llvm::SmallVector<llvm::Value *, 16> CapturedVars; + CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device, CapturedVars); } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 5b21f580125..a4622e1dfb3 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1863,6 +1863,7 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, OMPOrderedClause *OC = nullptr; OMPScheduleClause *SC = nullptr; SmallVector<OMPLinearClause *, 4> LCs; + SmallVector<OMPClauseWithPreInit *, 8> PICs; // This is required for proper codegen. for (auto *Clause : Clauses) { if (isOpenMPPrivate(Clause->getClauseKind()) || @@ -1879,15 +1880,8 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, } DSAStack->setForceVarCapturing(/*V=*/false); } 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 *C = OMPClauseWithPreInit::get(Clause)) { - if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) { - for (auto *D : DS->decls()) - MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D)); - } - } + if (auto *C = OMPClauseWithPreInit::get(Clause)) + PICs.push_back(C); if (auto *C = OMPClauseWithPostUpdate::get(Clause)) { if (auto *E = C->getPostUpdateExpr()) MarkDeclarationsReferencedInExpr(E); @@ -1933,10 +1927,31 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, return StmtError(); } StmtResult SR = S; - int ThisCaptureLevel = - getOpenMPCaptureLevels(DSAStack->getCurrentDirective()); - while (--ThisCaptureLevel >= 0) + SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; + getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective()); + for (auto ThisCaptureRegion : llvm::reverse(CaptureRegions)) { + // 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 (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) { + for (auto *C : PICs) { + OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion(); + // Find the particular capture region for the clause if the + // directive is a combined one with multiple capture regions. + // If the directive is not a combined one, the capture region + // associated with the clause is OMPD_unknown and is generated + // only once. + if (CaptureRegion == ThisCaptureRegion || + CaptureRegion == OMPD_unknown) { + if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) { + for (auto *D : DS->decls()) + MarkVariableReferenced(D->getLocation(), cast<VarDecl>(D)); + } + } + } + } SR = ActOnCapturedRegionEnd(SR.get()); + } return SR; } @@ -6611,6 +6626,137 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, return Res; } +// An OpenMP directive such as 'target parallel' has two captured regions: +// for the 'target' and 'parallel' respectively. This function returns +// the region in which to capture expressions associated with a clause. +// A return value of OMPD_unknown signifies that the expression should not +// be captured. +static OpenMPDirectiveKind +getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, + OpenMPClauseKind CKind, + OpenMPDirectiveKind NameModifier) { + OpenMPDirectiveKind CaptureRegion = OMPD_unknown; + + switch (CKind) { + case OMPC_if: + switch (DKind) { + case OMPD_target_parallel: + // If this clause applies to the nested 'parallel' region, capture within + // the 'target' region, otherwise do not capture. + if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel) + CaptureRegion = OMPD_target; + break; + case OMPD_cancel: + case OMPD_parallel: + case OMPD_parallel_sections: + case OMPD_parallel_for: + case OMPD_parallel_for_simd: + case OMPD_target: + case OMPD_target_simd: + case OMPD_target_parallel_for: + case OMPD_target_parallel_for_simd: + case OMPD_target_teams: + case OMPD_target_teams_distribute: + case OMPD_target_teams_distribute_simd: + case OMPD_target_teams_distribute_parallel_for: + case OMPD_target_teams_distribute_parallel_for_simd: + case OMPD_teams_distribute_parallel_for: + case OMPD_teams_distribute_parallel_for_simd: + case OMPD_distribute_parallel_for: + case OMPD_distribute_parallel_for_simd: + case OMPD_task: + case OMPD_taskloop: + case OMPD_taskloop_simd: + case OMPD_target_data: + case OMPD_target_enter_data: + case OMPD_target_exit_data: + case OMPD_target_update: + // Do not capture if-clause expressions. + break; + case OMPD_threadprivate: + case OMPD_taskyield: + case OMPD_barrier: + case OMPD_taskwait: + case OMPD_cancellation_point: + case OMPD_flush: + case OMPD_declare_reduction: + case OMPD_declare_simd: + case OMPD_declare_target: + case OMPD_end_declare_target: + case OMPD_teams: + case OMPD_simd: + case OMPD_for: + case OMPD_for_simd: + case OMPD_sections: + case OMPD_section: + case OMPD_single: + case OMPD_master: + case OMPD_critical: + case OMPD_taskgroup: + case OMPD_distribute: + case OMPD_ordered: + case OMPD_atomic: + case OMPD_distribute_simd: + case OMPD_teams_distribute: + case OMPD_teams_distribute_simd: + llvm_unreachable("Unexpected OpenMP directive with if-clause"); + case OMPD_unknown: + llvm_unreachable("Unknown OpenMP directive"); + } + break; + case OMPC_schedule: + case OMPC_dist_schedule: + case OMPC_firstprivate: + case OMPC_lastprivate: + case OMPC_reduction: + case OMPC_linear: + case OMPC_default: + case OMPC_proc_bind: + case OMPC_final: + case OMPC_num_threads: + case OMPC_safelen: + case OMPC_simdlen: + case OMPC_collapse: + case OMPC_private: + case OMPC_shared: + 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: + case OMPC_uniform: + case OMPC_to: + case OMPC_from: + case OMPC_use_device_ptr: + case OMPC_is_device_ptr: + llvm_unreachable("Unexpected OpenMP clause."); + } + return CaptureRegion; +} + OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -6618,6 +6764,8 @@ OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, SourceLocation ColonLoc, SourceLocation EndLoc) { Expr *ValExpr = Condition; + Stmt *HelperValStmt = nullptr; + OpenMPDirectiveKind CaptureRegion = OMPD_unknown; if (!Condition->isValueDependent() && !Condition->isTypeDependent() && !Condition->isInstantiationDependent() && !Condition->containsUnexpandedParameterPack()) { @@ -6626,10 +6774,20 @@ OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, return nullptr; ValExpr = MakeFullExpr(Val.get()).get(); + + OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); + CaptureRegion = + getOpenMPCaptureRegionForClause(DKind, OMPC_if, NameModifier); + if (CaptureRegion != OMPD_unknown) { + llvm::MapVector<Expr *, DeclRefExpr *> Captures; + ValExpr = tryBuildCapture(*this, ValExpr, Captures).get(); + HelperValStmt = buildPreInits(Context, Captures); + } } - return new (Context) OMPIfClause(NameModifier, ValExpr, StartLoc, LParenLoc, - NameModifierLoc, ColonLoc, EndLoc); + return new (Context) + OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc, + LParenLoc, NameModifierLoc, ColonLoc, EndLoc); } OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition, diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 686a69bbbcd..ab158f7241a 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1928,7 +1928,8 @@ OMPClause *OMPClauseReader::readClause() { } void OMPClauseReader::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) { - C->setPreInitStmt(Reader->Record.readSubStmt()); + C->setPreInitStmt(Reader->Record.readSubStmt(), + static_cast<OpenMPDirectiveKind>(Reader->Record.readInt())); } void OMPClauseReader::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) { @@ -1937,6 +1938,7 @@ void OMPClauseReader::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) { } void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) { + VisitOMPClauseWithPreInit(C); C->setNameModifier(static_cast<OpenMPDirectiveKind>(Reader->Record.readInt())); C->setNameModifierLoc(Reader->ReadSourceLocation()); C->setColonLoc(Reader->ReadSourceLocation()); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 01fd98ceadb..4e8660e028d 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1794,6 +1794,7 @@ void OMPClauseWriter::writeClause(OMPClause *C) { } void OMPClauseWriter::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) { + Record.push_back(C->getCaptureRegion()); Record.AddStmt(C->getPreInitStmt()); } @@ -1803,6 +1804,7 @@ void OMPClauseWriter::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) { } void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) { + VisitOMPClauseWithPreInit(C); Record.push_back(C->getNameModifier()); Record.AddSourceLocation(C->getNameModifierLoc()); Record.AddSourceLocation(C->getColonLoc()); |