23#include "llvm/ADT/SmallPtrSet.h"
24#include "llvm/Frontend/OpenMP/OMPDeviceConstants.h"
25#include "llvm/Frontend/OpenMP/OMPGridValues.h"
29using namespace llvm::omp;
34 llvm::FunctionCallee EnterCallee =
nullptr;
35 ArrayRef<llvm::Value *> EnterArgs;
36 llvm::FunctionCallee ExitCallee =
nullptr;
37 ArrayRef<llvm::Value *> ExitArgs;
38 bool Conditional =
false;
39 llvm::BasicBlock *ContBlock =
nullptr;
42 NVPTXActionTy(llvm::FunctionCallee EnterCallee,
43 ArrayRef<llvm::Value *> EnterArgs,
44 llvm::FunctionCallee ExitCallee,
45 ArrayRef<llvm::Value *> ExitArgs,
bool Conditional =
false)
46 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
47 ExitArgs(ExitArgs), Conditional(Conditional) {}
48 void Enter(CodeGenFunction &CGF)
override {
51 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
55 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
59 void Done(CodeGenFunction &CGF) {
64 void Exit(CodeGenFunction &CGF)
override {
73class ExecutionRuntimeModesRAII {
82 : ExecMode(ExecMode) {
83 SavedExecMode = ExecMode;
86 ~ExecutionRuntimeModesRAII() { ExecMode = SavedExecMode; }
91 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr)) {
92 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
93 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
94 Base = TempASE->getBase()->IgnoreParenImpCasts();
96 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr)) {
97 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
98 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
99 Base = TempOASE->getBase()->IgnoreParenImpCasts();
100 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
101 Base = TempASE->getBase()->IgnoreParenImpCasts();
105 if (
const auto *DE = dyn_cast<DeclRefExpr>(RefExpr))
111static RecordDecl *buildRecordForGlobalizedVars(
114 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
118 if (EscapedDecls.empty() && EscapedDeclsForTeams.empty())
122 GlobalizedVars.emplace_back(
C.getDeclAlign(D), D);
123 for (
const ValueDecl *D : EscapedDeclsForTeams)
124 GlobalizedVars.emplace_back(
C.getDeclAlign(D), D);
130 RecordDecl *GlobalizedRD =
C.buildImplicitRecord(
"_globalized_locals_ty");
133 EscapedDeclsForTeams);
134 for (
const auto &Pair : GlobalizedVars) {
138 Type =
C.getPointerType(
Type.getNonReferenceType());
143 if (SingleEscaped.count(VD)) {
158 llvm::APInt ArraySize(32, BufSize);
159 Type =
C.getConstantArrayType(
Type, ArraySize,
nullptr,
168 llvm::APInt Align(32, Pair.first.getQuantity());
169 Field->addAttr(AlignedAttr::CreateImplicit(
172 C.getIntTypeForBitwidth(32, 0),
174 {}, AlignedAttr::GNU_aligned));
177 MappedDeclsFields.try_emplace(VD, Field);
184class CheckVarsEscapingDeclContext final
186 CodeGenFunction &CGF;
187 llvm::SetVector<const ValueDecl *> EscapedDecls;
188 llvm::SetVector<const ValueDecl *> EscapedVariableLengthDecls;
189 llvm::SetVector<const ValueDecl *> DelayedVariableLengthDecls;
190 llvm::SmallPtrSet<const Decl *, 4> EscapedParameters;
191 RecordDecl *GlobalizedRD =
nullptr;
192 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> MappedDeclsFields;
193 bool AllEscaped =
false;
194 bool IsForCombinedParallelRegion =
false;
196 void markAsEscaped(
const ValueDecl *VD) {
199 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
206 bool IsCaptured =
false;
207 if (
auto *CSI = CGF.CapturedStmtInfo) {
212 if (!IsForCombinedParallelRegion) {
215 const auto *Attr = FD->getAttr<OMPCaptureKindAttr>();
218 if (((Attr->getCaptureKind() != OMPC_map) &&
220 ((Attr->getCaptureKind() == OMPC_map) &&
221 !FD->getType()->isAnyPointerType()))
224 if (!FD->getType()->isReferenceType()) {
226 "Parameter captured by value with variably modified type");
227 EscapedParameters.insert(VD);
228 }
else if (!IsForCombinedParallelRegion) {
233 if ((!CGF.CapturedStmtInfo ||
234 (IsForCombinedParallelRegion && CGF.CapturedStmtInfo)) &&
242 EscapedVariableLengthDecls.insert(VD);
244 DelayedVariableLengthDecls.insert(VD);
246 EscapedDecls.insert(VD);
249 void VisitValueDecl(
const ValueDecl *VD) {
252 if (
const auto *VarD = dyn_cast<VarDecl>(VD)) {
254 const bool SavedAllEscaped = AllEscaped;
256 Visit(VarD->getInit());
257 AllEscaped = SavedAllEscaped;
261 void VisitOpenMPCapturedStmt(
const CapturedStmt *S,
262 ArrayRef<OMPClause *> Clauses,
263 bool IsCombinedParallelRegion) {
266 for (
const CapturedStmt::Capture &
C : S->
captures()) {
267 if (
C.capturesVariable() && !
C.capturesVariableByCopy()) {
268 const ValueDecl *VD =
C.getCapturedVar();
269 bool SavedIsForCombinedParallelRegion = IsForCombinedParallelRegion;
270 if (IsCombinedParallelRegion) {
274 IsForCombinedParallelRegion =
false;
275 for (
const OMPClause *
C : Clauses) {
277 C->getClauseKind() == OMPC_reduction ||
278 C->getClauseKind() == OMPC_linear ||
279 C->getClauseKind() == OMPC_private)
281 ArrayRef<const Expr *> Vars;
282 if (
const auto *PC = dyn_cast<OMPFirstprivateClause>(
C))
283 Vars = PC->getVarRefs();
284 else if (
const auto *PC = dyn_cast<OMPLastprivateClause>(
C))
285 Vars = PC->getVarRefs();
287 llvm_unreachable(
"Unexpected clause.");
288 for (
const auto *E : Vars) {
292 IsForCombinedParallelRegion =
true;
296 if (IsForCombinedParallelRegion)
303 IsForCombinedParallelRegion = SavedIsForCombinedParallelRegion;
308 void buildRecordForGlobalizedVars(
bool IsInTTDRegion) {
309 assert(!GlobalizedRD &&
310 "Record for globalized variables is built already.");
311 ArrayRef<const ValueDecl *> EscapedDeclsForParallel, EscapedDeclsForTeams;
312 unsigned WarpSize = CGF.getTarget().getGridValue().GV_Warp_Size;
314 EscapedDeclsForTeams = EscapedDecls.getArrayRef();
316 EscapedDeclsForParallel = EscapedDecls.getArrayRef();
317 GlobalizedRD = ::buildRecordForGlobalizedVars(
318 CGF.getContext(), EscapedDeclsForParallel, EscapedDeclsForTeams,
319 MappedDeclsFields, WarpSize);
323 CheckVarsEscapingDeclContext(CodeGenFunction &CGF,
324 ArrayRef<const ValueDecl *> TeamsReductions)
325 : CGF(CGF), EscapedDecls(llvm::from_range, TeamsReductions) {}
326 ~CheckVarsEscapingDeclContext() =
default;
327 void VisitDeclStmt(
const DeclStmt *S) {
331 if (
const auto *VD = dyn_cast_or_null<ValueDecl>(D))
334 void VisitOMPExecutableDirective(
const OMPExecutableDirective *D) {
337 if (!D->hasAssociatedStmt())
340 dyn_cast_or_null<CapturedStmt>(D->getAssociatedStmt())) {
343 llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
345 if (CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown) {
346 VisitStmt(S->getCapturedStmt());
349 VisitOpenMPCapturedStmt(
351 CaptureRegions.back() == OMPD_parallel &&
355 void VisitCapturedStmt(
const CapturedStmt *S) {
358 for (
const CapturedStmt::Capture &
C : S->
captures()) {
359 if (
C.capturesVariable() && !
C.capturesVariableByCopy()) {
360 const ValueDecl *VD =
C.getCapturedVar();
370 for (
const LambdaCapture &
C : E->
captures()) {
371 if (
C.capturesVariable()) {
373 const ValueDecl *VD =
C.getCapturedVar();
381 void VisitBlockExpr(
const BlockExpr *E) {
386 const VarDecl *VD =
C.getVariable();
393 void VisitCallExpr(
const CallExpr *E) {
399 if (Arg->isLValue()) {
400 const bool SavedAllEscaped = AllEscaped;
403 AllEscaped = SavedAllEscaped;
410 void VisitDeclRefExpr(
const DeclRefExpr *E) {
413 const ValueDecl *VD = E->
getDecl();
421 void VisitUnaryOperator(
const UnaryOperator *E) {
425 const bool SavedAllEscaped = AllEscaped;
428 AllEscaped = SavedAllEscaped;
433 void VisitImplicitCastExpr(
const ImplicitCastExpr *E) {
437 const bool SavedAllEscaped = AllEscaped;
440 AllEscaped = SavedAllEscaped;
445 void VisitExpr(
const Expr *E) {
448 bool SavedAllEscaped = AllEscaped;
451 for (
const Stmt *Child : E->
children())
454 AllEscaped = SavedAllEscaped;
456 void VisitStmt(
const Stmt *S) {
459 for (
const Stmt *Child : S->
children())
466 const RecordDecl *getGlobalizedRecord(
bool IsInTTDRegion) {
468 buildRecordForGlobalizedVars(IsInTTDRegion);
473 const FieldDecl *getFieldForGlobalizedVar(
const ValueDecl *VD)
const {
474 assert(GlobalizedRD &&
475 "Record for globalized variables must be generated already.");
476 return MappedDeclsFields.lookup(VD);
480 ArrayRef<const ValueDecl *> getEscapedDecls()
const {
481 return EscapedDecls.getArrayRef();
486 const llvm::SmallPtrSetImpl<const Decl *> &getEscapedParameters()
const {
487 return EscapedParameters;
492 ArrayRef<const ValueDecl *> getEscapedVariableLengthDecls()
const {
493 return EscapedVariableLengthDecls.getArrayRef();
498 ArrayRef<const ValueDecl *> getDelayedVariableLengthDecls()
const {
499 return DelayedVariableLengthDecls.getArrayRef();
505CGOpenMPRuntimeGPU::getExecutionMode()
const {
506 return CurrentExecutionMode;
510CGOpenMPRuntimeGPU::getDataSharingMode()
const {
511 return CurrentDataSharingMode;
517 const auto *CS = D.getInnermostCapturedStmt();
519 CS->getCapturedStmt()->IgnoreContainers(
true);
522 if (
const auto *NestedDir =
523 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
525 switch (D.getDirectiveKind()) {
529 if (DKind == OMPD_teams) {
530 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
535 if (
const auto *NND =
536 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
537 DKind = NND->getDirectiveKind();
543 case OMPD_target_teams:
545 case OMPD_target_simd:
546 case OMPD_target_parallel:
547 case OMPD_target_parallel_for:
548 case OMPD_target_parallel_for_simd:
549 case OMPD_target_teams_distribute:
550 case OMPD_target_teams_distribute_simd:
551 case OMPD_target_teams_distribute_parallel_for:
552 case OMPD_target_teams_distribute_parallel_for_simd:
555 case OMPD_parallel_for:
556 case OMPD_parallel_master:
557 case OMPD_parallel_sections:
559 case OMPD_parallel_for_simd:
561 case OMPD_cancellation_point:
563 case OMPD_threadprivate:
581 case OMPD_target_data:
582 case OMPD_target_exit_data:
583 case OMPD_target_enter_data:
584 case OMPD_distribute:
585 case OMPD_distribute_simd:
586 case OMPD_distribute_parallel_for:
587 case OMPD_distribute_parallel_for_simd:
588 case OMPD_teams_distribute:
589 case OMPD_teams_distribute_simd:
590 case OMPD_teams_distribute_parallel_for:
591 case OMPD_teams_distribute_parallel_for_simd:
592 case OMPD_target_update:
593 case OMPD_declare_simd:
594 case OMPD_declare_variant:
595 case OMPD_begin_declare_variant:
596 case OMPD_end_declare_variant:
597 case OMPD_declare_target:
598 case OMPD_end_declare_target:
599 case OMPD_declare_reduction:
600 case OMPD_declare_mapper:
602 case OMPD_taskloop_simd:
603 case OMPD_master_taskloop:
604 case OMPD_master_taskloop_simd:
605 case OMPD_parallel_master_taskloop:
606 case OMPD_parallel_master_taskloop_simd:
610 llvm_unreachable(
"Unexpected directive.");
620 switch (DirectiveKind) {
622 case OMPD_target_teams:
624 case OMPD_target_parallel_loop:
625 case OMPD_target_parallel:
626 case OMPD_target_parallel_for:
627 case OMPD_target_parallel_for_simd:
628 case OMPD_target_teams_distribute_parallel_for:
629 case OMPD_target_teams_distribute_parallel_for_simd:
630 case OMPD_target_simd:
631 case OMPD_target_teams_distribute_simd:
633 case OMPD_target_teams_distribute:
635 case OMPD_target_teams_loop:
638 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
639 return TTLD->canBeParallelFor();
643 case OMPD_parallel_for:
644 case OMPD_parallel_master:
645 case OMPD_parallel_sections:
647 case OMPD_parallel_for_simd:
649 case OMPD_cancellation_point:
651 case OMPD_threadprivate:
669 case OMPD_target_data:
670 case OMPD_target_exit_data:
671 case OMPD_target_enter_data:
672 case OMPD_distribute:
673 case OMPD_distribute_simd:
674 case OMPD_distribute_parallel_for:
675 case OMPD_distribute_parallel_for_simd:
676 case OMPD_teams_distribute:
677 case OMPD_teams_distribute_simd:
678 case OMPD_teams_distribute_parallel_for:
679 case OMPD_teams_distribute_parallel_for_simd:
680 case OMPD_target_update:
681 case OMPD_declare_simd:
682 case OMPD_declare_variant:
683 case OMPD_begin_declare_variant:
684 case OMPD_end_declare_variant:
685 case OMPD_declare_target:
686 case OMPD_end_declare_target:
687 case OMPD_declare_reduction:
688 case OMPD_declare_mapper:
690 case OMPD_taskloop_simd:
691 case OMPD_master_taskloop:
692 case OMPD_master_taskloop_simd:
693 case OMPD_parallel_master_taskloop:
694 case OMPD_parallel_master_taskloop_simd:
701 "Unknown programming model for OpenMP directive on NVPTX target.");
704void CGOpenMPRuntimeGPU::emitNonSPMDKernel(
const OMPExecutableDirective &D,
705 StringRef ParentName,
706 llvm::Function *&OutlinedFn,
707 llvm::Constant *&OutlinedFnID,
710 ExecutionRuntimeModesRAII ModeRAII(CurrentExecutionMode,
EM_NonSPMD);
711 EntryFunctionState EST;
712 WrapperFunctionsMap.clear();
714 [[maybe_unused]]
bool IsBareKernel = D.getSingleClause<OMPXBareClause>();
715 assert(!IsBareKernel &&
"bare kernel should not be at generic mode");
718 class NVPTXPrePostActionTy :
public PrePostActionTy {
719 CGOpenMPRuntimeGPU::EntryFunctionState &EST;
720 const OMPExecutableDirective &D;
723 NVPTXPrePostActionTy(CGOpenMPRuntimeGPU::EntryFunctionState &EST,
724 const OMPExecutableDirective &D)
726 void Enter(CodeGenFunction &CGF)
override {
728 RT.emitKernelInit(D, CGF, EST,
false);
730 RT.setLocThreadIdInsertPt(CGF,
true);
732 void Exit(CodeGenFunction &CGF)
override {
734 RT.clearLocThreadIdInsertPt(CGF);
735 RT.emitKernelDeinit(CGF, EST,
false);
739 IsInTTDRegion =
true;
741 IsOffloadEntry, CodeGen);
742 IsInTTDRegion =
false;
745void CGOpenMPRuntimeGPU::emitKernelInit(
const OMPExecutableDirective &D,
747 EntryFunctionState &EST,
bool IsSPMD) {
748 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs Attrs;
750 IsSPMD ? llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_SPMD
751 : llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_GENERIC;
754 CGBuilderTy &Bld = CGF.
Builder;
755 Bld.restoreIP(
OMPBuilder.createTargetInit(Bld, Attrs));
757 emitGenericVarsProlog(CGF, EST.Loc);
761 EntryFunctionState &EST,
764 emitGenericVarsEpilog(CGF);
767 ASTContext &
C =
CGM.getContext();
768 RecordDecl *StaticRD =
C.buildImplicitRecord(
769 "_openmp_teams_reduction_type_$_", RecordDecl::TagKind::Union);
771 for (
const RecordDecl *TeamReductionRec : TeamsReductions) {
772 CanQualType RecTy =
C.getCanonicalTagType(TeamReductionRec);
774 C, StaticRD, SourceLocation(), SourceLocation(),
nullptr, RecTy,
775 C.getTrivialTypeSourceInfo(RecTy, SourceLocation()),
783 llvm::Type *LLVMReductionsBufferTy =
784 CGM.getTypes().ConvertTypeForMem(StaticTy);
785 const auto &DL =
CGM.getModule().getDataLayout();
787 TeamsReductions.empty()
789 : DL.getTypeAllocSize(LLVMReductionsBufferTy).getFixedValue();
790 CGBuilderTy &Bld = CGF.
Builder;
791 OMPBuilder.createTargetDeinit(Bld, ReductionDataSize);
792 TeamsReductions.clear();
795void CGOpenMPRuntimeGPU::emitSPMDKernel(
const OMPExecutableDirective &D,
796 StringRef ParentName,
797 llvm::Function *&OutlinedFn,
798 llvm::Constant *&OutlinedFnID,
801 ExecutionRuntimeModesRAII ModeRAII(CurrentExecutionMode,
EM_SPMD);
802 EntryFunctionState EST;
804 bool IsBareKernel = D.getSingleClause<OMPXBareClause>();
807 class NVPTXPrePostActionTy :
public PrePostActionTy {
808 CGOpenMPRuntimeGPU &RT;
809 CGOpenMPRuntimeGPU::EntryFunctionState &EST;
811 DataSharingMode Mode;
812 const OMPExecutableDirective &D;
815 NVPTXPrePostActionTy(CGOpenMPRuntimeGPU &RT,
816 CGOpenMPRuntimeGPU::EntryFunctionState &EST,
817 bool IsBareKernel,
const OMPExecutableDirective &D)
818 : RT(RT), EST(EST), IsBareKernel(IsBareKernel),
819 Mode(RT.CurrentDataSharingMode), D(D) {}
820 void Enter(CodeGenFunction &CGF)
override {
822 RT.CurrentDataSharingMode = DataSharingMode::DS_CUDA;
825 RT.emitKernelInit(D, CGF, EST,
true);
827 RT.setLocThreadIdInsertPt(CGF,
true);
829 void Exit(CodeGenFunction &CGF)
override {
831 RT.CurrentDataSharingMode = Mode;
834 RT.clearLocThreadIdInsertPt(CGF);
835 RT.emitKernelDeinit(CGF, EST,
true);
837 } Action(*
this, EST, IsBareKernel, D);
839 IsInTTDRegion =
true;
841 IsOffloadEntry, CodeGen);
842 IsInTTDRegion =
false;
845void CGOpenMPRuntimeGPU::emitTargetOutlinedFunction(
846 const OMPExecutableDirective &D, StringRef ParentName,
847 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
852 assert(!ParentName.empty() &&
"Invalid target region parent name!");
855 bool IsBareKernel = D.getSingleClause<OMPXBareClause>();
856 if (Mode || IsBareKernel)
857 emitSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry,
860 emitNonSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry,
866 llvm::OpenMPIRBuilderConfig Config(
867 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
868 CGM.getLangOpts().OpenMPOffloadMandatory,
871 Config.setDefaultTargetAS(
873 Config.setRuntimeCC(
CGM.getRuntimeCC());
877 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
878 llvm_unreachable(
"OpenMP can only handle device code.");
880 if (
CGM.getLangOpts().OpenMPCUDAMode)
884 if (
CGM.getLangOpts().NoGPULib ||
CGM.getLangOpts().OMPHostIRFile.empty())
887 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPTargetDebug,
888 "__omp_rtl_debug_kind");
889 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPTeamSubscription,
890 "__omp_rtl_assume_teams_oversubscription");
891 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPThreadSubscription,
892 "__omp_rtl_assume_threads_oversubscription");
893 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPNoThreadState,
894 "__omp_rtl_assume_no_thread_state");
895 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPNoNestedParallelism,
896 "__omp_rtl_assume_no_nested_parallelism");
900 ProcBindKind ProcBind,
908 CGM.getDiags().Report(Loc, diag::warn_omp_gpu_unsupported_clause)
909 << getOpenMPClauseName(OMPC_message);
916 CGM.getDiags().Report(Loc, diag::warn_omp_gpu_unsupported_clause)
917 << getOpenMPClauseName(OMPC_severity);
926 if (Modifier == OMPC_NUMTHREADS_strict) {
927 CGM.getDiags().Report(Loc,
928 diag::warn_omp_gpu_unsupported_modifier_for_clause)
929 <<
"strict" << getOpenMPClauseName(OMPC_num_threads);
937 const Expr *NumTeams,
938 const Expr *ThreadLimit,
946 bool PrevIsInTTDRegion = IsInTTDRegion;
947 IsInTTDRegion =
false;
950 CGF, D, ThreadIDVar, InnermostKind,
CodeGen));
951 IsInTTDRegion = PrevIsInTTDRegion;
953 llvm::Function *WrapperFun =
954 createParallelDataSharingWrapper(OutlinedFun, D);
955 WrapperFunctionsMap[OutlinedFun] = WrapperFun;
967 "expected teams directive.");
972 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(
974 Dir = dyn_cast_or_null<OMPExecutableDirective>(S);
981 for (
const auto *
C : Dir->getClausesOfKind<OMPLastprivateClause>()) {
982 for (
const Expr *E :
C->getVarRefs())
992 "expected teams directive.");
993 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
994 for (
const Expr *E :
C->privates())
1007 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> MappedDeclsFields;
1008 unsigned WarpSize =
CGM.getTarget().getGridValue().GV_Warp_Size;
1014 if (!LastPrivatesReductions.empty()) {
1015 GlobalizedRD = ::buildRecordForGlobalizedVars(
1016 CGM.getContext(), {}, LastPrivatesReductions, MappedDeclsFields,
1019 }
else if (!LastPrivatesReductions.empty()) {
1020 assert(!TeamAndReductions.first &&
1021 "Previous team declaration is not expected.");
1022 TeamAndReductions.first = D.getCapturedStmt(OMPD_teams)->getCapturedDecl();
1023 std::swap(TeamAndReductions.second, LastPrivatesReductions);
1030 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
1034 NVPTXPrePostActionTy(
1036 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
1038 : Loc(Loc), GlobalizedRD(GlobalizedRD),
1039 MappedDeclsFields(MappedDeclsFields) {}
1044 auto I = Rt.FunctionGlobalizedDecls.try_emplace(CGF.
CurFn).first;
1045 I->getSecond().MappedParams =
1046 std::make_unique<CodeGenFunction::OMPMapVars>();
1047 DeclToAddrMapTy &
Data = I->getSecond().LocalVarData;
1048 for (
const auto &Pair : MappedDeclsFields) {
1049 assert(Pair.getFirst()->isCanonicalDecl() &&
1050 "Expected canonical declaration");
1051 Data.try_emplace(Pair.getFirst());
1054 Rt.emitGenericVarsProlog(CGF, Loc);
1058 .emitGenericVarsEpilog(CGF);
1060 } Action(Loc, GlobalizedRD, MappedDeclsFields);
1063 CGF, D, ThreadIDVar, InnermostKind,
CodeGen);
1075 const auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
1076 if (I == FunctionGlobalizedDecls.end())
1079 for (
auto &Rec : I->getSecond().LocalVarData) {
1081 bool EscapedParam = I->getSecond().EscapedParameters.count(Rec.first);
1085 llvm::Value *ParValue;
1094 llvm::CallBase *VoidPtr =
1099 VoidPtr->addRetAttr(llvm::Attribute::get(
1105 VoidPtr, Bld.getPtrTy(0), VD->
getName() +
"_on_stack");
1108 Rec.second.PrivateAddr = VarAddr.getAddress();
1109 Rec.second.GlobalizedVal = VoidPtr;
1114 I->getSecond().MappedParams->setVarAddr(CGF, VD, VarAddr.getAddress());
1117 VoidPtr->setDebugLoc(DI->SourceLocToDebugLoc(VD->
getLocation()));
1120 for (
const auto *ValueD : I->getSecond().EscapedVariableLengthDecls) {
1122 std::pair<llvm::Value *, llvm::Value *> AddrSizePair =
1124 I->getSecond().EscapedVariableLengthDeclsAddrs.emplace_back(AddrSizePair);
1126 CGM.getContext().getDeclAlign(VD),
1128 I->getSecond().MappedParams->setVarAddr(CGF, VD,
Base.getAddress());
1130 I->getSecond().MappedParams->apply(CGF);
1135 const auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
1136 if (I == FunctionGlobalizedDecls.end())
1140 return llvm::is_contained(I->getSecond().DelayedVariableLengthDecls, VD);
1143std::pair<llvm::Value *, llvm::Value *>
1151 Size = Bld.CreateNUWAdd(
1153 llvm::Value *AlignVal =
1155 Size = Bld.CreateUDiv(Size, AlignVal);
1156 Size = Bld.CreateNUWMul(Size, AlignVal);
1159 llvm::Value *AllocArgs[] = {Size};
1160 llvm::CallBase *VoidPtr =
1162 CGM.getModule(), OMPRTL___kmpc_alloc_shared),
1164 VoidPtr->addRetAttr(llvm::Attribute::get(
1165 CGM.getLLVMContext(), llvm::Attribute::Alignment, Align.
getQuantity()));
1167 return std::make_pair(VoidPtr, Size);
1172 const std::pair<llvm::Value *, llvm::Value *> &AddrSizePair) {
1175 CGM.getModule(), OMPRTL___kmpc_free_shared),
1176 {AddrSizePair.first, AddrSizePair.second});
1183 const auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
1184 if (I != FunctionGlobalizedDecls.end()) {
1187 for (
const auto &AddrSizePair :
1188 llvm::reverse(I->getSecond().EscapedVariableLengthDeclsAddrs)) {
1191 {AddrSizePair.first, AddrSizePair.second});
1194 for (
auto &Rec : llvm::reverse(I->getSecond().LocalVarData)) {
1196 I->getSecond().MappedParams->restore(CGF);
1198 llvm::Value *FreeArgs[] = {Rec.second.GlobalizedVal,
1210 llvm::Function *OutlinedFn,
1224 OutlinedFnArgs.push_back(llvm::ConstantPointerNull::get(
CGM.VoidPtrTy));
1227 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1228 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
1240 auto &&ParallelGen = [
this, Loc, OutlinedFn, CapturedVars, IfCond,
1244 llvm::Value *NumThreadsVal = NumThreads;
1245 llvm::Function *WFn = WrapperFunctionsMap[OutlinedFn];
1246 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1249 llvm::Value *ID = llvm::ConstantPointerNull::get(FnPtrTy);
1251 ID = Bld.CreateBitOrPointerCast(WFn, FnPtrTy);
1253 llvm::Value *FnPtr = Bld.CreateBitOrPointerCast(OutlinedFn, FnPtrTy);
1261 llvm::ArrayType::get(
CGM.VoidPtrTy, CapturedVars.size()),
1262 "captured_vars_addrs");
1264 if (!CapturedVars.empty()) {
1268 for (llvm::Value *
V : CapturedVars) {
1271 if (
V->getType()->isIntegerTy())
1281 llvm::Value *IfCondVal =
nullptr;
1286 IfCondVal = llvm::ConstantInt::get(CGF.
Int32Ty, 1);
1289 NumThreadsVal = llvm::ConstantInt::getAllOnesValue(CGF.
Int32Ty);
1291 NumThreadsVal = Bld.CreateZExtOrTrunc(NumThreadsVal, CGF.
Int32Ty);
1294 llvm::Value *StrictNumThreadsVal = llvm::ConstantInt::get(CGF.
Int32Ty, 0);
1296 assert(IfCondVal &&
"Expected a value");
1298 llvm::Value *Args[] = {
1303 llvm::ConstantInt::getAllOnesValue(CGF.
Int32Ty),
1306 Bld.CreateBitOrPointerCast(CapturedVarsAddrs.
emitRawPointer(CGF),
1308 llvm::ConstantInt::get(
CGM.SizeTy, CapturedVars.size()),
1309 StrictNumThreadsVal};
1312 CGM.getModule(), OMPRTL___kmpc_parallel_60),
1326 llvm::Value *Args[] = {
1327 llvm::ConstantPointerNull::get(
1329 llvm::ConstantInt::get(CGF.
Int32Ty, 0,
true)};
1348 CGM.getModule(), OMPRTL___kmpc_barrier),
1366 CGM.getModule(), OMPRTL___kmpc_warp_active_thread_mask));
1368 llvm::Value *ThreadID = RT.getGPUThreadID(CGF);
1371 llvm::Value *TeamWidth = RT.getGPUNumThreads(CGF);
1384 llvm::Value *CmpLoopBound = CGF.
Builder.CreateICmpSLT(CounterVal, TeamWidth);
1385 CGF.
Builder.CreateCondBr(CmpLoopBound, TestBB, ExitBB);
1391 llvm::Value *CmpThreadToCounter =
1392 CGF.
Builder.CreateICmpEQ(ThreadID, CounterVal);
1393 CGF.
Builder.CreateCondBr(CmpThreadToCounter, BodyBB, SyncBB);
1409 CGM.getModule(), OMPRTL___kmpc_syncwarp),
1412 llvm::Value *IncCounterVal =
1426 "Cast type must sized.");
1428 "Val type must sized.");
1430 if (ValTy == CastTy)
1434 return CGF.
Builder.CreateBitCast(Val, LLVMCastTy);
1436 return CGF.
Builder.CreateIntCast(Val, LLVMCastTy,
1701 assert(!TeamsReduction && !ParallelReduction &&
1702 "Invalid reduction selection in emitReduction.");
1703 (void)ParallelReduction;
1705 ReductionOps, Options);
1709 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> VarFieldMap;
1716 const RecordDecl *ReductionRec = ::buildRecordForGlobalizedVars(
1717 CGM.getContext(), PrivatesReductions, {}, VarFieldMap, 1);
1720 TeamsReductions.push_back(ReductionRec);
1725 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1728 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
1729 CGF.
Builder.GetInsertPoint());
1730 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(
1737 llvm::Type *ElementType;
1738 llvm::Value *Variable;
1739 llvm::Value *PrivateVariable;
1740 llvm::OpenMPIRBuilder::ReductionGenAtomicCBTy AtomicReductionGen =
nullptr;
1742 const auto *RHSVar =
1745 const auto *LHSVar =
1748 llvm::OpenMPIRBuilder::EvalKind EvalKind;
1751 EvalKind = llvm::OpenMPIRBuilder::EvalKind::Scalar;
1754 EvalKind = llvm::OpenMPIRBuilder::EvalKind::Complex;
1757 EvalKind = llvm::OpenMPIRBuilder::EvalKind::Aggregate;
1760 auto ReductionGen = [&](InsertPointTy CodeGenIP,
unsigned I,
1761 llvm::Value **LHSPtr, llvm::Value **RHSPtr,
1762 llvm::Function *NewFunc) {
1763 CGF.
Builder.restoreIP(CodeGenIP);
1764 auto *CurFn = CGF.
CurFn;
1765 CGF.
CurFn = NewFunc;
1780 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
1781 CGF.
Builder.GetInsertPoint());
1783 ReductionInfos.emplace_back(llvm::OpenMPIRBuilder::ReductionInfo(
1784 ElementType, Variable, PrivateVariable, EvalKind,
1785 nullptr, ReductionGen, AtomicReductionGen,
1791 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
1793 OmpLoc, AllocaIP, CodeGenIP, ReductionInfos, {},
false,
1794 TeamsReduction, IsSPMD,
1795 llvm::OpenMPIRBuilder::ReductionGenCBKind::Clang,
1797 CGF.
Builder.restoreIP(AfterIP);
1802 const VarDecl *NativeParam)
const {
1809 if (
const auto *
Attr = FD->
getAttr<OMPCaptureKindAttr>()) {
1810 if (
Attr->getCaptureKind() == OMPC_map) {
1811 PointeeTy =
CGM.getContext().getAddrSpaceQualType(PointeeTy,
1815 ArgType =
CGM.getContext().getPointerType(PointeeTy);
1833 const VarDecl *TargetParam)
const {
1834 assert(NativeParam != TargetParam &&
1836 "Native arg must not be the same as target arg.");
1840 const Type *NonQualTy = QC.
strip(NativeParamType);
1842 unsigned NativePointeeAddrSpace =
1850 llvm::PointerType::get(CGF.
getLLVMContext(), NativePointeeAddrSpace));
1854 return NativeParamAddr;
1861 TargetArgs.reserve(Args.size());
1862 auto *FnType = OutlinedFn.getFunctionType();
1863 for (
unsigned I = 0, E = Args.size(); I < E; ++I) {
1864 if (FnType->isVarArg() && FnType->getNumParams() <= I) {
1865 TargetArgs.append(std::next(Args.begin(), I), Args.end());
1868 llvm::Type *TargetType = FnType->getParamType(I);
1869 llvm::Value *NativeArg = Args[I];
1870 if (!TargetType->isPointerTy()) {
1871 TargetArgs.emplace_back(NativeArg);
1874 TargetArgs.emplace_back(
1884llvm::Function *CGOpenMPRuntimeGPU::createParallelDataSharingWrapper(
1887 const auto &CS = *D.getCapturedStmt(OMPD_parallel);
1896 Ctx,
nullptr, D.getBeginLoc(),
1899 Ctx,
nullptr, D.getBeginLoc(),
1901 WrapperArgs.emplace_back(ParallelLevelArg);
1902 WrapperArgs.emplace_back(WrapperArg);
1907 auto *Fn = llvm::Function::Create(
1909 Twine(OutlinedParallelFn->getName(),
"_wrapper"), &
CGM.
getModule());
1917 Fn->addFnAttr(llvm::Attribute::NoInline);
1920 Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
1921 Fn->setDoesNotRecurse();
1925 D.getBeginLoc(), D.getBeginLoc());
1927 const auto *RD = CS.getCapturedRecordDecl();
1928 auto CurField = RD->field_begin();
1940 auto CI = CS.capture_begin();
1946 llvm::Value *GlobalArgsPtr = GlobalArgs.
getPointer();
1947 llvm::Value *DataSharingArgs[] = {GlobalArgsPtr};
1955 if (CS.capture_size() > 0 ||
1966 Src, Bld.getPtrTy(0), CGF.
SizeTy);
1972 Args.emplace_back(LB);
1982 Args.emplace_back(UB);
1985 if (CS.capture_size() > 0) {
1987 for (
unsigned I = 0, E = CS.capture_size(); I < E; ++I, ++CI, ++CurField) {
1988 QualType ElemTy = CurField->getType();
1997 if (CI->capturesVariableByCopy() &&
1998 !CI->getCapturedVar()->getType()->isAnyPointerType()) {
2002 Args.emplace_back(Arg);
2016 assert(D &&
"Expected function or captured|block decl.");
2017 assert(FunctionGlobalizedDecls.count(CGF.
CurFn) == 0 &&
2018 "Function is registered already.");
2019 assert((!TeamAndReductions.first || TeamAndReductions.first == D) &&
2020 "Team is set but not processed.");
2021 const Stmt *Body =
nullptr;
2022 bool NeedToDelayGlobalization =
false;
2023 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
2024 Body = FD->getBody();
2025 }
else if (
const auto *BD = dyn_cast<BlockDecl>(D)) {
2026 Body = BD->getBody();
2027 }
else if (
const auto *CD = dyn_cast<CapturedDecl>(D)) {
2028 Body = CD->getBody();
2030 if (NeedToDelayGlobalization &&
2036 CheckVarsEscapingDeclContext VarChecker(CGF, TeamAndReductions.second);
2037 VarChecker.Visit(Body);
2039 VarChecker.getGlobalizedRecord(IsInTTDRegion);
2040 TeamAndReductions.first =
nullptr;
2041 TeamAndReductions.second.clear();
2043 VarChecker.getEscapedVariableLengthDecls();
2045 VarChecker.getDelayedVariableLengthDecls();
2046 if (!GlobalizedVarsRecord && EscapedVariableLengthDecls.empty() &&
2047 DelayedVariableLengthDecls.empty())
2049 auto I = FunctionGlobalizedDecls.try_emplace(CGF.
CurFn).first;
2050 I->getSecond().MappedParams =
2051 std::make_unique<CodeGenFunction::OMPMapVars>();
2052 I->getSecond().EscapedParameters.insert(
2053 VarChecker.getEscapedParameters().begin(),
2054 VarChecker.getEscapedParameters().end());
2055 I->getSecond().EscapedVariableLengthDecls.append(
2056 EscapedVariableLengthDecls.begin(), EscapedVariableLengthDecls.end());
2057 I->getSecond().DelayedVariableLengthDecls.append(
2058 DelayedVariableLengthDecls.begin(), DelayedVariableLengthDecls.end());
2059 DeclToAddrMapTy &
Data = I->getSecond().LocalVarData;
2060 for (
const ValueDecl *VD : VarChecker.getEscapedDecls()) {
2062 Data.try_emplace(VD);
2064 if (!NeedToDelayGlobalization) {
2066 struct GlobalizationScope final : EHScopeStack::Cleanup {
2067 GlobalizationScope() =
default;
2071 .emitGenericVarsEpilog(CGF);
2080 if (VD && VD->
hasAttr<OMPAllocateDeclAttr>()) {
2081 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
2083 switch (A->getAllocatorType()) {
2084 case OMPAllocateDeclAttr::OMPNullMemAlloc:
2085 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
2086 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
2087 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
2089 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
2091 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
2094 case OMPAllocateDeclAttr::OMPConstMemAlloc:
2097 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
2100 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
2101 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
2105 auto *GV =
new llvm::GlobalVariable(
2106 CGM.getModule(), VarTy,
false,
2107 llvm::GlobalValue::InternalLinkage, llvm::PoisonValue::get(VarTy),
2109 nullptr, llvm::GlobalValue::NotThreadLocal,
2110 CGM.getContext().getTargetAddressSpace(AS));
2115 GV, CGF.
Builder.getPtrTy(
CGM.getContext().getTargetAddressSpace(
2124 auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
2125 if (I == FunctionGlobalizedDecls.end())
2127 auto VDI = I->getSecond().LocalVarData.find(VD);
2128 if (VDI != I->getSecond().LocalVarData.end())
2129 return VDI->second.PrivateAddr;
2134 auto VDI = I->getSecond().LocalVarData.find(
2136 ->getCanonicalDecl());
2137 if (VDI != I->getSecond().LocalVarData.end())
2138 return VDI->second.PrivateAddr;
2146 FunctionGlobalizedDecls.erase(CGF.
CurFn);
2153 llvm::Value *&Chunk)
const {
2156 ScheduleKind = OMPC_DIST_SCHEDULE_static;
2158 RT.getGPUNumThreads(CGF),
2160 S.getIterationVariable()->getType(), S.getBeginLoc());
2164 CGF, S, ScheduleKind, Chunk);
2170 const Expr *&ChunkExpr)
const {
2171 ScheduleKind = OMPC_SCHEDULE_static;
2173 llvm::APInt ChunkSize(32, 1);
2182 " Expected target-based directive.");
2183 const CapturedStmt *CS = D.getCapturedStmt(OMPD_target);
2187 if (!
C.capturesVariable())
2189 const VarDecl *VD =
C.getCapturedVar();
2190 const auto *RD = VD->
getType()
2194 if (!RD || !RD->isLambda())
2203 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
2205 RD->getCaptureFields(Captures, ThisCapture);
2215 const ValueDecl *VD = LC.getCapturedVar();
2220 auto It = Captures.find(VD);
2221 assert(It != Captures.end() &&
"Found lambda capture without field.");
2235 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
2237 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
2238 switch(A->getAllocatorType()) {
2239 case OMPAllocateDeclAttr::OMPNullMemAlloc:
2240 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
2242 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
2243 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
2244 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
2245 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
2246 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
2249 case OMPAllocateDeclAttr::OMPConstMemAlloc:
2252 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
2255 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
2256 llvm_unreachable(
"Expected predefined allocator for the variables with the "
2271 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
2284 llvm::raw_svector_ostream Out(Buffer);
2286 <<
" does not support unified addressing";
2287 CGM.Error(Clause->getBeginLoc(), Out.str());
2398 const char *LocSize =
"__kmpc_get_hardware_num_threads_in_block";
2399 llvm::Function *F = M->getFunction(LocSize);
2401 F = llvm::Function::Create(llvm::FunctionType::get(CGF.
Int32Ty, {},
false),
2402 llvm::GlobalVariable::ExternalLinkage, LocSize,
2405 return Bld.CreateCall(F, {},
"nvptx_num_threads");
2412 CGM.getModule(), OMPRTL___kmpc_get_hardware_thread_id_in_block),
static OffloadArch getOffloadArch(const CodeGenModule &CGM)
static void getTeamsReductionVars(ASTContext &Ctx, const OMPExecutableDirective &D, llvm::SmallVectorImpl< const ValueDecl * > &Vars)
Get list of reduction variables from the teams ... directives.
static llvm::Value * castValueToType(CodeGenFunction &CGF, llvm::Value *Val, QualType ValTy, QualType CastTy, SourceLocation Loc)
Cast value to the specified type.
static void getDistributeLastprivateVars(ASTContext &Ctx, const OMPExecutableDirective &D, llvm::SmallVectorImpl< const ValueDecl * > &Vars)
Get list of lastprivate variables from the teams distribute ... or teams {distribute ....
static bool hasNestedSPMDDirective(ASTContext &Ctx, const OMPExecutableDirective &D)
Check for inner (nested) SPMD construct, if any.
static bool supportsSPMDExecutionMode(ASTContext &Ctx, const OMPExecutableDirective &D)
This file defines OpenMP nodes for declarative directives.
This file defines OpenMP AST classes for clauses.
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, bool AllowAssumedSizeArray=false, StringRef DiagType="")
This file defines OpenMP AST classes for executable directives and clauses.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
Attr - This represents one attribute.
ArrayRef< Capture > captures() const
const BlockDecl * getBlockDecl() const
Describes the capture of either a variable, or 'this', or variable-length array type.
This captures a statement into a function.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
CastKind getCastKind() const
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
Address CreateConstArrayGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = [n x T]* ... produce name = getelementptr inbounds addr, i64 0, i64 index where i64 is a...
Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
CGFunctionInfo - Class to encapsulate the information about a function definition.
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits inlined function for the specified OpenMP teams.
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
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 reduction clause.
DataSharingMode
Target codegen is specialized based on two data-sharing modes: CUDA, in which the local variables are...
@ DS_CUDA
CUDA data sharing mode.
@ DS_Generic
Generic data-sharing mode.
void getDefaultDistScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPDistScheduleClauseKind &ScheduleKind, llvm::Value *&Chunk) const override
Choose a default value for the dist_schedule clause.
Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD) override
Gets the OpenMP-specific address of the local variable.
void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) override
Emits OpenMP-specific function prolog.
void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const override
Choose a default value for the schedule clause.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
This function ought to emit, in the general case, a call to.
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS) override
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
void getKmpcFreeShared(CodeGenFunction &CGF, const std::pair< llvm::Value *, llvm::Value * > &AddrSizePair) override
Get call to __kmpc_free_shared.
CGOpenMPRuntimeGPU(CodeGenModule &CGM)
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits inlined function for the specified OpenMP parallel.
void functionFinished(CodeGenFunction &CGF) override
Cleans up references to the objects in finished function.
llvm::Value * getGPUThreadID(CodeGenFunction &CGF)
Get the id of the current thread on the GPU.
void processRequiresDirective(const OMPRequiresDecl *D) override
Perform check on requires decl to ensure that target architecture supports unified addressing.
bool isDelayedVariableLengthDecl(CodeGenFunction &CGF, const VarDecl *VD) const override
Declare generalized virtual functions which need to be defined by all specializations of OpenMPGPURun...
void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const override
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
ExecutionMode
Defines the execution mode.
@ EM_NonSPMD
Non-SPMD execution mode (1 master thread, others are workers).
@ EM_Unknown
Unknown execution mode (orphaned directive).
@ EM_SPMD
SPMD execution mode (all threads are worker threads).
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
llvm::Value * getGPUNumThreads(CodeGenFunction &CGF)
Get the maximum number of threads in a block of the GPU.
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
std::pair< llvm::Value *, llvm::Value * > getKmpcAllocShared(CodeGenFunction &CGF, const VarDecl *VD) override
Get call to __kmpc_alloc_shared.
bool isGPU() const override
Returns true if the current target is a GPU.
llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc) override
llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc) override
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const override
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc)
Emits address of the word in a memory where current thread id is stored.
CGOpenMPRuntime(CodeGenModule &CGM)
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
llvm::Value * emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags=0, bool EmitLoc=false)
Emits object of ident_t type with info for source location.
virtual void functionFinished(CodeGenFunction &CGF)
Cleans up references to the objects in finished function.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
llvm::OpenMPIRBuilder OMPBuilder
An OpenMP-IR-Builder instance.
virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Helper to emit outlined function for 'target' directive.
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
virtual void getDefaultDistScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPDistScheduleClauseKind &ScheduleKind, llvm::Value *&Chunk) const
Choose default schedule type and chunk value for the dist_schedule clause.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
CapturedRegionKind getKind() const
bool isCXXThisExprCaptured() const
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
CGCapturedStmtInfo * CapturedStmtInfo
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
LValue MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, QualType T)
Same as MakeNaturalAlignPointeeAddrLValue except that the pointer is known to be unsigned.
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
const TargetInfo & getTarget() const
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
CGDebugInfo * getDebugInfo()
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertTypeForMem(QualType T)
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::Value * LoadCXXThis()
LoadCXXThis - Load the value of 'this'.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
llvm::LLVMContext & getLLVMContext()
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
ASTContext & getContext() const
llvm::LLVMContext & getLLVMContext()
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
unsigned getTargetAddressSpace(QualType T) const
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
Address getAddress() const
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
An abstract representation of an aligned address.
llvm::Value * getPointer() const
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void setAction(PrePostActionTy &Action) const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void addDecl(Decl *D)
Add the declaration D into this context.
attr_iterator attr_end() const
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
attr_iterator attr_begin() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Represents a member of a struct/union/class.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
GlobalDecl - represents a global declaration.
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Describes the capture of a variable or of this, or of a C++1y init-capture.
bool isInitCapture(const LambdaCapture *Capture) const
Determine whether one of this lambda's captures is an init-capture.
capture_range captures() const
Retrieve this lambda's captures.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
This is a basic class for representing single OpenMP clause.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
LangAS getAddressSpace() const
Return the address space of this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
A qualifier set is used to build a set of qualifiers.
const Type * strip(QualType type)
Collect any qualifiers on the given type and return an unqualified type.
QualType apply(const ASTContext &Context, QualType QT) const
Apply the collected qualifiers to the given type.
Represents a struct/union/class.
virtual void completeDefinition()
Note that the definition of this type is now complete.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
Stmt - This represents one statement.
void startDefinition()
Starts the definition of this tag declaration.
unsigned getNewAlign() const
Return the largest alignment for which a suitably-sized allocation with 'operator new(size_t)' is gua...
TargetOptions & getTargetOpts() const
Retrieve the target options.
virtual const llvm::omp::GV & getGridValue() const
std::string CPU
If given, the name of the target CPU to generate code for.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isReferenceType() const
bool isLValueReferenceType() const
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Expr * getSubExpr() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ Address
A pointer to a ValueDecl.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
OffloadArch StringToOffloadArch(llvm::StringRef S)
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
LangAS
Defines the address space values used by the address space qualifier of QualType.
const char * OffloadArchToString(OffloadArch A)
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
U cast(CodeGen::Address addr)
@ CXXThis
Parameter for C++ 'this' argument.
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
OpenMPDirectiveKind ReductionKind
llvm::PointerType * VoidPtrTy
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::IntegerType * Int32Ty