23#include "llvm/ADT/SmallPtrSet.h"
24#include "llvm/Frontend/OpenMP/OMPDeviceConstants.h"
25#include "llvm/Frontend/OpenMP/OMPGridValues.h"
26#include "llvm/IR/IRBuilder.h"
27#include "llvm/IR/Instructions.h"
28#include "llvm/TargetParser/NVPTXTargetParser.h"
32using namespace llvm::omp;
37 llvm::FunctionCallee EnterCallee =
nullptr;
38 ArrayRef<llvm::Value *> EnterArgs;
39 llvm::FunctionCallee ExitCallee =
nullptr;
40 ArrayRef<llvm::Value *> ExitArgs;
41 bool Conditional =
false;
42 llvm::BasicBlock *ContBlock =
nullptr;
45 NVPTXActionTy(llvm::FunctionCallee EnterCallee,
46 ArrayRef<llvm::Value *> EnterArgs,
47 llvm::FunctionCallee ExitCallee,
48 ArrayRef<llvm::Value *> ExitArgs,
bool Conditional =
false)
49 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
50 ExitArgs(ExitArgs), Conditional(Conditional) {}
51 void Enter(CodeGenFunction &CGF)
override {
54 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
58 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
62 void Done(CodeGenFunction &CGF) {
67 void Exit(CodeGenFunction &CGF)
override {
76class ExecutionRuntimeModesRAII {
85 : ExecMode(ExecMode) {
86 SavedExecMode = ExecMode;
89 ~ExecutionRuntimeModesRAII() { ExecMode = SavedExecMode; }
94 if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr)) {
95 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
96 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
97 Base = TempASE->getBase()->IgnoreParenImpCasts();
99 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr)) {
100 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
101 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
102 Base = TempOASE->getBase()->IgnoreParenImpCasts();
103 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
104 Base = TempASE->getBase()->IgnoreParenImpCasts();
108 if (
const auto *DE = dyn_cast<DeclRefExpr>(RefExpr))
114static RecordDecl *buildRecordForGlobalizedVars(
117 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
121 if (EscapedDecls.empty() && EscapedDeclsForTeams.empty())
125 GlobalizedVars.emplace_back(
C.getDeclAlign(D), D);
126 for (
const ValueDecl *D : EscapedDeclsForTeams)
127 GlobalizedVars.emplace_back(
C.getDeclAlign(D), D);
133 RecordDecl *GlobalizedRD =
C.buildImplicitRecord(
"_globalized_locals_ty");
136 EscapedDeclsForTeams);
137 for (
const auto &Pair : GlobalizedVars) {
141 Type =
C.getPointerType(
Type.getNonReferenceType());
146 if (SingleEscaped.count(VD)) {
161 llvm::APInt ArraySize(32, BufSize);
162 Type =
C.getConstantArrayType(
Type, ArraySize,
nullptr,
171 llvm::APInt Align(32, Pair.first.getQuantity());
172 Field->addAttr(AlignedAttr::CreateImplicit(
175 C.getIntTypeForBitwidth(32, 0),
177 {}, AlignedAttr::GNU_aligned));
180 MappedDeclsFields.try_emplace(VD, Field);
187class CheckVarsEscapingDeclContext final
189 CodeGenFunction &CGF;
190 llvm::SetVector<const ValueDecl *> EscapedDecls;
191 llvm::SetVector<const ValueDecl *> EscapedVariableLengthDecls;
192 llvm::SetVector<const ValueDecl *> DelayedVariableLengthDecls;
193 llvm::SmallPtrSet<const Decl *, 4> EscapedParameters;
194 RecordDecl *GlobalizedRD =
nullptr;
195 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> MappedDeclsFields;
196 bool AllEscaped =
false;
197 bool IsForCombinedParallelRegion =
false;
199 void markAsEscaped(
const ValueDecl *VD) {
202 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
209 bool IsCaptured =
false;
210 if (
auto *CSI = CGF.CapturedStmtInfo) {
215 if (!IsForCombinedParallelRegion) {
218 const auto *Attr = FD->getAttr<OMPCaptureKindAttr>();
221 if (((Attr->getCaptureKind() != OMPC_map) &&
223 ((Attr->getCaptureKind() == OMPC_map) &&
224 !FD->getType()->isAnyPointerType()))
227 if (!FD->getType()->isReferenceType()) {
229 "Parameter captured by value with variably modified type");
230 EscapedParameters.insert(VD);
231 }
else if (!IsForCombinedParallelRegion) {
236 if ((!CGF.CapturedStmtInfo ||
237 (IsForCombinedParallelRegion && CGF.CapturedStmtInfo)) &&
245 EscapedVariableLengthDecls.insert(VD);
247 DelayedVariableLengthDecls.insert(VD);
249 EscapedDecls.insert(VD);
252 void VisitValueDecl(
const ValueDecl *VD) {
255 if (
const auto *VarD = dyn_cast<VarDecl>(VD)) {
257 const bool SavedAllEscaped = AllEscaped;
259 Visit(VarD->getInit());
260 AllEscaped = SavedAllEscaped;
264 void VisitOpenMPCapturedStmt(
const CapturedStmt *S,
265 ArrayRef<OMPClause *> Clauses,
266 bool IsCombinedParallelRegion) {
269 for (
const CapturedStmt::Capture &
C : S->
captures()) {
270 if (
C.capturesVariable() && !
C.capturesVariableByCopy()) {
271 const ValueDecl *VD =
C.getCapturedVar();
272 bool SavedIsForCombinedParallelRegion = IsForCombinedParallelRegion;
273 if (IsCombinedParallelRegion) {
277 IsForCombinedParallelRegion =
false;
278 for (
const OMPClause *
C : Clauses) {
280 C->getClauseKind() == OMPC_reduction ||
281 C->getClauseKind() == OMPC_linear ||
282 C->getClauseKind() == OMPC_private)
284 ArrayRef<const Expr *> Vars;
285 if (
const auto *PC = dyn_cast<OMPFirstprivateClause>(
C))
286 Vars = PC->getVarRefs();
287 else if (
const auto *PC = dyn_cast<OMPLastprivateClause>(
C))
288 Vars = PC->getVarRefs();
290 llvm_unreachable(
"Unexpected clause.");
291 for (
const auto *E : Vars) {
295 IsForCombinedParallelRegion =
true;
299 if (IsForCombinedParallelRegion)
306 IsForCombinedParallelRegion = SavedIsForCombinedParallelRegion;
311 void buildRecordForGlobalizedVars(
bool IsInTTDRegion) {
312 assert(!GlobalizedRD &&
313 "Record for globalized variables is built already.");
314 ArrayRef<const ValueDecl *> EscapedDeclsForParallel, EscapedDeclsForTeams;
315 unsigned WarpSize = CGF.getTarget().getGridValue().GV_Warp_Size;
317 EscapedDeclsForTeams = EscapedDecls.getArrayRef();
319 EscapedDeclsForParallel = EscapedDecls.getArrayRef();
320 GlobalizedRD = ::buildRecordForGlobalizedVars(
321 CGF.getContext(), EscapedDeclsForParallel, EscapedDeclsForTeams,
322 MappedDeclsFields, WarpSize);
326 CheckVarsEscapingDeclContext(CodeGenFunction &CGF,
327 ArrayRef<const ValueDecl *> TeamsReductions)
328 : CGF(CGF), EscapedDecls(llvm::from_range, TeamsReductions) {}
329 ~CheckVarsEscapingDeclContext() =
default;
330 void VisitDeclStmt(
const DeclStmt *S) {
334 if (
const auto *VD = dyn_cast_or_null<ValueDecl>(D))
337 void VisitOMPExecutableDirective(
const OMPExecutableDirective *D) {
340 if (!D->hasAssociatedStmt())
343 dyn_cast_or_null<CapturedStmt>(D->getAssociatedStmt())) {
346 llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
348 if (CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown) {
349 VisitStmt(S->getCapturedStmt());
352 VisitOpenMPCapturedStmt(
354 CaptureRegions.back() == OMPD_parallel &&
358 void VisitCapturedStmt(
const CapturedStmt *S) {
361 for (
const CapturedStmt::Capture &
C : S->
captures()) {
362 if (
C.capturesVariable() && !
C.capturesVariableByCopy()) {
363 const ValueDecl *VD =
C.getCapturedVar();
373 for (
const LambdaCapture &
C : E->
captures()) {
374 if (
C.capturesVariable()) {
376 const ValueDecl *VD =
C.getCapturedVar();
384 void VisitBlockExpr(
const BlockExpr *E) {
389 const VarDecl *VD =
C.getVariable();
396 void VisitCallExpr(
const CallExpr *E) {
402 if (Arg->isLValue()) {
403 const bool SavedAllEscaped = AllEscaped;
406 AllEscaped = SavedAllEscaped;
413 void VisitDeclRefExpr(
const DeclRefExpr *E) {
416 const ValueDecl *VD = E->
getDecl();
424 void VisitUnaryOperator(
const UnaryOperator *E) {
428 const bool SavedAllEscaped = AllEscaped;
431 AllEscaped = SavedAllEscaped;
436 void VisitImplicitCastExpr(
const ImplicitCastExpr *E) {
440 const bool SavedAllEscaped = AllEscaped;
443 AllEscaped = SavedAllEscaped;
448 void VisitExpr(
const Expr *E) {
451 bool SavedAllEscaped = AllEscaped;
454 for (
const Stmt *Child : E->
children())
457 AllEscaped = SavedAllEscaped;
459 void VisitStmt(
const Stmt *S) {
462 for (
const Stmt *Child : S->
children())
469 const RecordDecl *getGlobalizedRecord(
bool IsInTTDRegion) {
471 buildRecordForGlobalizedVars(IsInTTDRegion);
476 const FieldDecl *getFieldForGlobalizedVar(
const ValueDecl *VD)
const {
477 assert(GlobalizedRD &&
478 "Record for globalized variables must be generated already.");
479 return MappedDeclsFields.lookup(VD);
483 ArrayRef<const ValueDecl *> getEscapedDecls()
const {
484 return EscapedDecls.getArrayRef();
489 const llvm::SmallPtrSetImpl<const Decl *> &getEscapedParameters()
const {
490 return EscapedParameters;
495 ArrayRef<const ValueDecl *> getEscapedVariableLengthDecls()
const {
496 return EscapedVariableLengthDecls.getArrayRef();
501 ArrayRef<const ValueDecl *> getDelayedVariableLengthDecls()
const {
502 return DelayedVariableLengthDecls.getArrayRef();
508CGOpenMPRuntimeGPU::getExecutionMode()
const {
509 return CurrentExecutionMode;
513CGOpenMPRuntimeGPU::getDataSharingMode()
const {
514 return CurrentDataSharingMode;
520 const auto *CS = D.getInnermostCapturedStmt();
522 CS->getCapturedStmt()->IgnoreContainers(
true);
525 if (
const auto *NestedDir =
526 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
528 switch (D.getDirectiveKind()) {
532 if (DKind == OMPD_teams) {
533 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
538 if (
const auto *NND =
539 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
540 DKind = NND->getDirectiveKind();
546 case OMPD_target_teams:
548 case OMPD_target_simd:
549 case OMPD_target_parallel:
550 case OMPD_target_parallel_for:
551 case OMPD_target_parallel_for_simd:
552 case OMPD_target_teams_distribute:
553 case OMPD_target_teams_distribute_simd:
554 case OMPD_target_teams_distribute_parallel_for:
555 case OMPD_target_teams_distribute_parallel_for_simd:
558 case OMPD_parallel_for:
559 case OMPD_parallel_master:
560 case OMPD_parallel_sections:
562 case OMPD_parallel_for_simd:
564 case OMPD_cancellation_point:
565 case OMPD_ordered_standalone:
566 case OMPD_ordered_blockassoc:
567 case OMPD_threadprivate:
585 case OMPD_target_data:
586 case OMPD_target_exit_data:
587 case OMPD_target_enter_data:
588 case OMPD_distribute:
589 case OMPD_distribute_simd:
590 case OMPD_distribute_parallel_for:
591 case OMPD_distribute_parallel_for_simd:
592 case OMPD_teams_distribute:
593 case OMPD_teams_distribute_simd:
594 case OMPD_teams_distribute_parallel_for:
595 case OMPD_teams_distribute_parallel_for_simd:
596 case OMPD_target_update:
597 case OMPD_declare_simd:
598 case OMPD_declare_variant:
599 case OMPD_begin_declare_variant:
600 case OMPD_end_declare_variant:
601 case OMPD_declare_target:
602 case OMPD_end_declare_target:
603 case OMPD_declare_reduction:
604 case OMPD_declare_mapper:
606 case OMPD_taskloop_simd:
607 case OMPD_master_taskloop:
608 case OMPD_master_taskloop_simd:
609 case OMPD_parallel_master_taskloop:
610 case OMPD_parallel_master_taskloop_simd:
614 llvm_unreachable(
"Unexpected directive.");
624 switch (DirectiveKind) {
626 case OMPD_target_teams:
628 case OMPD_target_parallel_loop:
629 case OMPD_target_parallel:
630 case OMPD_target_parallel_for:
631 case OMPD_target_parallel_for_simd:
632 case OMPD_target_teams_distribute_parallel_for:
633 case OMPD_target_teams_distribute_parallel_for_simd:
634 case OMPD_target_simd:
635 case OMPD_target_teams_distribute_simd:
637 case OMPD_target_teams_distribute:
639 case OMPD_target_teams_loop:
642 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
643 return TTLD->canBeParallelFor();
647 case OMPD_parallel_for:
648 case OMPD_parallel_master:
649 case OMPD_parallel_sections:
651 case OMPD_parallel_for_simd:
653 case OMPD_cancellation_point:
654 case OMPD_ordered_standalone:
655 case OMPD_ordered_blockassoc:
656 case OMPD_threadprivate:
674 case OMPD_target_data:
675 case OMPD_target_exit_data:
676 case OMPD_target_enter_data:
677 case OMPD_distribute:
678 case OMPD_distribute_simd:
679 case OMPD_distribute_parallel_for:
680 case OMPD_distribute_parallel_for_simd:
681 case OMPD_teams_distribute:
682 case OMPD_teams_distribute_simd:
683 case OMPD_teams_distribute_parallel_for:
684 case OMPD_teams_distribute_parallel_for_simd:
685 case OMPD_target_update:
686 case OMPD_declare_simd:
687 case OMPD_declare_variant:
688 case OMPD_begin_declare_variant:
689 case OMPD_end_declare_variant:
690 case OMPD_declare_target:
691 case OMPD_end_declare_target:
692 case OMPD_declare_reduction:
693 case OMPD_declare_mapper:
695 case OMPD_taskloop_simd:
696 case OMPD_master_taskloop:
697 case OMPD_master_taskloop_simd:
698 case OMPD_parallel_master_taskloop:
699 case OMPD_parallel_master_taskloop_simd:
706 "Unknown programming model for OpenMP directive on NVPTX target.");
709void CGOpenMPRuntimeGPU::emitNonSPMDKernel(
const OMPExecutableDirective &D,
710 StringRef ParentName,
711 llvm::Function *&OutlinedFn,
712 llvm::Constant *&OutlinedFnID,
715 ExecutionRuntimeModesRAII ModeRAII(CurrentExecutionMode,
EM_NonSPMD);
716 EntryFunctionState EST;
717 WrapperFunctionsMap.clear();
719 [[maybe_unused]]
bool IsBareKernel = D.getSingleClause<OMPXBareClause>();
720 assert(!IsBareKernel &&
"bare kernel should not be at generic mode");
723 class NVPTXPrePostActionTy :
public PrePostActionTy {
724 CGOpenMPRuntimeGPU::EntryFunctionState &EST;
725 const OMPExecutableDirective &D;
728 NVPTXPrePostActionTy(CGOpenMPRuntimeGPU::EntryFunctionState &EST,
729 const OMPExecutableDirective &D)
731 void Enter(CodeGenFunction &CGF)
override {
733 RT.emitKernelInit(D, CGF, EST,
false);
735 RT.setLocThreadIdInsertPt(CGF,
true);
737 void Exit(CodeGenFunction &CGF)
override {
739 RT.clearLocThreadIdInsertPt(CGF);
740 RT.emitKernelDeinit(CGF, EST,
false);
744 IsInTTDRegion =
true;
746 IsOffloadEntry, CodeGen);
747 IsInTTDRegion =
false;
750void CGOpenMPRuntimeGPU::emitBareKernelEnvironment(
756 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs Attrs;
757 Attrs.ExecFlags = llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_BARE;
758 CGBuilderTy &Bld = CGF.
Builder;
762void CGOpenMPRuntimeGPU::emitKernelInit(
const OMPExecutableDirective &D,
764 EntryFunctionState &EST,
bool IsSPMD) {
765 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs Attrs;
767 IsSPMD ? llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_SPMD
768 : llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_GENERIC;
771 CGBuilderTy &Bld = CGF.
Builder;
772 Bld.restoreIP(
OMPBuilder.createTargetInit(Bld, Attrs));
774 emitGenericVarsProlog(CGF, EST.Loc);
778 EntryFunctionState &EST,
781 emitGenericVarsEpilog(CGF);
784 ASTContext &
C =
CGM.getContext();
785 RecordDecl *StaticRD =
C.buildImplicitRecord(
786 "_openmp_teams_reduction_type_$_", RecordDecl::TagKind::Union);
788 for (
const RecordDecl *TeamReductionRec : TeamsReductions) {
789 CanQualType RecTy =
C.getCanonicalTagType(TeamReductionRec);
791 C, StaticRD, SourceLocation(), SourceLocation(),
nullptr, RecTy,
792 C.getTrivialTypeSourceInfo(RecTy, SourceLocation()),
800 llvm::Type *LLVMReductionsBufferTy =
801 CGM.getTypes().ConvertTypeForMem(StaticTy);
802 const auto &DL =
CGM.getModule().getDataLayout();
804 TeamsReductions.empty()
806 : DL.getTypeAllocSize(LLVMReductionsBufferTy).getFixedValue();
807 CGBuilderTy &Bld = CGF.
Builder;
808 OMPBuilder.createTargetDeinit(Bld, ReductionDataSize);
809 TeamsReductions.clear();
812void CGOpenMPRuntimeGPU::emitSPMDKernel(
const OMPExecutableDirective &D,
813 StringRef ParentName,
814 llvm::Function *&OutlinedFn,
815 llvm::Constant *&OutlinedFnID,
818 ExecutionRuntimeModesRAII ModeRAII(CurrentExecutionMode,
EM_SPMD);
819 EntryFunctionState EST;
821 bool IsBareKernel = D.getSingleClause<OMPXBareClause>();
824 class NVPTXPrePostActionTy :
public PrePostActionTy {
825 CGOpenMPRuntimeGPU &RT;
826 CGOpenMPRuntimeGPU::EntryFunctionState &EST;
828 DataSharingMode Mode;
829 const OMPExecutableDirective &D;
832 NVPTXPrePostActionTy(CGOpenMPRuntimeGPU &RT,
833 CGOpenMPRuntimeGPU::EntryFunctionState &EST,
834 bool IsBareKernel,
const OMPExecutableDirective &D)
835 : RT(RT), EST(EST), IsBareKernel(IsBareKernel),
836 Mode(RT.CurrentDataSharingMode), D(D) {}
837 void Enter(CodeGenFunction &CGF)
override {
839 RT.CurrentDataSharingMode = DataSharingMode::DS_CUDA;
840 RT.emitBareKernelEnvironment(D, CGF);
843 RT.emitKernelInit(D, CGF, EST,
true);
845 RT.setLocThreadIdInsertPt(CGF,
true);
847 void Exit(CodeGenFunction &CGF)
override {
849 RT.CurrentDataSharingMode = Mode;
852 RT.clearLocThreadIdInsertPt(CGF);
853 RT.emitKernelDeinit(CGF, EST,
true);
855 } Action(*
this, EST, IsBareKernel, D);
857 IsInTTDRegion =
true;
859 IsOffloadEntry, CodeGen);
860 IsInTTDRegion =
false;
863void CGOpenMPRuntimeGPU::emitTargetOutlinedFunction(
864 const OMPExecutableDirective &D, StringRef ParentName,
865 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
870 assert(!ParentName.empty() &&
"Invalid target region parent name!");
873 bool IsBareKernel = D.getSingleClause<OMPXBareClause>();
874 if (Mode || IsBareKernel)
875 emitSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry,
878 emitNonSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry,
884 llvm::OpenMPIRBuilderConfig Config(
885 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
886 CGM.getLangOpts().OpenMPOffloadMandatory,
889 Config.setDefaultTargetAS(
891 Config.setRuntimeCC(
CGM.getRuntimeCC());
895 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
896 llvm_unreachable(
"OpenMP can only handle device code.");
898 if (
CGM.getLangOpts().OpenMPCUDAMode)
902 if (
CGM.getLangOpts().NoGPULib ||
CGM.getLangOpts().OMPHostIRFile.empty())
905 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPTargetDebug,
906 "__omp_rtl_debug_kind");
907 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPTeamSubscription,
908 "__omp_rtl_assume_teams_oversubscription");
909 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPThreadSubscription,
910 "__omp_rtl_assume_threads_oversubscription");
911 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPNoThreadState,
912 "__omp_rtl_assume_no_thread_state");
913 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPNoNestedParallelism,
914 "__omp_rtl_assume_no_nested_parallelism");
918 ProcBindKind ProcBind,
926 CGM.getDiags().Report(Loc, diag::warn_omp_gpu_unsupported_clause)
927 << getOpenMPClauseName(OMPC_message);
934 CGM.getDiags().Report(Loc, diag::warn_omp_gpu_unsupported_clause)
935 << getOpenMPClauseName(OMPC_severity);
944 if (Modifier == OMPC_NUMTHREADS_strict) {
945 CGM.getDiags().Report(Loc,
946 diag::warn_omp_gpu_unsupported_modifier_for_clause)
947 <<
"strict" << getOpenMPClauseName(OMPC_num_threads);
955 const Expr *NumTeams,
956 const Expr *ThreadLimit,
964 bool PrevIsInTTDRegion = IsInTTDRegion;
965 IsInTTDRegion =
false;
968 CGF, D, ThreadIDVar, InnermostKind,
CodeGen));
969 IsInTTDRegion = PrevIsInTTDRegion;
971 llvm::Function *WrapperFun =
972 createParallelDataSharingWrapper(OutlinedFun, D);
973 WrapperFunctionsMap[OutlinedFun] = WrapperFun;
985 "expected teams directive.");
990 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(
992 Dir = dyn_cast_or_null<OMPExecutableDirective>(S);
999 for (
const auto *
C : Dir->getClausesOfKind<OMPLastprivateClause>()) {
1000 for (
const Expr *E :
C->getVarRefs())
1010 "expected teams directive.");
1011 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1012 for (
const Expr *E :
C->privates())
1025 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> MappedDeclsFields;
1026 unsigned WarpSize =
CGM.getTarget().getGridValue().GV_Warp_Size;
1032 if (!LastPrivatesReductions.empty()) {
1033 GlobalizedRD = ::buildRecordForGlobalizedVars(
1034 CGM.getContext(), {}, LastPrivatesReductions, MappedDeclsFields,
1037 }
else if (!LastPrivatesReductions.empty()) {
1038 assert(!TeamAndReductions.first &&
1039 "Previous team declaration is not expected.");
1040 TeamAndReductions.first = D.getCapturedStmt(OMPD_teams)->getCapturedDecl();
1041 std::swap(TeamAndReductions.second, LastPrivatesReductions);
1048 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
1052 NVPTXPrePostActionTy(
1054 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
1056 : Loc(Loc), GlobalizedRD(GlobalizedRD),
1057 MappedDeclsFields(MappedDeclsFields) {}
1062 auto I = Rt.FunctionGlobalizedDecls.try_emplace(CGF.
CurFn).first;
1063 I->getSecond().MappedParams =
1064 std::make_unique<CodeGenFunction::OMPMapVars>();
1065 DeclToAddrMapTy &
Data = I->getSecond().LocalVarData;
1066 for (
const auto &Pair : MappedDeclsFields) {
1067 assert(Pair.getFirst()->isCanonicalDecl() &&
1068 "Expected canonical declaration");
1069 Data.try_emplace(Pair.getFirst());
1072 Rt.emitGenericVarsProlog(CGF, Loc);
1076 .emitGenericVarsEpilog(CGF);
1078 } Action(Loc, GlobalizedRD, MappedDeclsFields);
1081 CGF, D, ThreadIDVar, InnermostKind,
CodeGen);
1093 const auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
1094 if (I == FunctionGlobalizedDecls.end())
1097 for (
auto &Rec : I->getSecond().LocalVarData) {
1099 bool EscapedParam = I->getSecond().EscapedParameters.count(Rec.first);
1103 llvm::Value *ParValue;
1112 llvm::CallBase *VoidPtr =
1117 VoidPtr->addRetAttr(llvm::Attribute::get(
1123 VoidPtr, Bld.getPtrTy(0), VD->
getName() +
"_on_stack");
1126 Rec.second.PrivateAddr = VarAddr.getAddress();
1127 Rec.second.GlobalizedVal = VoidPtr;
1132 I->getSecond().MappedParams->setVarAddr(CGF, VD, VarAddr.getAddress());
1135 VoidPtr->setDebugLoc(DI->SourceLocToDebugLoc(VD->
getLocation()));
1138 for (
const auto *ValueD : I->getSecond().EscapedVariableLengthDecls) {
1140 std::pair<llvm::Value *, llvm::Value *> AddrSizePair =
1142 I->getSecond().EscapedVariableLengthDeclsAddrs.emplace_back(AddrSizePair);
1144 CGM.getContext().getDeclAlign(VD),
1146 I->getSecond().MappedParams->setVarAddr(CGF, VD,
Base.getAddress());
1148 I->getSecond().MappedParams->apply(CGF);
1153 const auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
1154 if (I == FunctionGlobalizedDecls.end())
1158 return llvm::is_contained(I->getSecond().DelayedVariableLengthDecls, VD);
1161std::pair<llvm::Value *, llvm::Value *>
1169 Size = Bld.CreateNUWAdd(
1171 llvm::Value *AlignVal =
1173 Size = Bld.CreateUDiv(Size, AlignVal);
1174 Size = Bld.CreateNUWMul(Size, AlignVal);
1177 llvm::Value *AllocArgs[] = {Size};
1178 llvm::CallBase *VoidPtr =
1180 CGM.getModule(), OMPRTL___kmpc_alloc_shared),
1182 VoidPtr->addRetAttr(llvm::Attribute::get(
1183 CGM.getLLVMContext(), llvm::Attribute::Alignment, Align.
getQuantity()));
1185 return std::make_pair(VoidPtr, Size);
1190 const std::pair<llvm::Value *, llvm::Value *> &AddrSizePair) {
1193 CGM.getModule(), OMPRTL___kmpc_free_shared),
1194 {AddrSizePair.first, AddrSizePair.second});
1201 const auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
1202 if (I != FunctionGlobalizedDecls.end()) {
1205 for (
const auto &AddrSizePair :
1206 llvm::reverse(I->getSecond().EscapedVariableLengthDeclsAddrs)) {
1209 {AddrSizePair.first, AddrSizePair.second});
1212 for (
auto &Rec : llvm::reverse(I->getSecond().LocalVarData)) {
1214 I->getSecond().MappedParams->restore(CGF);
1216 llvm::Value *FreeArgs[] = {Rec.second.GlobalizedVal,
1228 llvm::Function *OutlinedFn,
1242 OutlinedFnArgs.push_back(llvm::ConstantPointerNull::get(
CGM.VoidPtrTy));
1245 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1246 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
1258 auto &&ParallelGen = [
this, Loc, OutlinedFn, CapturedVars, IfCond,
1262 llvm::Value *NumThreadsVal = NumThreads;
1263 llvm::Function *WFn = WrapperFunctionsMap[OutlinedFn];
1264 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1267 llvm::Value *ID = llvm::ConstantPointerNull::get(FnPtrTy);
1269 ID = Bld.CreateBitOrPointerCast(WFn, FnPtrTy);
1271 llvm::Value *FnPtr = Bld.CreateBitOrPointerCast(OutlinedFn, FnPtrTy);
1279 llvm::ArrayType::get(
CGM.VoidPtrTy, CapturedVars.size()),
1280 "captured_vars_addrs");
1282 if (!CapturedVars.empty()) {
1286 for (llvm::Value *
V : CapturedVars) {
1289 if (
V->getType()->isIntegerTy())
1299 llvm::Value *IfCondVal =
nullptr;
1304 IfCondVal = llvm::ConstantInt::get(CGF.
Int32Ty, 1);
1307 NumThreadsVal = llvm::ConstantInt::getAllOnesValue(CGF.
Int32Ty);
1309 NumThreadsVal = Bld.CreateZExtOrTrunc(NumThreadsVal, CGF.
Int32Ty);
1312 llvm::Value *StrictNumThreadsVal = llvm::ConstantInt::get(CGF.
Int32Ty, 0);
1314 assert(IfCondVal &&
"Expected a value");
1316 llvm::Value *Args[] = {
1321 llvm::ConstantInt::getAllOnesValue(CGF.
Int32Ty),
1324 Bld.CreateBitOrPointerCast(CapturedVarsAddrs.
emitRawPointer(CGF),
1326 llvm::ConstantInt::get(
CGM.SizeTy, CapturedVars.size()),
1327 StrictNumThreadsVal};
1330 CGM.getModule(), OMPRTL___kmpc_parallel_60),
1344 llvm::Value *Args[] = {
1345 llvm::ConstantPointerNull::get(
1347 llvm::ConstantInt::get(CGF.
Int32Ty, 0,
true)};
1366 CGM.getModule(), OMPRTL___kmpc_barrier),
1384 CGM.getModule(), OMPRTL___kmpc_warp_active_thread_mask));
1386 llvm::Value *ThreadID = RT.getGPUThreadID(CGF);
1389 llvm::Value *TeamWidth = RT.getGPUNumThreads(CGF);
1402 llvm::Value *CmpLoopBound = CGF.
Builder.CreateICmpSLT(CounterVal, TeamWidth);
1403 CGF.
Builder.CreateCondBr(CmpLoopBound, TestBB, ExitBB);
1409 llvm::Value *CmpThreadToCounter =
1410 CGF.
Builder.CreateICmpEQ(ThreadID, CounterVal);
1411 CGF.
Builder.CreateCondBr(CmpThreadToCounter, BodyBB, SyncBB);
1427 CGM.getModule(), OMPRTL___kmpc_syncwarp),
1430 llvm::Value *IncCounterVal =
1444 "Cast type must sized.");
1446 "Val type must sized.");
1448 if (ValTy == CastTy)
1452 return CGF.
Builder.CreateBitCast(Val, LLVMCastTy);
1454 return CGF.
Builder.CreateIntCast(Val, LLVMCastTy,
1469static std::optional<BinaryOperatorKind>
1471 const auto *Assign = dyn_cast<BinaryOperator>(ReductionOp);
1472 if (!Assign || Assign->getOpcode() != BO_Assign)
1473 return std::nullopt;
1474 const Expr *RHS = Assign->getRHS();
1477 if (
const auto *ACO =
1479 RHS = ACO->getCond();
1481 return BO->getOpcode();
1482 return std::nullopt;
1488static std::optional<llvm::AtomicRMWInst::BinOp>
1496 return llvm::AtomicRMWInst::Add;
1498 return llvm::AtomicRMWInst::FAdd;
1499 return std::nullopt;
1501 return IsInt ? std::optional(llvm::AtomicRMWInst::And) : std::nullopt;
1503 return IsInt ? std::optional(llvm::AtomicRMWInst::Or) : std::nullopt;
1505 return IsInt ? std::optional(llvm::AtomicRMWInst::Xor) : std::nullopt;
1508 return IsSigned ? llvm::AtomicRMWInst::Min : llvm::AtomicRMWInst::UMin;
1509 return std::nullopt;
1512 return IsSigned ? llvm::AtomicRMWInst::Max : llvm::AtomicRMWInst::UMax;
1513 return std::nullopt;
1515 return std::nullopt;
1772 assert(!TeamsReduction && !ParallelReduction &&
1773 "Invalid reduction selection in emitReduction.");
1774 (void)ParallelReduction;
1776 ReductionOps, Options);
1780 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> VarFieldMap;
1787 const RecordDecl *ReductionRec = ::buildRecordForGlobalizedVars(
1788 CGM.getContext(), PrivatesReductions, {}, VarFieldMap, 1);
1794 bool UseAtomicReduction =
1795 TeamsReduction &&
CGM.getLangOpts().OpenMPTargetAtomicReduction;
1796 bool AllAtomicable = UseAtomicReduction;
1801 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1804 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
1805 CGF.
Builder.GetInsertPoint());
1806 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(
1813 llvm::Type *ElementType;
1814 llvm::Value *Variable;
1815 llvm::Value *PrivateVariable;
1816 llvm::OpenMPIRBuilder::ReductionGenAtomicCBTy AtomicReductionGen =
nullptr;
1818 const auto *RHSVar =
1821 const auto *LHSVar =
1824 llvm::OpenMPIRBuilder::EvalKind EvalKind;
1827 EvalKind = llvm::OpenMPIRBuilder::EvalKind::Scalar;
1830 EvalKind = llvm::OpenMPIRBuilder::EvalKind::Complex;
1833 EvalKind = llvm::OpenMPIRBuilder::EvalKind::Aggregate;
1836 auto ReductionGen = [&](InsertPointTy CodeGenIP,
unsigned I,
1837 llvm::Value **LHSPtr, llvm::Value **RHSPtr,
1838 llvm::Function *NewFunc) {
1839 CGF.
Builder.restoreIP(CodeGenIP);
1840 auto *CurFn = CGF.
CurFn;
1841 CGF.
CurFn = NewFunc;
1846 llvm::DebugLoc SavedDebugLoc = CGF.
Builder.getCurrentDebugLocation();
1847 CGF.
Builder.SetCurrentDebugLocation(llvm::DebugLoc());
1862 CGF.
Builder.SetCurrentDebugLocation(SavedDebugLoc);
1865 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
1866 CGF.
Builder.GetInsertPoint());
1872 if (UseAtomicReduction) {
1873 std::optional<llvm::AtomicRMWInst::BinOp> AtomicOp;
1874 if (EvalKind == llvm::OpenMPIRBuilder::EvalKind::Scalar) {
1875 if (std::optional<BinaryOperatorKind> BOK =
1880 AllAtomicable =
false;
1882 llvm::AtomicRMWInst::BinOp Op = *AtomicOp;
1883 llvm::Align Alignment =
1884 CGM.getModule().getDataLayout().getPrefTypeAlign(ElementType);
1893 AtomicReductionGen = [Op, Alignment,
1894 SSID](InsertPointTy IP, llvm::Type *EltTy,
1895 llvm::Value *LHS, llvm::Value *RHS)
1896 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1897 llvm::IRBuilder<> Builder(IP.getBlock(), IP.getPoint());
1898 llvm::Value *Val = Builder.CreateLoad(EltTy, RHS);
1899 Builder.CreateAtomicRMW(Op, LHS, Val, Alignment,
1900 llvm::AtomicOrdering::Monotonic, SSID);
1901 return InsertPointTy(Builder.GetInsertBlock(),
1902 Builder.GetInsertPoint());
1907 ReductionInfos.emplace_back(llvm::OpenMPIRBuilder::ReductionInfo(
1908 ElementType, Variable, PrivateVariable, EvalKind,
1909 nullptr, ReductionGen, AtomicReductionGen,
1916 if (TeamsReduction && !AllAtomicable)
1917 TeamsReductions.push_back(ReductionRec);
1920 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
1922 OmpLoc, AllocaIP, CodeGenIP, ReductionInfos, {},
false,
1923 TeamsReduction, IsSPMD,
1924 llvm::OpenMPIRBuilder::ReductionGenCBKind::Clang,
1926 CGF.
Builder.restoreIP(AfterIP);
1931 const VarDecl *NativeParam)
const {
1938 if (
const auto *
Attr = FD->
getAttr<OMPCaptureKindAttr>()) {
1939 if (
Attr->getCaptureKind() == OMPC_map) {
1940 PointeeTy =
CGM.getContext().getAddrSpaceQualType(PointeeTy,
1944 ArgType =
CGM.getContext().getPointerType(PointeeTy);
1962 const VarDecl *TargetParam)
const {
1963 assert(NativeParam != TargetParam &&
1965 "Native arg must not be the same as target arg.");
1969 const Type *NonQualTy = QC.
strip(NativeParamType);
1971 unsigned NativePointeeAddrSpace =
1979 llvm::PointerType::get(CGF.
getLLVMContext(), NativePointeeAddrSpace));
1983 return NativeParamAddr;
1990 TargetArgs.reserve(Args.size());
1991 auto *FnType = OutlinedFn.getFunctionType();
1992 for (
unsigned I = 0, E = Args.size(); I < E; ++I) {
1993 if (FnType->isVarArg() && FnType->getNumParams() <= I) {
1994 TargetArgs.append(std::next(Args.begin(), I), Args.end());
1997 llvm::Type *TargetType = FnType->getParamType(I);
1998 llvm::Value *NativeArg = Args[I];
1999 if (!TargetType->isPointerTy()) {
2000 TargetArgs.emplace_back(NativeArg);
2003 TargetArgs.emplace_back(
2013llvm::Function *CGOpenMPRuntimeGPU::createParallelDataSharingWrapper(
2016 const auto &CS = *D.getCapturedStmt(OMPD_parallel);
2025 Ctx,
nullptr, D.getBeginLoc(),
2028 Ctx,
nullptr, D.getBeginLoc(),
2030 WrapperArgs.emplace_back(ParallelLevelArg);
2031 WrapperArgs.emplace_back(WrapperArg);
2036 auto *Fn = llvm::Function::Create(
2038 Twine(OutlinedParallelFn->getName(),
"_wrapper"), &
CGM.
getModule());
2046 Fn->addFnAttr(llvm::Attribute::NoInline);
2049 Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
2053 D.getBeginLoc(), D.getBeginLoc());
2055 const auto *RD = CS.getCapturedRecordDecl();
2056 auto CurField = RD->field_begin();
2068 auto CI = CS.capture_begin();
2074 llvm::Value *GlobalArgsPtr = GlobalArgs.
getPointer();
2075 llvm::Value *DataSharingArgs[] = {GlobalArgsPtr};
2083 if (CS.capture_size() > 0 ||
2094 Src, Bld.getPtrTy(0), CGF.
SizeTy);
2100 Args.emplace_back(LB);
2110 Args.emplace_back(UB);
2113 if (CS.capture_size() > 0) {
2115 for (
unsigned I = 0, E = CS.capture_size(); I < E; ++I, ++CI, ++CurField) {
2116 QualType ElemTy = CurField->getType();
2125 if (CI->capturesVariableByCopy() &&
2126 !CI->getCapturedVar()->getType()->isAnyPointerType()) {
2130 Args.emplace_back(Arg);
2144 assert(D &&
"Expected function or captured|block decl.");
2145 assert(FunctionGlobalizedDecls.count(CGF.
CurFn) == 0 &&
2146 "Function is registered already.");
2147 assert((!TeamAndReductions.first || TeamAndReductions.first == D) &&
2148 "Team is set but not processed.");
2149 const Stmt *Body =
nullptr;
2150 bool NeedToDelayGlobalization =
false;
2151 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
2152 Body = FD->getBody();
2153 }
else if (
const auto *BD = dyn_cast<BlockDecl>(D)) {
2154 Body = BD->getBody();
2155 }
else if (
const auto *CD = dyn_cast<CapturedDecl>(D)) {
2156 Body = CD->getBody();
2158 if (NeedToDelayGlobalization &&
2164 CheckVarsEscapingDeclContext VarChecker(CGF, TeamAndReductions.second);
2165 VarChecker.Visit(Body);
2167 VarChecker.getGlobalizedRecord(IsInTTDRegion);
2168 TeamAndReductions.first =
nullptr;
2169 TeamAndReductions.second.clear();
2171 VarChecker.getEscapedVariableLengthDecls();
2173 VarChecker.getDelayedVariableLengthDecls();
2174 if (!GlobalizedVarsRecord && EscapedVariableLengthDecls.empty() &&
2175 DelayedVariableLengthDecls.empty())
2177 auto I = FunctionGlobalizedDecls.try_emplace(CGF.
CurFn).first;
2178 I->getSecond().MappedParams =
2179 std::make_unique<CodeGenFunction::OMPMapVars>();
2180 I->getSecond().EscapedParameters.insert(
2181 VarChecker.getEscapedParameters().begin(),
2182 VarChecker.getEscapedParameters().end());
2183 I->getSecond().EscapedVariableLengthDecls.append(
2184 EscapedVariableLengthDecls.begin(), EscapedVariableLengthDecls.end());
2185 I->getSecond().DelayedVariableLengthDecls.append(
2186 DelayedVariableLengthDecls.begin(), DelayedVariableLengthDecls.end());
2187 DeclToAddrMapTy &
Data = I->getSecond().LocalVarData;
2188 for (
const ValueDecl *VD : VarChecker.getEscapedDecls()) {
2190 Data.try_emplace(VD);
2192 if (!NeedToDelayGlobalization) {
2194 struct GlobalizationScope final : EHScopeStack::Cleanup {
2195 GlobalizationScope() =
default;
2199 .emitGenericVarsEpilog(CGF);
2208 if (VD && VD->
hasAttr<OMPAllocateDeclAttr>()) {
2209 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
2211 switch (A->getAllocatorType()) {
2212 case OMPAllocateDeclAttr::OMPNullMemAlloc:
2213 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
2214 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
2215 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
2217 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
2219 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
2222 case OMPAllocateDeclAttr::OMPConstMemAlloc:
2225 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
2228 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
2229 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
2233 auto *GV =
new llvm::GlobalVariable(
2234 CGM.getModule(), VarTy,
false,
2235 llvm::GlobalValue::InternalLinkage, llvm::PoisonValue::get(VarTy),
2237 nullptr, llvm::GlobalValue::NotThreadLocal,
2238 CGM.getContext().getTargetAddressSpace(AS));
2243 GV, CGF.
Builder.getPtrTy(
CGM.getContext().getTargetAddressSpace(
2252 auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
2253 if (I == FunctionGlobalizedDecls.end())
2255 auto VDI = I->getSecond().LocalVarData.find(VD);
2256 if (VDI != I->getSecond().LocalVarData.end())
2257 return VDI->second.PrivateAddr;
2262 auto VDI = I->getSecond().LocalVarData.find(
2264 ->getCanonicalDecl());
2265 if (VDI != I->getSecond().LocalVarData.end())
2266 return VDI->second.PrivateAddr;
2274 FunctionGlobalizedDecls.erase(CGF.
CurFn);
2281 llvm::Value *&Chunk)
const {
2284 ScheduleKind = OMPC_DIST_SCHEDULE_static;
2286 RT.getGPUNumThreads(CGF),
2292 CGF, S, ScheduleKind, Chunk);
2298 const Expr *&ChunkExpr)
const {
2299 ScheduleKind = OMPC_SCHEDULE_static;
2301 llvm::APInt ChunkSize(32, 1);
2310 " Expected target-based directive.");
2311 const CapturedStmt *CS = D.getCapturedStmt(OMPD_target);
2315 if (!
C.capturesVariable())
2317 const VarDecl *VD =
C.getCapturedVar();
2318 const auto *RD = VD->
getType()
2322 if (!RD || !RD->isLambda())
2331 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
2333 RD->getCaptureFields(Captures, ThisCapture);
2343 const ValueDecl *VD = LC.getCapturedVar();
2348 auto It = Captures.find(VD);
2349 assert(It != Captures.end() &&
"Found lambda capture without field.");
2363 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
2365 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
2366 switch(A->getAllocatorType()) {
2367 case OMPAllocateDeclAttr::OMPNullMemAlloc:
2368 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
2370 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
2371 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
2372 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
2373 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
2374 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
2377 case OMPAllocateDeclAttr::OMPConstMemAlloc:
2380 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
2383 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
2384 llvm_unreachable(
"Expected predefined allocator for the variables with the "
2393 StringRef CPU =
CGM.getTarget().getTargetOpts().CPU;
2394 if (
CGM.getTarget().getTriple().isNVPTX() &&
2395 !llvm::NVPTX::supportsUnifiedAddressing(llvm::NVPTX::parseArch(CPU))) {
2397 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
2398 CGM.getDiags().Report(Clause->getBeginLoc(),
2399 diag::err_omp_unified_shared_memory_unsupported)
2412 const char *LocSize =
"__kmpc_get_hardware_num_threads_in_block";
2413 llvm::Function *F = M->getFunction(LocSize);
2415 F = llvm::Function::Create(llvm::FunctionType::get(CGF.
Int32Ty, {},
false),
2416 llvm::GlobalVariable::ExternalLinkage, LocSize,
2419 return Bld.CreateCall(F, {},
"nvptx_num_threads");
2426 CGM.getModule(), OMPRTL___kmpc_get_hardware_thread_id_in_block),
static std::optional< BinaryOperatorKind > getReductionBinOpKind(const Expr *ReductionOp)
Extracts the built-in reduction operator from a combiner of the form x = x / <op> rhs (or the min/max...
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)
static std::optional< llvm::AtomicRMWInst::BinOp > getReductionAtomicRMWOp(BinaryOperatorKind BOK, QualType Ty)
Maps a built-in reduction operator to an atomicrmw opcode for the atomic cross-team reduction fast pa...
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 is a common base class for loop directives ('omp simd', 'omp for', 'omp for simd' etc....
Expr * getIterationVariable() const
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.
const LangOptions & getLangOpts() const
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,...
const TargetCodeGenInfo & getTargetHooks() const
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()
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
llvm::SyncScope::ID getLLVMSyncScopeID(const LangOptions &LangOpts, SyncScope Scope, llvm::AtomicOrdering Ordering, llvm::LLVMContext &Ctx) const
Get the syncscope used in LLVM IR as a SyncScope ID.
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...
virtual const llvm::omp::GV & getGridValue() const
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).
bool isFloatingType() const
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.
Top level wrappers for InstallAPI frontend operations.
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.
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.
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