Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 7006d27

Browse files
committed
[OpenMP] Codegen support for 'target parallel' on the host.
This patch adds support for codegen of 'target parallel' on the host. It is also the first combined directive that requires two or more captured statements. Support for this functionality is included in the patch. A combined directive such as 'target parallel' has two captured statements, one for the 'target' and the other for the 'parallel' region. Two captured statements are required because each has different implicit parameters (see SemaOpenMP.cpp). For example, the 'parallel' has 'global_tid' and 'bound_tid' while the 'target' does not. The patch adds support for handling multiple captured statements based on the combined directive. When codegen'ing the 'target parallel' directive, the 'target' outlined function is created using the outer captured statement and the 'parallel' outlined function is created using the inner captured statement. Reviewers: ABataev Differential Revision: https://reviews.llvm.org/D28753 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@292374 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent c68b6cd commit 7006d27

15 files changed

+1612
-42
lines changed

include/clang/AST/StmtOpenMP.h

+20
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,26 @@ class OMPExecutableDirective : public Stmt {
198198
return const_cast<Stmt *>(*child_begin());
199199
}
200200

201+
/// \brief Returns the captured statement associated with the
202+
/// component region within the (combined) directive.
203+
//
204+
// \param RegionKind Component region kind.
205+
CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
206+
ArrayRef<OpenMPDirectiveKind> CaptureRegions =
207+
getOpenMPCaptureRegions(getDirectiveKind());
208+
assert(std::any_of(
209+
CaptureRegions.begin(), CaptureRegions.end(),
210+
[=](const OpenMPDirectiveKind K) { return K == RegionKind; }) &&
211+
"RegionKind not found in OpenMP CaptureRegions.");
212+
auto *CS = cast<CapturedStmt>(getAssociatedStmt());
213+
for (auto ThisCaptureRegion : CaptureRegions) {
214+
if (ThisCaptureRegion == RegionKind)
215+
return CS;
216+
CS = cast<CapturedStmt>(CS->getCapturedStmt());
217+
}
218+
llvm_unreachable("Incorrect RegionKind specified for directive.");
219+
}
220+
201221
OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
202222

203223
static bool classof(const Stmt *S) {

include/clang/Basic/OpenMPKinds.h

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef LLVM_CLANG_BASIC_OPENMPKINDS_H
1616
#define LLVM_CLANG_BASIC_OPENMPKINDS_H
1717

18+
#include "llvm/ADT/ArrayRef.h"
1819
#include "llvm/ADT/StringRef.h"
1920

2021
namespace clang {
@@ -234,6 +235,10 @@ bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind);
234235
/// directives that need loop bound sharing across loops outlined in nested
235236
/// functions
236237
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind);
238+
239+
/// Return the captured regions of an OpenMP directive.
240+
llvm::ArrayRef<OpenMPDirectiveKind>
241+
getOpenMPCaptureRegions(OpenMPDirectiveKind DKind);
237242
}
238243

239244
#endif

include/clang/Sema/Sema.h

+3
Original file line numberDiff line numberDiff line change
@@ -8340,6 +8340,9 @@ class Sema {
83408340
return IsInOpenMPDeclareTargetContext;
83418341
}
83428342

8343+
/// Return the number of captured regions created for an OpenMP directive.
8344+
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);
8345+
83438346
/// \brief Initialization of captured region for OpenMP region.
83448347
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
83458348
/// \brief End of OpenMP region.

lib/Basic/OpenMPKinds.cpp

