diff options
| author | Alexey Bataev <a.bataev@hotmail.com> | 2017-12-29 18:07:07 +0000 |
|---|---|---|
| committer | Alexey Bataev <a.bataev@hotmail.com> | 2017-12-29 18:07:07 +0000 |
| commit | a8a9153a372afcfe2d18399b079bfdc5fd4da626 (patch) | |
| tree | 2ffdc9dbbd1c24dbbf2467c736a2bbb2470c4e52 /clang/lib/CodeGen | |
| parent | 78df5da53dc03851b08b1c10bf613eefb83d21ab (diff) | |
| download | bcm5719-llvm-a8a9153a372afcfe2d18399b079bfdc5fd4da626.tar.gz bcm5719-llvm-a8a9153a372afcfe2d18399b079bfdc5fd4da626.zip | |
[OPENMP] Support for -fopenmp-simd option with compilation of simd loops
only.
Added support for -fopenmp-simd option that allows compilation of
simd-based constructs without emission of OpenMP runtime calls.
llvm-svn: 321560
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGDeclCXX.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 300 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.h | 565 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 127 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 8 |
8 files changed, 1007 insertions, 16 deletions
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 04299783170..8c0e01e5624 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -173,10 +173,12 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, ConstantAddress DeclAddr(DeclPtr, getContext().getDeclAlign(&D)); if (!T->isReferenceType()) { - if (getLangOpts().OpenMP && D.hasAttr<OMPThreadPrivateDeclAttr>()) + if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && + D.hasAttr<OMPThreadPrivateDeclAttr>()) { (void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition( &D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(), PerformInit, this); + } if (PerformInit) EmitDeclInit(*this, D, DeclAddr); if (CGM.isTypeConstant(D.getType(), true)) diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index c7dc8337e19..3f81be00f32 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2263,9 +2263,11 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF, Address Addr(V, Alignment); // Emit reference to the private copy of the variable if it is an OpenMP // threadprivate variable. - if (CGF.getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>()) + if (CGF.getLangOpts().OpenMP && !CGF.getLangOpts().OpenMPSimd && + VD->hasAttr<OMPThreadPrivateDeclAttr>()) { return EmitThreadPrivateVarDeclLValue(CGF, VD, T, Addr, RealVarTy, E->getExprLoc()); + } LValue LV = VD->getType()->isReferenceType() ? CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), AlignmentSource::Decl) : @@ -2446,7 +2448,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // Check for OpenMP threadprivate variables. - if (getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>()) { + if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && + VD->hasAttr<OMPThreadPrivateDeclAttr>()) { return EmitThreadPrivateVarDeclLValue( *this, VD, T, addr, getTypes().ConvertTypeForMem(VD->getType()), E->getExprLoc()); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index fa38ee80bf4..784c90a9eb9 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -397,6 +397,7 @@ class InlinedOpenMPRegionRAII { CodeGenFunction &CGF; llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; FieldDecl *LambdaThisCaptureField = nullptr; + const CodeGen::CGBlockInfo *BlockInfo = nullptr; public: /// \brief Constructs region for combined constructs. @@ -412,6 +413,8 @@ public: std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); LambdaThisCaptureField = CGF.LambdaThisCaptureField; CGF.LambdaThisCaptureField = nullptr; + BlockInfo = CGF.BlockInfo; + CGF.BlockInfo = nullptr; } ~InlinedOpenMPRegionRAII() { @@ -422,6 +425,7 @@ public: CGF.CapturedStmtInfo = OldCSI; std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); CGF.LambdaThisCaptureField = LambdaThisCaptureField; + CGF.BlockInfo = BlockInfo; } }; @@ -8014,3 +8018,299 @@ Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, const VarDecl *TargetParam) const { return CGF.GetAddrOfLocalVar(NativeParam); } + +llvm::Value *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( + const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +llvm::Value *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( + const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +llvm::Value *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( + const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, + const VarDecl *PartIDVar, const VarDecl *TaskTVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, + bool Tied, unsigned &NumberOfParts) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, + SourceLocation Loc, + llvm::Value *OutlinedFn, + ArrayRef<llvm::Value *> CapturedVars, + const Expr *IfCond) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitCriticalRegion( + CodeGenFunction &CGF, StringRef CriticalName, + const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, + const Expr *Hint) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, + const RegionCodeGenTy &MasterOpGen, + SourceLocation Loc) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, + SourceLocation Loc) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitTaskgroupRegion( + CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, + SourceLocation Loc) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitSingleRegion( + CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, + SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, + ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, + ArrayRef<const Expr *> AssignmentOps) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, + const RegionCodeGenTy &OrderedOpGen, + SourceLocation Loc, + bool IsThreads) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, + SourceLocation Loc, + OpenMPDirectiveKind Kind, + bool EmitChecks, + bool ForceSimpleCall) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitForDispatchInit( + CodeGenFunction &CGF, SourceLocation Loc, + const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, + bool Ordered, const DispatchRTInput &DispatchValues) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitForStaticInit( + CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, + const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitDistributeStaticInit( + CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, + SourceLocation Loc, + unsigned IVSize, + bool IVSigned) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, + SourceLocation Loc, + OpenMPDirectiveKind DKind) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, + SourceLocation Loc, + unsigned IVSize, bool IVSigned, + Address IL, Address LB, + Address UB, Address ST) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, + llvm::Value *NumThreads, + SourceLocation Loc) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, + OpenMPProcBindClauseKind ProcBind, + SourceLocation Loc) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, + const VarDecl *VD, + Address VDAddr, + SourceLocation Loc) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( + const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, + CodeGenFunction *CGF) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( + CodeGenFunction &CGF, QualType VarType, StringRef Name) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, + ArrayRef<const Expr *> Vars, + SourceLocation Loc) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, + const OMPExecutableDirective &D, + llvm::Value *TaskFunction, + QualType SharedsTy, Address Shareds, + const Expr *IfCond, + const OMPTaskDataTy &Data) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitTaskLoopCall( + CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, + llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds, + const Expr *IfCond, const OMPTaskDataTy &Data) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitReduction( + CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, + ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, + ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { + assert(Options.SimpleReduction && "Only simple reduction is expected."); + CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, + ReductionOps, Options); +} + +llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( + CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, + ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, + SourceLocation Loc, + ReductionCodeGen &RCG, + unsigned N) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, + SourceLocation Loc, + llvm::Value *ReductionsPtr, + LValue SharedLVal) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, + SourceLocation Loc) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitCancellationPointCall( + CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind CancelRegion) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, + SourceLocation Loc, const Expr *IfCond, + OpenMPDirectiveKind CancelRegion) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( + const OMPExecutableDirective &D, StringRef ParentName, + llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, + bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF, + const OMPExecutableDirective &D, + llvm::Value *OutlinedFn, + llvm::Value *OutlinedFnID, + const Expr *IfCond, const Expr *Device, + ArrayRef<llvm::Value *> CapturedVars) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { + return false; +} + +llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() { + return nullptr; +} + +void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, + const OMPExecutableDirective &D, + SourceLocation Loc, + llvm::Value *OutlinedFn, + ArrayRef<llvm::Value *> CapturedVars) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, + const Expr *NumTeams, + const Expr *ThreadLimit, + SourceLocation Loc) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitTargetDataCalls( + CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, + const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( + CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, + const Expr *Device) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, + const OMPLoopDirective &D) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, + const OMPDependClause *C) { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +const VarDecl * +CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, + const VarDecl *NativeParam) const { + llvm_unreachable("Not supported in SIMD-only mode"); +} + +Address +CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, + const VarDecl *NativeParam, + const VarDecl *TargetParam) const { + llvm_unreachable("Not supported in SIMD-only mode"); +} + diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index 94a14384137..98e09e09b5e 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -1364,6 +1364,571 @@ public: ArrayRef<llvm::Value *> Args = llvm::None) const; }; +/// Class supports emissionof SIMD-only code. +class CGOpenMPSIMDRuntime final : public CGOpenMPRuntime { +public: + explicit CGOpenMPSIMDRuntime(CodeGenModule &CGM) : CGOpenMPRuntime(CGM) {} + ~CGOpenMPSIMDRuntime() override {} + + /// \brief Emits outlined function for the specified OpenMP parallel directive + /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, + /// kmp_int32 BoundID, struct context_vars*). + /// \param D OpenMP directive. + /// \param ThreadIDVar Variable for thread id in the current OpenMP region. + /// \param InnermostKind Kind of innermost directive (for simple directives it + /// is a directive itself, for combined - its innermost directive). + /// \param CodeGen Code generation sequence for the \a D directive. + llvm::Value * + emitParallelOutlinedFunction(const OMPExecutableDirective &D, + const VarDecl *ThreadIDVar, + OpenMPDirectiveKind InnermostKind, + const RegionCodeGenTy &CodeGen) override; + + /// \brief Emits outlined function for the specified OpenMP teams directive + /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID, + /// kmp_int32 BoundID, struct context_vars*). + /// \param D OpenMP directive. + /// \param ThreadIDVar Variable for thread id in the current OpenMP region. + /// \param InnermostKind Kind of innermost directive (for simple directives it + /// is a directive itself, for combined - its innermost directive). + /// \param CodeGen Code generation sequence for the \a D directive. + llvm::Value * + emitTeamsOutlinedFunction(const OMPExecutableDirective &D, + const VarDecl *ThreadIDVar, + OpenMPDirectiveKind InnermostKind, + const RegionCodeGenTy &CodeGen) override; + + /// \brief Emits outlined function for the OpenMP task directive \a D. This + /// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t* + /// TaskT). + /// \param D OpenMP directive. + /// \param ThreadIDVar Variable for thread id in the current OpenMP region. + /// \param PartIDVar Variable for partition id in the current OpenMP untied + /// task region. + /// \param TaskTVar Variable for task_t argument. + /// \param InnermostKind Kind of innermost directive (for simple directives it + /// is a directive itself, for combined - its innermost directive). + /// \param CodeGen Code generation sequence for the \a D directive. + /// \param Tied true if task is generated for tied task, false otherwise. + /// \param NumberOfParts Number of parts in untied task. Ignored for tied + /// tasks. + /// + llvm::Value *emitTaskOutlinedFunction( + const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, + const VarDecl *PartIDVar, const VarDecl *TaskTVar, + OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, + bool Tied, unsigned &NumberOfParts) override; + + /// \brief Emits code for parallel or serial call of the \a OutlinedFn with + /// variables captured in a record which address is stored in \a + /// CapturedStruct. + /// \param OutlinedFn Outlined function to be run in parallel threads. Type of + /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). + /// \param CapturedVars A pointer to the record with the references to + /// variables used in \a OutlinedFn function. + /// \param IfCond Condition in the associated 'if' clause, if it was + /// specified, nullptr otherwise. + /// + void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, + llvm::Value *OutlinedFn, + ArrayRef<llvm::Value *> CapturedVars, + const Expr *IfCond) override; + + /// \brief Emits a critical region. + /// \param CriticalName Name of the critical region. + /// \param CriticalOpGen Generator for the statement associated with the given + /// critical region. + /// \param Hint Value of the 'hint' clause (optional). + void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, + const RegionCodeGenTy &CriticalOpGen, + SourceLocation Loc, + const Expr *Hint = nullptr) override; + + /// \brief Emits a master region. + /// \param MasterOpGen Generator for the statement associated with the given + /// master region. + void emitMasterRegion(CodeGenFunction &CGF, + const RegionCodeGenTy &MasterOpGen, + SourceLocation Loc) override; + + /// \brief Emits code for a taskyield directive. + void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override; + + /// \brief Emit a taskgroup region. + /// \param TaskgroupOpGen Generator for the statement associated with the + /// given taskgroup region. + void emitTaskgroupRegion(CodeGenFunction &CGF, + const RegionCodeGenTy &TaskgroupOpGen, + SourceLocation Loc) override; + + /// \brief Emits a single region. + /// \param SingleOpGen Generator for the statement associated with the given + /// single region. + void emitSingleRegion(CodeGenFunction &CGF, + const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, + ArrayRef<const Expr *> CopyprivateVars, + ArrayRef<const Expr *> DestExprs, + ArrayRef<const Expr *> SrcExprs, + ArrayRef<const Expr *> AssignmentOps) override; + + /// \brief Emit an ordered region. + /// \param OrderedOpGen Generator for the statement associated with the given + /// ordered region. + void emitOrderedRegion(CodeGenFunction &CGF, + const RegionCodeGenTy &OrderedOpGen, + SourceLocation Loc, bool IsThreads) override; + + /// \brief Emit an implicit/explicit barrier for OpenMP threads. + /// \param Kind Directive for which this implicit barrier call must be + /// generated. Must be OMPD_barrier for explicit barrier generation. + /// \param EmitChecks true if need to emit checks for cancellation barriers. + /// \param ForceSimpleCall true simple barrier call must be emitted, false if + /// runtime class decides which one to emit (simple or with cancellation + /// checks). + /// + void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind Kind, bool EmitChecks = true, + bool ForceSimpleCall = false) override; + + /// This is used for non static scheduled types and when the ordered + /// clause is present on the loop construct. + /// Depending on the loop schedule, it is necessary to call some runtime + /// routine before start of the OpenMP loop to get the loop upper / lower + /// bounds \a LB and \a UB and stride \a ST. + /// + /// \param CGF Reference to current CodeGenFunction. + /// \param Loc Clang source location. + /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. + /// \param IVSize Size of the iteration variable in bits. + /// \param IVSigned Sign of the iteration variable. + /// \param Ordered true if loop is ordered, false otherwise. + /// \param DispatchValues struct containing llvm values for lower bound, upper + /// bound, and chunk expression. + /// For the default (nullptr) value, the chunk 1 will be used. + /// + void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, + const OpenMPScheduleTy &ScheduleKind, + unsigned IVSize, bool IVSigned, bool Ordered, + const DispatchRTInput &DispatchValues) override; + + /// \brief Call the appropriate runtime routine to initialize it before start + /// of loop. + /// + /// This is used only in case of static schedule, when the user did not + /// specify a ordered clause on the loop construct. + /// Depending on the loop schedule, it is necessary to call some runtime + /// routine before start of the OpenMP loop to get the loop upper / lower + /// bounds LB and UB and stride ST. + /// + /// \param CGF Reference to current CodeGenFunction. + /// \param Loc Clang source location. + /// \param DKind Kind of the directive. + /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause. + /// \param Values Input arguments for the construct. + /// + void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind DKind, + const OpenMPScheduleTy &ScheduleKind, + const StaticRTInput &Values) override; + + /// + /// \param CGF Reference to current CodeGenFunction. + /// \param Loc Clang source location. + /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause. + /// \param Values Input arguments for the construct. + /// + void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDistScheduleClauseKind SchedKind, + const StaticRTInput &Values) override; + + /// \brief Call the appropriate runtime routine to notify that we finished + /// iteration of the ordered loop with the dynamic scheduling. + /// + /// \param CGF Reference to current CodeGenFunction. + /// \param Loc Clang source location. + /// \param IVSize Size of the iteration variable in bits. + /// \param IVSigned Sign of the iteration variable. + /// + void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, + unsigned IVSize, bool IVSigned) override; + + /// \brief Call the appropriate runtime routine to notify that we finished + /// all the work with current loop. + /// + /// \param CGF Reference to current CodeGenFunction. + /// \param Loc Clang source location. + /// \param DKind Kind of the directive for which the static finish is emitted. + /// + void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind DKind) override; + + /// Call __kmpc_dispatch_next( + /// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, + /// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, + /// kmp_int[32|64] *p_stride); + /// \param IVSize Size of the iteration variable in bits. + /// \param IVSigned Sign of the iteration variable. + /// \param IL Address of the output variable in which the flag of the + /// last iteration is returned. + /// \param LB Address of the output variable in which the lower iteration + /// number is returned. + /// \param UB Address of the output variable in which the upper iteration + /// number is returned. + /// \param ST Address of the output variable in which the stride value is + /// returned. + llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc, + unsigned IVSize, bool IVSigned, Address IL, + Address LB, Address UB, Address ST) override; + + /// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 + /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads' + /// clause. + /// \param NumThreads An integer value of threads. + void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, + SourceLocation Loc) override; + + /// \brief Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 + /// global_tid, int proc_bind) to generate code for 'proc_bind' clause. + void emitProcBindClause(CodeGenFunction &CGF, + OpenMPProcBindClauseKind ProcBind, + SourceLocation Loc) override; + + /// \brief Returns address of the threadprivate variable for the current + /// thread. + /// \param VD Threadprivate variable. + /// \param VDAddr Address of the global variable \a VD. + /// \param Loc Location of the reference to threadprivate var. + /// \return Address of the threadprivate variable for the current thread. + Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, + Address VDAddr, SourceLocation Loc) override; + + /// \brief Emit a code for initialization of threadprivate variable. It emits + /// a call to runtime library which adds initial value to the newly created + /// threadprivate variable (if it is not constant) and registers destructor + /// for the variable (if any). + /// \param VD Threadprivate variable. + /// \param VDAddr Address of the global variable \a VD. + /// \param Loc Location of threadprivate declaration. + /// \param PerformInit true if initialization expression is not constant. + llvm::Function * + emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, + SourceLocation Loc, bool PerformInit, + CodeGenFunction *CGF = nullptr) override; + + /// Creates artificial threadprivate variable with name \p Name and type \p + /// VarType. + /// \param VarType Type of the artificial threadprivate variable. + /// \param Name Name of the artificial threadprivate variable. + Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, + QualType VarType, + StringRef Name) override; + + /// \brief Emit flush of the variables specified in 'omp flush' directive. + /// \param Vars List of variables to flush. + void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars, + SourceLocation Loc) override; + + /// \brief Emit task region for the task directive. The task region is + /// emitted in several steps: + /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 + /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, + /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the + /// function: + /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { + /// TaskFunction(gtid, tt->part_id, tt->shareds); + /// return 0; + /// } + /// 2. Copy a list of shared variables to field shareds of the resulting + /// structure kmp_task_t returned by the previous call (if any). + /// 3. Copy a pointer to destructions function to field destructions of the + /// resulting structure kmp_task_t. + /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, + /// kmp_task_t *new_task), where new_task is a resulting structure from + /// previous items. + /// \param D Current task directive. + /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 + /// /*part_id*/, captured_struct */*__context*/); + /// \param SharedsTy A type which contains references the shared variables. + /// \param Shareds Context with the list of shared variables from the \p + /// TaskFunction. + /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr + /// otherwise. + /// \param Data Additional data for task generation like tiednsee, final + /// state, list of privates etc. + void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, + const OMPExecutableDirective &D, llvm::Value *TaskFunction, + QualType SharedsTy, Address Shareds, const Expr *IfCond, + const OMPTaskDataTy &Data) override; + + /// Emit task region for the taskloop directive. The taskloop region is + /// emitted in several steps: + /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 + /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, + /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the + /// function: + /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { + /// TaskFunction(gtid, tt->part_id, tt->shareds); + /// return 0; + /// } + /// 2. Copy a list of shared variables to field shareds of the resulting + /// structure kmp_task_t returned by the previous call (if any). + /// 3. Copy a pointer to destructions function to field destructions of the + /// resulting structure kmp_task_t. + /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t + /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int + /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task + /// is a resulting structure from + /// previous items. + /// \param D Current task directive. + /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 + /// /*part_id*/, captured_struct */*__context*/); + /// \param SharedsTy A type which contains references the shared variables. + /// \param Shareds Context with the list of shared variables from the \p + /// TaskFunction. + /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr + /// otherwise. + /// \param Data Additional data for task generation like tiednsee, final + /// state, list of privates etc. + void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, + const OMPLoopDirective &D, llvm::Value *TaskFunction, + QualType SharedsTy, Address Shareds, const Expr *IfCond, + const OMPTaskDataTy &Data) override; + + /// \brief Emit a code for reduction clause. Next code should be emitted for + /// reduction: + /// \code + /// + /// static kmp_critical_name lock = { 0 }; + /// + /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) { + /// ... + /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); + /// ... + /// } + /// + /// ... + /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; + /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), + /// RedList, reduce_func, &<lock>)) { + /// case 1: + /// ... + /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); + /// ... + /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); + /// break; + /// case 2: + /// ... + /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); + /// ... + /// break; + /// default:; + /// } + /// \endcode + /// + /// \param Privates List of private copies for original reduction arguments. + /// \param LHSExprs List of LHS in \a ReductionOps reduction operations. + /// \param RHSExprs List of RHS in \a ReductionOps reduction operations. + /// \param ReductionOps List of reduction operations in form 'LHS binop RHS' + /// or 'operator binop(LHS, RHS)'. + /// \param Options List of options for reduction codegen: + /// WithNowait true if parent directive has also nowait clause, false + /// otherwise. + /// SimpleReduction Emit reduction operation only. Used for omp simd + /// directive on the host. + /// ReductionKind The kind of reduction to perform. + void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, + ArrayRef<const Expr *> Privates, + ArrayRef<const Expr *> LHSExprs, + ArrayRef<const Expr *> RHSExprs, + ArrayRef<const Expr *> ReductionOps, + ReductionOptionsTy Options) override; + + /// Emit a code for initialization of task reduction clause. Next code + /// should be emitted for reduction: + /// \code + /// + /// _task_red_item_t red_data[n]; + /// ... + /// red_data[i].shar = &origs[i]; + /// red_data[i].size = sizeof(origs[i]); + /// red_data[i].f_init = (void*)RedInit<i>; + /// red_data[i].f_fini = (void*)RedDest<i>; + /// red_data[i].f_comb = (void*)RedOp<i>; + /// red_data[i].flags = <Flag_i>; + /// ... + /// void* tg1 = __kmpc_task_reduction_init(gtid, n, red_data); + /// \endcode + /// + /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations. + /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations. + /// \param Data Additional data for task generation like tiedness, final + /// state, list of privates, reductions etc. + llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, + ArrayRef<const Expr *> LHSExprs, + ArrayRef<const Expr *> RHSExprs, + const OMPTaskDataTy &Data) override; + + /// Required to resolve existing problems in the runtime. Emits threadprivate + /// variables to store the size of the VLAs/array sections for + /// initializer/combiner/finalizer functions + emits threadprivate variable to + /// store the pointer to the original reduction item for the custom + /// initializer defined by declare reduction construct. + /// \param RCG Allows to reuse an existing data for the reductions. + /// \param N Reduction item for which fixups must be emitted. + void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, + ReductionCodeGen &RCG, unsigned N) override; + + /// Get the address of `void *` type of the privatue copy of the reduction + /// item specified by the \p SharedLVal. + /// \param ReductionsPtr Pointer to the reduction data returned by the + /// emitTaskReductionInit function. + /// \param SharedLVal Address of the original reduction item. + Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, + llvm::Value *ReductionsPtr, + LValue SharedLVal) override; + + /// \brief Emit code for 'taskwait' directive. + void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc) override; + + /// \brief Emit code for 'cancellation point' construct. + /// \param CancelRegion Region kind for which the cancellation point must be + /// emitted. + /// + void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, + OpenMPDirectiveKind CancelRegion) override; + + /// \brief Emit code for 'cancel' construct. + /// \param IfCond Condition in the associated 'if' clause, if it was + /// specified, nullptr otherwise. + /// \param CancelRegion Region kind for which the cancel must be emitted. + /// + void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, + const Expr *IfCond, + OpenMPDirectiveKind CancelRegion) override; + + /// \brief Emit outilined function for 'target' directive. + /// \param D Directive to emit. + /// \param ParentName Name of the function that encloses the target region. + /// \param OutlinedFn Outlined function value to be defined by this call. + /// \param OutlinedFnID Outlined function ID value to be defined by this call. + /// \param IsOffloadEntry True if the outlined function is an offload entry. + /// \param CodeGen Code generation sequence for the \a D directive. + /// An outlined function may not be an entry if, e.g. the if clause always + /// evaluates to false. + void emitTargetOutlinedFunction(const OMPExecutableDirective &D, + StringRef ParentName, + llvm::Function *&OutlinedFn, + llvm::Constant *&OutlinedFnID, + bool IsOffloadEntry, + const RegionCodeGenTy &CodeGen) override; + + /// \brief Emit the target offloading code associated with \a D. The emitted + /// code attempts offloading the execution to the device, an the event of + /// a failure it executes the host version outlined in \a OutlinedFn. + /// \param D Directive to emit. + /// \param OutlinedFn Host version of the code to be offloaded. + /// \param OutlinedFnID ID of host version of the code to be offloaded. + /// \param IfCond Expression evaluated in if clause associated with the target + /// directive, or null if no if clause is used. + /// \param Device Expression evaluated in device clause associated with the + /// target directive, or null if no device clause is used. + /// \param CapturedVars Values captured in the current region. + void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, + llvm::Value *OutlinedFn, llvm::Value *OutlinedFnID, + const Expr *IfCond, const Expr *Device, + ArrayRef<llvm::Value *> CapturedVars) override; + + /// \brief Emit the target regions enclosed in \a GD function definition or + /// the function itself in case it is a valid device function. Returns true if + /// \a GD was dealt with successfully. + /// \param GD Function to scan. + bool emitTargetFunctions(GlobalDecl GD) override; + + /// \brief Emit the global variable if it is a valid device global variable. + /// Returns true if \a GD was dealt with successfully. + /// \param GD Variable declaration to emit. + bool emitTargetGlobalVariable(GlobalDecl GD) override; + + /// \brief Emit the global \a GD if it is meaningful for the target. Returns + /// if it was emitted successfully. + /// \param GD Global to scan. + bool emitTargetGlobal(GlobalDecl GD) override; + + /// \brief Creates the offloading descriptor in the event any target region + /// was emitted in the current module and return the function that registers + /// it. + llvm::Function *emitRegistrationFunction() override; + + /// \brief Emits code for teams call of the \a OutlinedFn with + /// variables captured in a record which address is stored in \a + /// CapturedStruct. + /// \param OutlinedFn Outlined function to be run by team masters. Type of + /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*). + /// \param CapturedVars A pointer to the record with the references to + /// variables used in \a OutlinedFn function. + /// + void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, + SourceLocation Loc, llvm::Value *OutlinedFn, + ArrayRef<llvm::Value *> CapturedVars) override; + + /// \brief Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 + /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code + /// for num_teams clause. + /// \param NumTeams An integer expression of teams. + /// \param ThreadLimit An integer expression of threads. + void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, + const Expr *ThreadLimit, SourceLocation Loc) override; + + /// \brief Emit the target data mapping code associated with \a D. + /// \param D Directive to emit. + /// \param IfCond Expression evaluated in if clause associated with the + /// target directive, or null if no device clause is used. + /// \param Device Expression evaluated in device clause associated with the + /// target directive, or null if no device clause is used. + /// \param Info A record used to store information that needs to be preserved + /// until the region is closed. + void emitTargetDataCalls(CodeGenFunction &CGF, + const OMPExecutableDirective &D, const Expr *IfCond, + const Expr *Device, const RegionCodeGenTy &CodeGen, + TargetDataInfo &Info) override; + + /// \brief Emit the data mapping/movement code associated with the directive + /// \a D that should be of the form 'target [{enter|exit} data | update]'. + /// \param D Directive to emit. + /// \param IfCond Expression evaluated in if clause associated with the target + /// directive, or null if no if clause is used. + /// \param Device Expression evaluated in device clause associated with the + /// target directive, or null if no device clause is used. + void emitTargetDataStandAloneCall(CodeGenFunction &CGF, + const OMPExecutableDirective &D, + const Expr *IfCond, + const Expr *Device) override; + + /// Emit initialization for doacross loop nesting support. + /// \param D Loop-based construct used in doacross nesting construct. + void emitDoacrossInit(CodeGenFunction &CGF, + const OMPLoopDirective &D) override; + + /// Emit code for doacross ordered directive with 'depend' clause. + /// \param C 'depend' clause with 'sink|source' dependency kind. + void emitDoacrossOrdered(CodeGenFunction &CGF, + const OMPDependClause *C) override; + + /// Translates the native parameter of outlined function if this is required + /// for target. + /// \param FD Field decl from captured record for the paramater. + /// \param NativeParam Parameter itself. + const VarDecl *translateParameter(const FieldDecl *FD, + const VarDecl *NativeParam) const override; + + /// Gets the address of the native argument basing on the address of the + /// target-specific parameter. + /// \param NativeParam Parameter itself. + /// \param TargetParam Corresponding target-specific parameter. + Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, + const VarDecl *TargetParam) const override; +}; + } // namespace CodeGen } // namespace clang diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 91fa49a46ef..97e35e2b6e8 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -74,6 +74,15 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) { // Generate a stoppoint if we are emitting debug info. EmitStopPoint(S); + // Ignore all OpenMP directives except for simd if OpenMP with Simd is + // enabled. + if (getLangOpts().OpenMP && getLangOpts().OpenMPSimd) { + if (const auto *D = dyn_cast<OMPExecutableDirective>(S)) { + EmitSimpleOMPExecutableDirective(*D); + return; + } + } + switch (S->getStmtClass()) { case Stmt::NoStmtClass: case Stmt::CXXCatchStmtClass: diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index f9861735832..26817ac330b 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -144,6 +144,71 @@ public: } }; +class OMPSimdLexicalScope : public CodeGenFunction::LexicalScope { + CodeGenFunction::OMPPrivateScope InlinedShareds; + + static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) { + return CGF.LambdaCaptureFields.lookup(VD) || + (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) || + (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) && + cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD)); + } + +public: + OMPSimdLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S) + : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()), + InlinedShareds(CGF) { + 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()) { + if (!I->hasAttr<OMPCaptureNoInitAttr>()) + CGF.EmitVarDecl(cast<VarDecl>(*I)); + else { + CodeGenFunction::AutoVarEmission Emission = + CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); + CGF.EmitAutoVarCleanups(Emission); + } + } + } + } else if (const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(C)) { + for (const Expr *E : UDP->varlists()) { + const Decl *D = cast<DeclRefExpr>(E)->getDecl(); + if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D)) + CGF.EmitVarDecl(*OED); + } + } + } + if (!isOpenMPSimdDirective(S.getDirectiveKind())) + CGF.EmitOMPPrivateClause(S, InlinedShareds); + if (const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) { + if (const Expr *E = TG->getReductionRef()) + CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl())); + } + const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt()); + while (CS) { + for (auto &C : CS->captures()) { + if (C.capturesVariable() || C.capturesVariableByCopy()) { + auto *VD = C.getCapturedVar(); + assert(VD == VD->getCanonicalDecl() && + "Canonical decl must be captured."); + DeclRefExpr DRE(const_cast<VarDecl *>(VD), + isCapturedVar(CGF, VD) || + (CGF.CapturedStmtInfo && + InlinedShareds.isGlobalVarCaptured(VD)), + VD->getType().getNonReferenceType(), VK_LValue, + SourceLocation()); + InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address { + return CGF.EmitLValue(&DRE).getAddress(); + }); + } + } + CS = dyn_cast<CapturedStmt>(CS->getCapturedStmt()); + } + (void)InlinedShareds.Privatize(); + } +}; + } // namespace static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, @@ -863,7 +928,8 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit( llvm::DenseSet<const VarDecl *> AlreadyEmittedVars; for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { HasAtLeastOneLastprivate = true; - if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) + if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && + !getLangOpts().OpenMPSimd) break; auto IRef = C->varlist_begin(); auto IDestRef = C->destination_exprs().begin(); @@ -1100,9 +1166,8 @@ void CodeGenFunction::EmitOMPReductionClauseFinal( if (HasAtLeastOneReduction) { bool WithNowait = D.getSingleClause<OMPNowaitClause>() || isOpenMPParallelDirective(D.getDirectiveKind()) || - D.getDirectiveKind() == OMPD_simd; - bool SimpleReduction = D.getDirectiveKind() == OMPD_simd || - D.getDirectiveKind() == OMPD_distribute_simd; + ReductionKind == OMPD_simd; + bool SimpleReduction = ReductionKind == OMPD_simd; // Emit nowait reduction if nowait clause is present or directive is a // parallel directive (it always has implicit barrier). CGM.getOpenMPRuntime().emitReduction( @@ -1570,6 +1635,14 @@ static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, CGF.EmitStopPoint(&S); } +/// Emit a helper variable and return corresponding lvalue. +static LValue EmitOMPHelperVar(CodeGenFunction &CGF, + const DeclRefExpr *Helper) { + auto VDecl = cast<VarDecl>(Helper->getDecl()); + CGF.EmitVarDecl(*VDecl); + return CGF.EmitLValue(Helper); +} + static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action) { Action.Enter(CGF); @@ -1581,6 +1654,12 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, // <Final counter/linear vars updates>; // } // + if (isOpenMPDistributeDirective(S.getDirectiveKind()) || + isOpenMPWorksharingDirective(S.getDirectiveKind()) || + isOpenMPTaskLoopDirective(S.getDirectiveKind())) { + (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable())); + (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable())); + } // Emit: if (PreCond) - begin. // If the condition constant folds and can be elided, avoid emitting the @@ -1933,14 +2012,6 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop( emitEmptyOrdered); } -/// Emit a helper variable and return corresponding lvalue. -static LValue EmitOMPHelperVar(CodeGenFunction &CGF, - const DeclRefExpr *Helper) { - auto VDecl = cast<VarDecl>(Helper->getDecl()); - CGF.EmitVarDecl(*VDecl); - return CGF.EmitLValue(Helper); -} - static std::pair<LValue, LValue> emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S) { @@ -4721,3 +4792,35 @@ void CodeGenFunction::EmitOMPTargetUpdateDirective( OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device); } + +void CodeGenFunction::EmitSimpleOMPExecutableDirective( + const OMPExecutableDirective &D) { + if (!D.hasAssociatedStmt() || !D.getAssociatedStmt()) + return; + auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) { + if (isOpenMPSimdDirective(D.getDirectiveKind())) { + emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action); + } else { + if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) { + for (const auto *E : LD->counters()) { + if (const auto *VD = dyn_cast<OMPCapturedExprDecl>( + cast<DeclRefExpr>(E)->getDecl())) { + // Emit only those that were not explicitly referenced in clauses. + if (!CGF.LocalDeclMap.count(VD)) + CGF.EmitVarDecl(*VD); + } + } + } + const auto *CS = cast<CapturedStmt>(D.getAssociatedStmt()); + while (const auto *CCS = dyn_cast<CapturedStmt>(CS->getCapturedStmt())) + CS = CCS; + CGF.EmitStmt(CS->getCapturedStmt()); + } + }; + OMPSimdLexicalScope Scope(*this, D); + CGM.getOpenMPRuntime().emitInlinedDirective( + *this, + isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd + : D.getDirectiveKind(), + CodeGen); +} diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index dd4c2e43ef6..a7c322d3b95 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2655,6 +2655,9 @@ public: llvm::Value *EmitSEHExceptionInfo(); llvm::Value *EmitSEHAbnormalTermination(); + /// Emit simple code for OpenMP directives in Simd-only mode. + void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D); + /// Scan the outlined statement for captures from the parent function. For /// each capture, mark the capture as escaped and emit a call to /// llvm.localrecover. Insert the localrecover result into the LocalDeclMap. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 5bdf81aaf66..df33fc3e820 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -208,7 +208,10 @@ void CodeGenModule::createOpenMPRuntime() { OpenMPRuntime.reset(new CGOpenMPRuntimeNVPTX(*this)); break; default: - OpenMPRuntime.reset(new CGOpenMPRuntime(*this)); + if (LangOpts.OpenMPSimd) + OpenMPRuntime.reset(new CGOpenMPSIMDRuntime(*this)); + else + OpenMPRuntime.reset(new CGOpenMPRuntime(*this)); break; } } @@ -4515,6 +4518,9 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty, } void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { + // Do not emit threadprivates in simd-only mode. + if (LangOpts.OpenMP && LangOpts.OpenMPSimd) + return; for (auto RefExpr : D->varlists()) { auto *VD = cast<VarDecl>(cast<DeclRefExpr>(RefExpr)->getDecl()); bool PerformInit = |