+98
Original file line numberDiff line numberDiff line change
@@ -863,3 +863,101 @@ bool clang::isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind) {
863863
Kind == OMPD_target_teams_distribute_parallel_for_simd ||
864864
Kind == OMPD_target_teams_distribute_simd;
865865
}
866+
867+
ArrayRef<OpenMPDirectiveKind>
868+
clang::getOpenMPCaptureRegions(OpenMPDirectiveKind DKind) {
869+
assert(DKind <= OMPD_unknown);
870+
switch (DKind) {
871+
case OMPD_parallel:
872+
case OMPD_parallel_for:
873+
case OMPD_parallel_for_simd:
874+
case OMPD_parallel_sections:
875+
return {OMPD_parallel};
876+
case OMPD_teams:
877+
return {OMPD_teams};
878+
case OMPD_target_teams:
879+
return {OMPD_target_teams};
880+
case OMPD_simd:
881+
return {OMPD_simd};
882+
case OMPD_for:
883+
return {OMPD_for};
884+
case OMPD_for_simd:
885+
return {OMPD_for_simd};
886+
case OMPD_sections:
887+
return {OMPD_sections};
888+
case OMPD_section:
889+
return {OMPD_section};
890+
case OMPD_single:
891+
return {OMPD_single};
892+
case OMPD_master:
893+
return {OMPD_master};
894+
case OMPD_critical:
895+
return {OMPD_critical};
896+
case OMPD_taskgroup:
897+
return {OMPD_taskgroup};
898+
case OMPD_distribute:
899+
return {OMPD_distribute};
900+
case OMPD_ordered:
901+
return {OMPD_ordered};
902+
case OMPD_atomic:
903+
return {OMPD_atomic};
904+
case OMPD_target_data:
905+
return {OMPD_target_data};
906+
case OMPD_target:
907+
return {OMPD_target};
908+
case OMPD_target_parallel_for:
909+
return {OMPD_target_parallel_for};
910+
case OMPD_target_parallel_for_simd:
911+
return {OMPD_target_parallel_for_simd};
912+
case OMPD_target_simd:
913+
return {OMPD_target_simd};
914+
case OMPD_task:
915+
return {OMPD_task};
916+
case OMPD_taskloop:
917+
return {OMPD_taskloop};
918+
case OMPD_taskloop_simd:
919+
return {OMPD_taskloop_simd};
920+
case OMPD_distribute_parallel_for_simd:
921+
return {OMPD_distribute_parallel_for_simd};
922+
case OMPD_distribute_simd:
923+
return {OMPD_distribute_simd};
924+
case OMPD_distribute_parallel_for:
925+
return {OMPD_distribute_parallel_for};
926+
case OMPD_teams_distribute:
927+
return {OMPD_teams_distribute};
928+
case OMPD_teams_distribute_simd:
929+
return {OMPD_teams_distribute_simd};
930+
case OMPD_teams_distribute_parallel_for_simd:
931+
return {OMPD_teams_distribute_parallel_for_simd};
932+
case OMPD_teams_distribute_parallel_for:
933+
return {OMPD_teams_distribute_parallel_for};
934+
case OMPD_target_teams_distribute:
935+
return {OMPD_target_teams_distribute};
936+
case OMPD_target_teams_distribute_parallel_for:
937+
return {OMPD_target_teams_distribute_parallel_for};
938+
case OMPD_target_teams_distribute_parallel_for_simd:
939+
return {OMPD_target_teams_distribute_parallel_for_simd};
940+
case OMPD_target_teams_distribute_simd:
941+
return {OMPD_target_teams_distribute_simd};
942+
case OMPD_target_parallel:
943+
return {OMPD_target, OMPD_parallel};
944+
case OMPD_threadprivate:
945+
case OMPD_taskyield:
946+
case OMPD_barrier:
947+
case OMPD_taskwait:
948+
case OMPD_cancellation_point:
949+
case OMPD_cancel:
950+
case OMPD_flush:
951+
case OMPD_target_enter_data:
952+
case OMPD_target_exit_data:
953+
case OMPD_declare_reduction:
954+
case OMPD_declare_simd:
955+
case OMPD_declare_target:
956+
case OMPD_end_declare_target:
957+
case OMPD_target_update:
958+
llvm_unreachable("OpenMP Directive is not allowed");
959+
case OMPD_unknown:
960+
llvm_unreachable("Unknown OpenMP directive");
961+
}
962+
return {OMPD_unknown};
963+
}

lib/CodeGen/CGOpenMPRuntime.cpp

+25-5
Original file line numberDiff line numberDiff line change
@@ -842,12 +842,12 @@ static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
842842
return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
843843
}
844844

845-
llvm::Value *CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
846-
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
847-
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
845+
static llvm::Value *emitParallelOrTeamsOutlinedFunction(
846+
CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
847+
const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
848+
const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
848849
assert(ThreadIDVar->getType()->isPointerType() &&
849850
"thread id variable must be of type kmp_int32 *");
850-
const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
851851
CodeGenFunction CGF(CGM, true);
852852
bool HasCancel = false;
853853
if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
@@ -857,11 +857,27 @@ llvm::Value *CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
857857
else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
858858
HasCancel = OPFD->hasCancel();
859859
CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
860-
HasCancel, getOutlinedHelperName());
860+
HasCancel, OutlinedHelperName);
861861
CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
862862
return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
863863
}
864864

865+
llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction(
866+
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
867+
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
868+
const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
869+
return emitParallelOrTeamsOutlinedFunction(
870+
CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
871+
}
872+
873+
llvm::Value *CGOpenMPRuntime::emitTeamsOutlinedFunction(
874+
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
875+
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
876+
const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
877+
return emitParallelOrTeamsOutlinedFunction(
878+
CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
879+
}
880+
865881
llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
866882
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
867883
const VarDecl *PartIDVar, const VarDecl *TaskTVar,
@@ -6124,6 +6140,10 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
61246140
CodeGenFunction::EmitOMPTargetDeviceFunction(
61256141
CGM, ParentName, cast<OMPTargetDirective>(*S));
61266142
break;
6143+
case Stmt::OMPTargetParallelDirectiveClass:
6144+
CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
6145+
CGM, ParentName, cast<OMPTargetParallelDirective>(*S));
6146+
break;
61276147
default:
61286148
llvm_unreachable("Unknown target directive for OpenMP device codegen.");
61296149
}

lib/CodeGen/CGOpenMPRuntime.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ class CGOpenMPRuntime {
527527
/// Get combiner/initializer for the specified user-defined reduction, if any.
528528
virtual std::pair<llvm::Function *, llvm::Function *>
529529
getUserDefinedReduction(const OMPDeclareReductionDecl *D);
530+
530531
/// \brief Emits outlined function for the specified OpenMP parallel directive
531532
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
532533
/// kmp_int32 BoundID, struct context_vars*).
@@ -535,7 +536,19 @@ class CGOpenMPRuntime {
535536
/// \param InnermostKind Kind of innermost directive (for simple directives it
536537
/// is a directive itself, for combined - its innermost directive).
537538
/// \param CodeGen Code generation sequence for the \a D directive.
538-
virtual llvm::Value *emitParallelOrTeamsOutlinedFunction(
539+
virtual llvm::Value *emitParallelOutlinedFunction(
540+
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
541+
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
542+
543+
/// \brief Emits outlined function for the specified OpenMP teams directive
544+
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
545+
/// kmp_int32 BoundID, struct context_vars*).
546+
/// \param D OpenMP directive.
547+
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
548+
/// \param InnermostKind Kind of innermost directive (for simple directives it
549+
/// is a directive itself, for combined - its innermost directive).
550+
/// \param CodeGen Code generation sequence for the \a D directive.
551+
virtual llvm::Value *emitTeamsOutlinedFunction(
539552
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
540553
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
541554

lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp

+13-15
Original file line numberDiff line numberDiff line change
@@ -478,24 +478,22 @@ void CGOpenMPRuntimeNVPTX::emitNumTeamsClause(CodeGenFunction &CGF,
478478
const Expr *ThreadLimit,
479479
SourceLocation Loc) {}
480480

481-
llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOrTeamsOutlinedFunction(
481+
llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOutlinedFunction(
482482
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
483483
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
484+
return CGOpenMPRuntime::emitParallelOutlinedFunction(D, ThreadIDVar,
485+
InnermostKind, CodeGen);
486+
}
484487

485-
llvm::Function *OutlinedFun = nullptr;
486-
if (isa<OMPTeamsDirective>(D)) {
487-
llvm::Value *OutlinedFunVal =
488-
CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
489-
D, ThreadIDVar, InnermostKind, CodeGen);
490-
OutlinedFun = cast<llvm::Function>(OutlinedFunVal);
491-
OutlinedFun->removeFnAttr(llvm::Attribute::NoInline);
492-
OutlinedFun->addFnAttr(llvm::Attribute::AlwaysInline);
493-
} else {
494-
llvm::Value *OutlinedFunVal =
495-
CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
496-
D, ThreadIDVar, InnermostKind, CodeGen);
497-
OutlinedFun = cast<llvm::Function>(OutlinedFunVal);
498-
}
488+
llvm::Value *CGOpenMPRuntimeNVPTX::emitTeamsOutlinedFunction(
489+
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
490+
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
491+
492+
llvm::Value *OutlinedFunVal = CGOpenMPRuntime::emitTeamsOutlinedFunction(
493+
D, ThreadIDVar, InnermostKind, CodeGen);
494+
llvm::Function *OutlinedFun = cast<llvm::Function>(OutlinedFunVal);
495+
OutlinedFun->removeFnAttr(llvm::Attribute::NoInline);
496+
OutlinedFun->addFnAttr(llvm::Attribute::AlwaysInline);
499497

500498
return OutlinedFun;
501499
}

lib/CodeGen/CGOpenMPRuntimeNVPTX.h

+20-5
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class CGOpenMPRuntimeNVPTX : public CGOpenMPRuntime {
138138
const Expr *ThreadLimit, SourceLocation Loc) override;
139139

140140
/// \brief Emits inlined function for the specified OpenMP parallel
141-
// directive but an inlined function for teams.
141+
// directive.
142142
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
143143
/// kmp_int32 BoundID, struct context_vars*).
144144
/// \param D OpenMP directive.
@@ -147,10 +147,25 @@ class CGOpenMPRuntimeNVPTX : public CGOpenMPRuntime {
147147
/// is a directive itself, for combined - its innermost directive).
148148
/// \param CodeGen Code generation sequence for the \a D directive.
149149
llvm::Value *
150-
emitParallelOrTeamsOutlinedFunction(const OMPExecutableDirective &D,
151-
const VarDecl *ThreadIDVar,
152-
OpenMPDirectiveKind InnermostKind,
153-
const RegionCodeGenTy &CodeGen) override;
150+
emitParallelOutlinedFunction(const OMPExecutableDirective &D,
151+
const VarDecl *ThreadIDVar,
152+
OpenMPDirectiveKind InnermostKind,
153+
const RegionCodeGenTy &CodeGen) override;
154+
155+
/// \brief Emits inlined function for the specified OpenMP teams
156+
// directive.
157+
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
158+
/// kmp_int32 BoundID, struct context_vars*).
159+
/// \param D OpenMP directive.
160+
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
161+
/// \param InnermostKind Kind of innermost directive (for simple directives it
162+
/// is a directive itself, for combined - its innermost directive).
163+
/// \param CodeGen Code generation sequence for the \a D directive.
164+
llvm::Value *
165+
emitTeamsOutlinedFunction(const OMPExecutableDirective &D,
166+
const VarDecl *ThreadIDVar,
167+
OpenMPDirectiveKind InnermostKind,
168+
const RegionCodeGenTy &CodeGen) override;
154169

155170
/// \brief Emits code for teams call of the \a OutlinedFn with
156171
/// variables captured in a record which address is stored in \a

lib/CodeGen/CGStmtOpenMP.cpp

+37-9
Original file line numberDiff line numberDiff line change
@@ -1213,10 +1213,9 @@ static void emitCommonOMPParallelDirective(CodeGenFunction &CGF,
12131213
const OMPExecutableDirective &S,
12141214
OpenMPDirectiveKind InnermostKind,
12151215
const RegionCodeGenTy &CodeGen) {
1216-
auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
1217-
auto OutlinedFn = CGF.CGM.getOpenMPRuntime().
1218-
emitParallelOrTeamsOutlinedFunction(S,
1219-
*CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
1216+
const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1217+
auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction(
1218+
S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
12201219
if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) {
12211220
CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
12221221
auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
@@ -3497,10 +3496,9 @@ static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF,
34973496
const OMPExecutableDirective &S,
34983497
OpenMPDirectiveKind InnermostKind,
34993498
const RegionCodeGenTy &CodeGen) {
3500-
auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
3501-
auto OutlinedFn = CGF.CGM.getOpenMPRuntime().
3502-
emitParallelOrTeamsOutlinedFunction(S,
3503-
*CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
3499+
const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
3500+
auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitTeamsOutlinedFunction(
3501+
S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
35043502

35053503
const OMPTeamsDirective &TD = *dyn_cast<OMPTeamsDirective>(&S);
35063504
const OMPNumTeamsClause *NT = TD.getSingleClause<OMPNumTeamsClause>();
@@ -3755,9 +3753,39 @@ void CodeGenFunction::EmitOMPTargetExitDataDirective(
37553753
CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
37563754
}
37573755

3756+
static void emitTargetParallelRegion(CodeGenFunction &CGF,
3757+
const OMPTargetParallelDirective &S,
3758+
PrePostActionTy &Action) {
3759+
// Get the captured statement associated with the 'parallel' region.
3760+
auto *CS = S.getCapturedStmt(OMPD_parallel);
3761+
Action.Enter(CGF);
3762+
auto &&CodeGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) {
3763+
// TODO: Add support for clauses.
3764+
CGF.EmitStmt(CS->getCapturedStmt());
3765+
};
3766+
emitCommonOMPParallelDirective(CGF, S, OMPD_parallel, CodeGen);
3767+
}
3768+
3769+
void CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
3770+
CodeGenModule &CGM, StringRef ParentName,
3771+
const OMPTargetParallelDirective &S) {
3772+
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3773+
emitTargetParallelRegion(CGF, S, Action);
3774+
};
3775+
llvm::Function *Fn;
3776+
llvm::Constant *Addr;
3777+
// Emit target region as a standalone region.
3778+
CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3779+
S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
3780+
assert(Fn && Addr && "Target device function emission failed.");
3781+
}
3782+
37583783
void CodeGenFunction::EmitOMPTargetParallelDirective(
37593784
const OMPTargetParallelDirective &S) {
3760-
// TODO: codegen for target parallel.
3785+
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3786+
emitTargetParallelRegion(CGF, S, Action);
3787+
};
3788+
emitCommonOMPTargetDirective(*this, S, CodeGen);
37613789
}
37623790

37633791
void CodeGenFunction::EmitOMPTargetParallelForDirective(

lib/CodeGen/CodeGenFunction.h

+3
Original file line numberDiff line numberDiff line change
@@ -2708,6 +2708,9 @@ class CodeGenFunction : public CodeGenTypeCache {
27082708
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM,
27092709
StringRef ParentName,
27102710
const OMPTargetDirective &S);
2711+
static void
2712+
EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName,
2713+
const OMPTargetParallelDirective &S);
27112714
/// \brief Emit inner loop of the worksharing/simd construct.
27122715
///
27132716
/// \param S Directive, for which the inner loop must be emitted.

0 commit comments

Comments
 (0)