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 &&
360 void VisitOMPMetaDirective(
const OMPMetaDirective *D) { VisitStmt(D); }
361 void VisitCapturedStmt(
const CapturedStmt *S) {
364 for (
const CapturedStmt::Capture &
C : S->
captures()) {
365 if (
C.capturesVariable() && !
C.capturesVariableByCopy()) {
366 const ValueDecl *VD =
C.getCapturedVar();
376 for (
const LambdaCapture &
C : E->
captures()) {
377 if (
C.capturesVariable()) {
379 const ValueDecl *VD =
C.getCapturedVar();
387 void VisitBlockExpr(
const BlockExpr *E) {
392 const VarDecl *VD =
C.getVariable();
399 void VisitCallExpr(
const CallExpr *E) {
405 if (Arg->isLValue()) {
406 const bool SavedAllEscaped = AllEscaped;
409 AllEscaped = SavedAllEscaped;
416 void VisitDeclRefExpr(
const DeclRefExpr *E) {
419 const ValueDecl *VD = E->
getDecl();
427 void VisitUnaryOperator(
const UnaryOperator *E) {
431 const bool SavedAllEscaped = AllEscaped;
434 AllEscaped = SavedAllEscaped;
439 void VisitImplicitCastExpr(
const ImplicitCastExpr *E) {
443 const bool SavedAllEscaped = AllEscaped;
446 AllEscaped = SavedAllEscaped;
451 void VisitExpr(
const Expr *E) {
454 bool SavedAllEscaped = AllEscaped;
457 for (
const Stmt *Child : E->
children())
460 AllEscaped = SavedAllEscaped;
462 void VisitStmt(
const Stmt *S) {
465 for (
const Stmt *Child : S->
children())
472 const RecordDecl *getGlobalizedRecord(
bool IsInTTDRegion) {
474 buildRecordForGlobalizedVars(IsInTTDRegion);
479 const FieldDecl *getFieldForGlobalizedVar(
const ValueDecl *VD)
const {
480 assert(GlobalizedRD &&
481 "Record for globalized variables must be generated already.");
482 return MappedDeclsFields.lookup(VD);
486 ArrayRef<const ValueDecl *> getEscapedDecls()
const {
487 return EscapedDecls.getArrayRef();
492 const llvm::SmallPtrSetImpl<const Decl *> &getEscapedParameters()
const {
493 return EscapedParameters;
498 ArrayRef<const ValueDecl *> getEscapedVariableLengthDecls()
const {
499 return EscapedVariableLengthDecls.getArrayRef();
504 ArrayRef<const ValueDecl *> getDelayedVariableLengthDecls()
const {
505 return DelayedVariableLengthDecls.getArrayRef();
511CGOpenMPRuntimeGPU::getExecutionMode()
const {
512 return CurrentExecutionMode;
516CGOpenMPRuntimeGPU::getDataSharingMode()
const {
517 return CurrentDataSharingMode;
523 const auto *CS = D.getInnermostCapturedStmt();
525 CS->getCapturedStmt()->IgnoreContainers(
true);
528 if (
const auto *NestedDir =
529 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
531 switch (D.getDirectiveKind()) {
535 if (DKind == OMPD_teams) {
536 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
541 if (
const auto *NND =
542 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
543 DKind = NND->getDirectiveKind();
549 case OMPD_target_teams:
551 case OMPD_target_simd:
552 case OMPD_target_parallel:
553 case OMPD_target_parallel_for:
554 case OMPD_target_parallel_for_simd:
555 case OMPD_target_teams_distribute:
556 case OMPD_target_teams_distribute_simd:
557 case OMPD_target_teams_distribute_parallel_for:
558 case OMPD_target_teams_distribute_parallel_for_simd:
561 case OMPD_parallel_for:
562 case OMPD_parallel_master:
563 case OMPD_parallel_sections:
565 case OMPD_parallel_for_simd:
567 case OMPD_cancellation_point:
568 case OMPD_ordered_standalone:
569 case OMPD_ordered_blockassoc:
570 case OMPD_threadprivate:
588 case OMPD_target_data:
589 case OMPD_target_exit_data:
590 case OMPD_target_enter_data:
591 case OMPD_distribute:
592 case OMPD_distribute_simd:
593 case OMPD_distribute_parallel_for:
594 case OMPD_distribute_parallel_for_simd:
595 case OMPD_teams_distribute:
596 case OMPD_teams_distribute_simd:
597 case OMPD_teams_distribute_parallel_for:
598 case OMPD_teams_distribute_parallel_for_simd:
599 case OMPD_target_update:
600 case OMPD_declare_simd:
601 case OMPD_declare_variant:
602 case OMPD_begin_declare_variant:
603 case OMPD_end_declare_variant:
604 case OMPD_declare_target:
605 case OMPD_end_declare_target:
606 case OMPD_declare_reduction:
607 case OMPD_declare_mapper:
609 case OMPD_taskloop_simd:
610 case OMPD_master_taskloop:
611 case OMPD_master_taskloop_simd:
612 case OMPD_parallel_master_taskloop:
613 case OMPD_parallel_master_taskloop_simd:
617 llvm_unreachable(
"Unexpected directive.");
627 switch (DirectiveKind) {
629 case OMPD_target_teams:
631 case OMPD_target_parallel_loop:
632 case OMPD_target_parallel:
633 case OMPD_target_parallel_for:
634 case OMPD_target_parallel_for_simd:
635 case OMPD_target_teams_distribute_parallel_for:
636 case OMPD_target_teams_distribute_parallel_for_simd:
637 case OMPD_target_simd:
638 case OMPD_target_teams_distribute_simd:
640 case OMPD_target_teams_distribute:
642 case OMPD_target_teams_loop:
645 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
646 return TTLD->canBeParallelFor();
650 case OMPD_parallel_for:
651 case OMPD_parallel_master:
652 case OMPD_parallel_sections:
654 case OMPD_parallel_for_simd:
656 case OMPD_cancellation_point:
657 case OMPD_ordered_standalone:
658 case OMPD_ordered_blockassoc:
659 case OMPD_threadprivate:
677 case OMPD_target_data:
678 case OMPD_target_exit_data:
679 case OMPD_target_enter_data:
680 case OMPD_distribute:
681 case OMPD_distribute_simd:
682 case OMPD_distribute_parallel_for:
683 case OMPD_distribute_parallel_for_simd:
684 case OMPD_teams_distribute:
685 case OMPD_teams_distribute_simd:
686 case OMPD_teams_distribute_parallel_for:
687 case OMPD_teams_distribute_parallel_for_simd:
688 case OMPD_target_update:
689 case OMPD_declare_simd:
690 case OMPD_declare_variant:
691 case OMPD_begin_declare_variant:
692 case OMPD_end_declare_variant:
693 case OMPD_declare_target:
694 case OMPD_end_declare_target:
695 case OMPD_declare_reduction:
696 case OMPD_declare_mapper:
698 case OMPD_taskloop_simd:
699 case OMPD_master_taskloop:
700 case OMPD_master_taskloop_simd:
701 case OMPD_parallel_master_taskloop:
702 case OMPD_parallel_master_taskloop_simd:
709 "Unknown programming model for OpenMP directive on NVPTX target.");
712void CGOpenMPRuntimeGPU::emitNonSPMDKernel(
const OMPExecutableDirective &D,
713 StringRef ParentName,
714 llvm::Function *&OutlinedFn,
715 llvm::Constant *&OutlinedFnID,
718 ExecutionRuntimeModesRAII ModeRAII(CurrentExecutionMode,
EM_NonSPMD);
719 EntryFunctionState EST;
720 WrapperFunctionsMap.clear();
722 [[maybe_unused]]
bool IsBareKernel = D.getSingleClause<OMPXBareClause>();
723 assert(!IsBareKernel &&
"bare kernel should not be at generic mode");
726 class NVPTXPrePostActionTy :
public PrePostActionTy {
727 CGOpenMPRuntimeGPU::EntryFunctionState &EST;
728 const OMPExecutableDirective &D;
731 NVPTXPrePostActionTy(CGOpenMPRuntimeGPU::EntryFunctionState &EST,
732 const OMPExecutableDirective &D)
734 void Enter(CodeGenFunction &CGF)
override {
736 RT.emitKernelInit(D, CGF, EST,
false);
738 RT.setLocThreadIdInsertPt(CGF,
true);
740 void Exit(CodeGenFunction &CGF)
override {
742 RT.clearLocThreadIdInsertPt(CGF);
743 RT.emitKernelDeinit(CGF, EST,
false);
747 IsInTTDRegion =
true;
749 IsOffloadEntry, CodeGen);
750 IsInTTDRegion =
false;
753void CGOpenMPRuntimeGPU::emitBareKernelEnvironment(
759 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs Attrs;
760 Attrs.ExecFlags = llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_BARE;
761 CGBuilderTy &Bld = CGF.
Builder;
765void CGOpenMPRuntimeGPU::emitKernelInit(
const OMPExecutableDirective &D,
767 EntryFunctionState &EST,
bool IsSPMD) {
768 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs Attrs;
770 IsSPMD ? llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_SPMD
771 : llvm::omp::OMPTgtExecModeFlags::OMP_TGT_EXEC_MODE_GENERIC;
774 CGBuilderTy &Bld = CGF.
Builder;
775 Bld.restoreIP(
OMPBuilder.createTargetInit(Bld, Attrs));
777 emitGenericVarsProlog(CGF, EST.Loc);
781 EntryFunctionState &EST,
784 emitGenericVarsEpilog(CGF);
787 ASTContext &
C =
CGM.getContext();
788 RecordDecl *StaticRD =
C.buildImplicitRecord(
789 "_openmp_teams_reduction_type_$_", RecordDecl::TagKind::Union);
791 for (
const RecordDecl *TeamReductionRec : TeamsReductions) {
792 CanQualType RecTy =
C.getCanonicalTagType(TeamReductionRec);
794 C, StaticRD, SourceLocation(), SourceLocation(),
nullptr, RecTy,
795 C.getTrivialTypeSourceInfo(RecTy, SourceLocation()),
803 llvm::Type *LLVMReductionsBufferTy =
804 CGM.getTypes().ConvertTypeForMem(StaticTy);
805 const auto &DL =
CGM.getModule().getDataLayout();
807 TeamsReductions.empty()
809 : DL.getTypeAllocSize(LLVMReductionsBufferTy).getFixedValue();
810 CGBuilderTy &Bld = CGF.
Builder;
811 OMPBuilder.createTargetDeinit(Bld, ReductionDataSize);
812 TeamsReductions.clear();
815void CGOpenMPRuntimeGPU::emitSPMDKernel(
const OMPExecutableDirective &D,
816 StringRef ParentName,
817 llvm::Function *&OutlinedFn,
818 llvm::Constant *&OutlinedFnID,
821 ExecutionRuntimeModesRAII ModeRAII(CurrentExecutionMode,
EM_SPMD);
822 EntryFunctionState EST;
824 bool IsBareKernel = D.getSingleClause<OMPXBareClause>();
827 class NVPTXPrePostActionTy :
public PrePostActionTy {
828 CGOpenMPRuntimeGPU &RT;
829 CGOpenMPRuntimeGPU::EntryFunctionState &EST;
831 DataSharingMode Mode;
832 const OMPExecutableDirective &D;
835 NVPTXPrePostActionTy(CGOpenMPRuntimeGPU &RT,
836 CGOpenMPRuntimeGPU::EntryFunctionState &EST,
837 bool IsBareKernel,
const OMPExecutableDirective &D)
838 : RT(RT), EST(EST), IsBareKernel(IsBareKernel),
839 Mode(RT.CurrentDataSharingMode), D(D) {}
840 void Enter(CodeGenFunction &CGF)
override {
842 RT.CurrentDataSharingMode = DataSharingMode::DS_CUDA;
843 RT.emitBareKernelEnvironment(D, CGF);
846 RT.emitKernelInit(D, CGF, EST,
true);
848 RT.setLocThreadIdInsertPt(CGF,
true);
850 void Exit(CodeGenFunction &CGF)
override {
852 RT.CurrentDataSharingMode = Mode;
855 RT.clearLocThreadIdInsertPt(CGF);
856 RT.emitKernelDeinit(CGF, EST,
true);
858 } Action(*
this, EST, IsBareKernel, D);
860 IsInTTDRegion =
true;
862 IsOffloadEntry, CodeGen);
863 IsInTTDRegion =
false;
866void CGOpenMPRuntimeGPU::emitTargetOutlinedFunction(
867 const OMPExecutableDirective &D, StringRef ParentName,
868 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
873 assert(!ParentName.empty() &&
"Invalid target region parent name!");
876 bool IsBareKernel = D.getSingleClause<OMPXBareClause>();
877 if (Mode || IsBareKernel)
878 emitSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry,
881 emitNonSPMDKernel(D, ParentName, OutlinedFn, OutlinedFnID, IsOffloadEntry,
887 llvm::OpenMPIRBuilderConfig Config(
888 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
889 CGM.getLangOpts().OpenMPOffloadMandatory,
892 Config.setDefaultTargetAS(
894 Config.setRuntimeCC(
CGM.getRuntimeCC());
898 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
899 llvm_unreachable(
"OpenMP can only handle device code.");
901 if (
CGM.getLangOpts().OpenMPCUDAMode)
905 if (
CGM.getLangOpts().NoGPULib ||
CGM.getLangOpts().OMPHostIRFile.empty())
908 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPTargetDebug,
909 "__omp_rtl_debug_kind");
910 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPTeamSubscription,
911 "__omp_rtl_assume_teams_oversubscription");
912 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPThreadSubscription,
913 "__omp_rtl_assume_threads_oversubscription");
914 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPNoThreadState,
915 "__omp_rtl_assume_no_thread_state");
916 OMPBuilder.createGlobalFlag(
CGM.getLangOpts().OpenMPNoNestedParallelism,
917 "__omp_rtl_assume_no_nested_parallelism");
921 ProcBindKind ProcBind,
929 CGM.getDiags().Report(Loc, diag::warn_omp_gpu_unsupported_clause)
930 << getOpenMPClauseName(OMPC_message);
937 CGM.getDiags().Report(Loc, diag::warn_omp_gpu_unsupported_clause)
938 << getOpenMPClauseName(OMPC_severity);
947 if (Modifier == OMPC_NUMTHREADS_strict) {
948 CGM.getDiags().Report(Loc,
949 diag::warn_omp_gpu_unsupported_modifier_for_clause)
950 <<
"strict" << getOpenMPClauseName(OMPC_num_threads);
958 const Expr *NumTeams,
959 const Expr *ThreadLimit,
967 bool PrevIsInTTDRegion = IsInTTDRegion;
968 IsInTTDRegion =
false;
971 CGF, D, ThreadIDVar, InnermostKind,
CodeGen));
972 IsInTTDRegion = PrevIsInTTDRegion;
974 llvm::Function *WrapperFun =
975 createParallelDataSharingWrapper(OutlinedFun, D);
976 WrapperFunctionsMap[OutlinedFun] = WrapperFun;
988 "expected teams directive.");
993 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(
995 Dir = dyn_cast_or_null<OMPExecutableDirective>(S);
1002 for (
const auto *
C : Dir->getClausesOfKind<OMPLastprivateClause>()) {
1003 for (
const Expr *E :
C->getVarRefs())
1013 "expected teams directive.");
1014 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1015 for (
const Expr *E :
C->privates())
1028 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> MappedDeclsFields;
1029 unsigned WarpSize =
CGM.getTarget().getGridValue().GV_Warp_Size;
1035 if (!LastPrivatesReductions.empty()) {
1036 GlobalizedRD = ::buildRecordForGlobalizedVars(
1037 CGM.getContext(), {}, LastPrivatesReductions, MappedDeclsFields,
1040 }
else if (!LastPrivatesReductions.empty()) {
1041 assert(!TeamAndReductions.first &&
1042 "Previous team declaration is not expected.");
1043 TeamAndReductions.first = D.getCapturedStmt(OMPD_teams)->getCapturedDecl();
1044 std::swap(TeamAndReductions.second, LastPrivatesReductions);
1051 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
1055 NVPTXPrePostActionTy(
1057 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *>
1059 : Loc(Loc), GlobalizedRD(GlobalizedRD),
1060 MappedDeclsFields(MappedDeclsFields) {}
1065 auto I = Rt.FunctionGlobalizedDecls.try_emplace(CGF.
CurFn).first;
1066 I->getSecond().MappedParams =
1067 std::make_unique<CodeGenFunction::OMPMapVars>();
1068 DeclToAddrMapTy &
Data = I->getSecond().LocalVarData;
1069 for (
const auto &Pair : MappedDeclsFields) {
1070 assert(Pair.getFirst()->isCanonicalDecl() &&
1071 "Expected canonical declaration");
1072 Data.try_emplace(Pair.getFirst());
1075 Rt.emitGenericVarsProlog(CGF, Loc);
1079 .emitGenericVarsEpilog(CGF);
1081 } Action(Loc, GlobalizedRD, MappedDeclsFields);
1084 CGF, D, ThreadIDVar, InnermostKind,
CodeGen);
1096 const auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
1097 if (I == FunctionGlobalizedDecls.end())
1100 for (
auto &Rec : I->getSecond().LocalVarData) {
1102 bool EscapedParam = I->getSecond().EscapedParameters.count(Rec.first);
1106 llvm::Value *ParValue;
1115 llvm::CallBase *VoidPtr =
1120 VoidPtr->addRetAttr(llvm::Attribute::get(
1126 VoidPtr, Bld.getPtrTy(0), VD->
getName() +
"_on_stack");
1129 Rec.second.PrivateAddr = VarAddr.getAddress();
1130 Rec.second.GlobalizedVal = VoidPtr;
1135 I->getSecond().MappedParams->setVarAddr(CGF, VD, VarAddr.getAddress());
1138 VoidPtr->setDebugLoc(DI->SourceLocToDebugLoc(VD->
getLocation()));
1141 for (
const auto *ValueD : I->getSecond().EscapedVariableLengthDecls) {
1143 std::pair<llvm::Value *, llvm::Value *> AddrSizePair =
1145 I->getSecond().EscapedVariableLengthDeclsAddrs.emplace_back(AddrSizePair);
1147 CGM.getContext().getDeclAlign(VD),
1149 I->getSecond().MappedParams->setVarAddr(CGF, VD,
Base.getAddress());
1151 I->getSecond().MappedParams->apply(CGF);
1156 const auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
1157 if (I == FunctionGlobalizedDecls.end())
1161 return llvm::is_contained(I->getSecond().DelayedVariableLengthDecls, VD);
1164std::pair<llvm::Value *, llvm::Value *>
1172 Size = Bld.CreateNUWAdd(
1174 llvm::Value *AlignVal =
1176 Size = Bld.CreateUDiv(Size, AlignVal);
1177 Size = Bld.CreateNUWMul(Size, AlignVal);
1180 llvm::Value *AllocArgs[] = {Size};
1181 llvm::CallBase *VoidPtr =
1183 CGM.getModule(), OMPRTL___kmpc_alloc_shared),
1185 VoidPtr->addRetAttr(llvm::Attribute::get(
1186 CGM.getLLVMContext(), llvm::Attribute::Alignment, Align.
getQuantity()));
1188 return std::make_pair(VoidPtr, Size);
1193 const std::pair<llvm::Value *, llvm::Value *> &AddrSizePair) {
1196 CGM.getModule(), OMPRTL___kmpc_free_shared),
1197 {AddrSizePair.first, AddrSizePair.second});
1204 const auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
1205 if (I != FunctionGlobalizedDecls.end()) {
1208 for (
const auto &AddrSizePair :
1209 llvm::reverse(I->getSecond().EscapedVariableLengthDeclsAddrs)) {
1212 {AddrSizePair.first, AddrSizePair.second});
1215 for (
auto &Rec : llvm::reverse(I->getSecond().LocalVarData)) {
1217 I->getSecond().MappedParams->restore(CGF);
1219 llvm::Value *FreeArgs[] = {Rec.second.GlobalizedVal,
1231 llvm::Function *OutlinedFn,
1245 OutlinedFnArgs.push_back(llvm::ConstantPointerNull::get(
CGM.VoidPtrTy));
1248 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1249 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
1261 auto &&ParallelGen = [
this, Loc, OutlinedFn, CapturedVars, IfCond,
1265 llvm::Value *NumThreadsVal = NumThreads;
1266 llvm::Function *WFn = WrapperFunctionsMap[OutlinedFn];
1267 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1270 llvm::Value *ID = llvm::ConstantPointerNull::get(FnPtrTy);
1272 ID = Bld.CreateBitOrPointerCast(WFn, FnPtrTy);
1274 llvm::Value *FnPtr = Bld.CreateBitOrPointerCast(OutlinedFn, FnPtrTy);
1282 llvm::ArrayType::get(
CGM.VoidPtrTy, CapturedVars.size()),
1283 "captured_vars_addrs");
1285 if (!CapturedVars.empty()) {
1289 for (llvm::Value *
V : CapturedVars) {
1292 if (
V->getType()->isIntegerTy())
1302 llvm::Value *IfCondVal =
nullptr;
1307 IfCondVal = llvm::ConstantInt::get(CGF.
Int32Ty, 1);
1310 NumThreadsVal = llvm::ConstantInt::getAllOnesValue(CGF.
Int32Ty);
1312 NumThreadsVal = Bld.CreateZExtOrTrunc(NumThreadsVal, CGF.
Int32Ty);
1315 llvm::Value *StrictNumThreadsVal = llvm::ConstantInt::get(CGF.
Int32Ty, 0);
1317 assert(IfCondVal &&
"Expected a value");
1319 llvm::Value *Args[] = {
1324 llvm::ConstantInt::getAllOnesValue(CGF.
Int32Ty),
1327 Bld.CreateBitOrPointerCast(CapturedVarsAddrs.
emitRawPointer(CGF),
1329 llvm::ConstantInt::get(
CGM.SizeTy, CapturedVars.size()),
1330 StrictNumThreadsVal};
1333 CGM.getModule(), OMPRTL___kmpc_parallel_60),
1347 llvm::Value *Args[] = {
1348 llvm::ConstantPointerNull::get(
1350 llvm::ConstantInt::get(CGF.
Int32Ty, 0,
true)};
1369 CGM.getModule(), OMPRTL___kmpc_barrier),
1387 CGM.getModule(), OMPRTL___kmpc_warp_active_thread_mask));
1389 llvm::Value *ThreadID = RT.getGPUThreadID(CGF);
1392 llvm::Value *TeamWidth = RT.getGPUNumThreads(CGF);
1405 llvm::Value *CmpLoopBound = CGF.
Builder.CreateICmpSLT(CounterVal, TeamWidth);
1406 CGF.
Builder.CreateCondBr(CmpLoopBound, TestBB, ExitBB);
1412 llvm::Value *CmpThreadToCounter =
1413 CGF.
Builder.CreateICmpEQ(ThreadID, CounterVal);
1414 CGF.
Builder.CreateCondBr(CmpThreadToCounter, BodyBB, SyncBB);
1430 CGM.getModule(), OMPRTL___kmpc_syncwarp),
1433 llvm::Value *IncCounterVal =
1447 "Cast type must sized.");
1449 "Val type must sized.");
1451 if (ValTy == CastTy)
1455 return CGF.
Builder.CreateBitCast(Val, LLVMCastTy);
1457 return CGF.
Builder.CreateIntCast(Val, LLVMCastTy,
1472static std::optional<BinaryOperatorKind>
1474 const auto *Assign = dyn_cast<BinaryOperator>(ReductionOp);
1475 if (!Assign || Assign->getOpcode() != BO_Assign)
1476 return std::nullopt;
1477 const Expr *RHS = Assign->getRHS();
1480 if (
const auto *ACO =
1482 RHS = ACO->getCond();
1484 return BO->getOpcode();
1485 return std::nullopt;
1491static std::optional<llvm::AtomicRMWInst::BinOp>
1499 return llvm::AtomicRMWInst::Add;
1501 return llvm::AtomicRMWInst::FAdd;
1502 return std::nullopt;
1504 return IsInt ? std::optional(llvm::AtomicRMWInst::And) : std::nullopt;
1506 return IsInt ? std::optional(llvm::AtomicRMWInst::Or) : std::nullopt;
1508 return IsInt ? std::optional(llvm::AtomicRMWInst::Xor) : std::nullopt;
1511 return IsSigned ? llvm::AtomicRMWInst::Min : llvm::AtomicRMWInst::UMin;
1512 return std::nullopt;
1515 return IsSigned ? llvm::AtomicRMWInst::Max : llvm::AtomicRMWInst::UMax;
1516 return std::nullopt;
1518 return std::nullopt;
1775 assert(!TeamsReduction && !ParallelReduction &&
1776 "Invalid reduction selection in emitReduction.");
1777 (void)ParallelReduction;
1779 ReductionOps, Options);
1783 llvm::SmallDenseMap<const ValueDecl *, const FieldDecl *> VarFieldMap;
1790 const RecordDecl *ReductionRec = ::buildRecordForGlobalizedVars(
1791 CGM.getContext(), PrivatesReductions, {}, VarFieldMap, 1);
1797 bool UseAtomicReduction =
1798 TeamsReduction &&
CGM.getLangOpts().OpenMPTargetAtomicReduction;
1799 bool AllAtomicable = UseAtomicReduction;
1804 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1806 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertPoint());
1807 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(
1814 llvm::Type *ElementType;
1815 llvm::Value *Variable;
1816 llvm::Value *PrivateVariable;
1817 llvm::OpenMPIRBuilder::ReductionGenAtomicCBTy AtomicReductionGen =
nullptr;
1819 const auto *RHSVar =
1822 const auto *LHSVar =
1825 llvm::OpenMPIRBuilder::EvalKind EvalKind;
1828 EvalKind = llvm::OpenMPIRBuilder::EvalKind::Scalar;
1831 EvalKind = llvm::OpenMPIRBuilder::EvalKind::Complex;
1834 EvalKind = llvm::OpenMPIRBuilder::EvalKind::Aggregate;
1837 auto ReductionGen = [&](InsertPointTy CodeGenIP,
unsigned I,
1838 llvm::Value **LHSPtr, llvm::Value **RHSPtr,
1839 llvm::Function *NewFunc) {
1840 CGF.
Builder.restoreIP(CodeGenIP);
1841 auto *CurFn = CGF.
CurFn;
1842 CGF.
CurFn = NewFunc;
1844 const bool DisableDebugInfo = !NewFunc->getSubprogram();
1845 llvm::DebugLoc SavedDebugLoc;
1846 if (DisableDebugInfo) {
1850 SavedDebugLoc = CGF.
Builder.getCurrentDebugLocation();
1851 CGF.
Builder.SetCurrentDebugLocation({});
1866 if (DisableDebugInfo) {
1868 CGF.
Builder.SetCurrentDebugLocation(SavedDebugLoc);
1872 return CGF.
Builder.GetInsertPoint();
1878 if (UseAtomicReduction) {
1879 std::optional<llvm::AtomicRMWInst::BinOp> AtomicOp;
1880 if (EvalKind == llvm::OpenMPIRBuilder::EvalKind::Scalar) {
1881 if (std::optional<BinaryOperatorKind> BOK =
1886 AllAtomicable =
false;
1888 llvm::AtomicRMWInst::BinOp Op = *AtomicOp;
1889 llvm::Align Alignment =
1890 CGM.getModule().getDataLayout().getPrefTypeAlign(ElementType);
1899 AtomicReductionGen = [Op, Alignment,
1900 SSID](InsertPointTy IP, llvm::Type *EltTy,
1901 llvm::Value *LHS, llvm::Value *RHS)
1902 -> llvm::OpenMPIRBuilder::InsertPointOrErrorTy {
1903 llvm::IRBuilder<> Builder(IP);
1904 llvm::Value *Val = Builder.CreateLoad(EltTy, RHS);
1905 Builder.CreateAtomicRMW(Op, LHS, Val, Alignment,
1906 llvm::AtomicOrdering::Monotonic, SSID);
1907 return Builder.GetInsertPoint();
1912 ReductionInfos.emplace_back(llvm::OpenMPIRBuilder::ReductionInfo(
1913 ElementType, Variable, PrivateVariable, EvalKind,
1914 nullptr, ReductionGen, AtomicReductionGen,
1921 if (TeamsReduction && !AllAtomicable)
1922 TeamsReductions.push_back(ReductionRec);
1925 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
1927 OmpLoc, AllocaIP, CodeGenIP, ReductionInfos, {},
false,
1928 TeamsReduction, IsSPMD,
1929 llvm::OpenMPIRBuilder::ReductionGenCBKind::Clang,
1931 CGF.
Builder.restoreIP(AfterIP);
1936 const VarDecl *NativeParam)
const {
1943 if (
const auto *
Attr = FD->
getAttr<OMPCaptureKindAttr>()) {
1944 if (
Attr->getCaptureKind() == OMPC_map) {
1945 PointeeTy =
CGM.getContext().getAddrSpaceQualType(PointeeTy,
1949 ArgType =
CGM.getContext().getPointerType(PointeeTy);
1967 const VarDecl *TargetParam)
const {
1968 assert(NativeParam != TargetParam &&
1970 "Native arg must not be the same as target arg.");
1974 const Type *NonQualTy = QC.
strip(NativeParamType);
1976 unsigned NativePointeeAddrSpace =
1984 llvm::PointerType::get(CGF.
getLLVMContext(), NativePointeeAddrSpace));
1988 return NativeParamAddr;
1995 TargetArgs.reserve(Args.size());
1996 auto *FnType = OutlinedFn.getFunctionType();
1997 for (
unsigned I = 0, E = Args.size(); I < E; ++I) {
1998 if (FnType->isVarArg() && FnType->getNumParams() <= I) {
1999 TargetArgs.append(std::next(Args.begin(), I), Args.end());
2002 llvm::Type *TargetType = FnType->getParamType(I);
2003 llvm::Value *NativeArg = Args[I];
2004 if (!TargetType->isPointerTy()) {
2005 TargetArgs.emplace_back(NativeArg);
2008 TargetArgs.emplace_back(
2018llvm::Function *CGOpenMPRuntimeGPU::createParallelDataSharingWrapper(
2021 const auto &CS = *D.getCapturedStmt(OMPD_parallel);
2030 Ctx,
nullptr, D.getBeginLoc(),
2033 Ctx,
nullptr, D.getBeginLoc(),
2035 WrapperArgs.emplace_back(ParallelLevelArg);
2036 WrapperArgs.emplace_back(WrapperArg);
2041 auto *Fn = llvm::Function::Create(
2043 Twine(OutlinedParallelFn->getName(),
"_wrapper"), &
CGM.
getModule());
2051 Fn->addFnAttr(llvm::Attribute::NoInline);
2054 Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
2058 D.getBeginLoc(), D.getBeginLoc());
2060 const auto *RD = CS.getCapturedRecordDecl();
2061 auto CurField = RD->field_begin();
2073 auto CI = CS.capture_begin();
2079 llvm::Value *GlobalArgsPtr = GlobalArgs.
getPointer();
2080 llvm::Value *DataSharingArgs[] = {GlobalArgsPtr};
2088 if (CS.capture_size() > 0 ||
2099 Src, Bld.getPtrTy(0), CGF.
SizeTy);
2105 Args.emplace_back(LB);
2115 Args.emplace_back(UB);
2118 if (CS.capture_size() > 0) {
2120 for (
unsigned I = 0, E = CS.capture_size(); I < E; ++I, ++CI, ++CurField) {
2121 QualType ElemTy = CurField->getType();
2130 if (CI->capturesVariableByCopy() &&
2131 !CI->getCapturedVar()->getType()->isAnyPointerType()) {
2135 Args.emplace_back(Arg);
2149 assert(D &&
"Expected function or captured|block decl.");
2150 assert(FunctionGlobalizedDecls.count(CGF.
CurFn) == 0 &&
2151 "Function is registered already.");
2152 assert((!TeamAndReductions.first || TeamAndReductions.first == D) &&
2153 "Team is set but not processed.");
2154 const Stmt *Body =
nullptr;
2155 bool NeedToDelayGlobalization =
false;
2156 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
2157 Body = FD->getBody();
2158 }
else if (
const auto *BD = dyn_cast<BlockDecl>(D)) {
2159 Body = BD->getBody();
2160 }
else if (
const auto *CD = dyn_cast<CapturedDecl>(D)) {
2161 Body = CD->getBody();
2163 if (NeedToDelayGlobalization &&
2169 CheckVarsEscapingDeclContext VarChecker(CGF, TeamAndReductions.second);
2170 VarChecker.Visit(Body);
2172 VarChecker.getGlobalizedRecord(IsInTTDRegion);
2173 TeamAndReductions.first =
nullptr;
2174 TeamAndReductions.second.clear();
2176 VarChecker.getEscapedVariableLengthDecls();
2178 VarChecker.getDelayedVariableLengthDecls();
2179 if (!GlobalizedVarsRecord && EscapedVariableLengthDecls.empty() &&
2180 DelayedVariableLengthDecls.empty())
2182 auto I = FunctionGlobalizedDecls.try_emplace(CGF.
CurFn).first;
2183 I->getSecond().MappedParams =
2184 std::make_unique<CodeGenFunction::OMPMapVars>();
2185 I->getSecond().EscapedParameters.insert(
2186 VarChecker.getEscapedParameters().begin(),
2187 VarChecker.getEscapedParameters().end());
2188 I->getSecond().EscapedVariableLengthDecls.append(
2189 EscapedVariableLengthDecls.begin(), EscapedVariableLengthDecls.end());
2190 I->getSecond().DelayedVariableLengthDecls.append(
2191 DelayedVariableLengthDecls.begin(), DelayedVariableLengthDecls.end());
2192 DeclToAddrMapTy &
Data = I->getSecond().LocalVarData;
2193 for (
const ValueDecl *VD : VarChecker.getEscapedDecls()) {
2195 Data.try_emplace(VD);
2197 if (!NeedToDelayGlobalization) {
2199 struct GlobalizationScope final : EHScopeStack::Cleanup {
2200 GlobalizationScope() =
default;
2204 .emitGenericVarsEpilog(CGF);
2213 if (VD && VD->
hasAttr<OMPAllocateDeclAttr>()) {
2214 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
2216 switch (A->getAllocatorType()) {
2217 case OMPAllocateDeclAttr::OMPNullMemAlloc:
2218 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
2219 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
2220 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
2222 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
2224 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
2227 case OMPAllocateDeclAttr::OMPConstMemAlloc:
2230 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
2233 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
2234 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
2238 auto *GV =
new llvm::GlobalVariable(
2239 CGM.getModule(), VarTy,
false,
2240 llvm::GlobalValue::InternalLinkage, llvm::PoisonValue::get(VarTy),
2242 nullptr, llvm::GlobalValue::NotThreadLocal,
2243 CGM.getContext().getTargetAddressSpace(AS));
2248 GV, CGF.
Builder.getPtrTy(
CGM.getContext().getTargetAddressSpace(
2257 auto I = FunctionGlobalizedDecls.find(CGF.
CurFn);
2258 if (I == FunctionGlobalizedDecls.end())
2260 auto VDI = I->getSecond().LocalVarData.find(VD);
2261 if (VDI != I->getSecond().LocalVarData.end())
2262 return VDI->second.PrivateAddr;
2267 auto VDI = I->getSecond().LocalVarData.find(
2269 ->getCanonicalDecl());
2270 if (VDI != I->getSecond().LocalVarData.end())
2271 return VDI->second.PrivateAddr;
2279 FunctionGlobalizedDecls.erase(CGF.
CurFn);
2286 llvm::Value *&Chunk)
const {
2289 ScheduleKind = OMPC_DIST_SCHEDULE_static;
2291 RT.getGPUNumThreads(CGF),
2297 CGF, S, ScheduleKind, Chunk);
2303 const Expr *&ChunkExpr)
const {
2304 ScheduleKind = OMPC_SCHEDULE_static;
2306 llvm::APInt ChunkSize(32, 1);
2315 " Expected target-based directive.");
2316 const CapturedStmt *CS = D.getCapturedStmt(OMPD_target);
2320 if (!
C.capturesVariable())
2322 const VarDecl *VD =
C.getCapturedVar();
2323 const auto *RD = VD->
getType()
2327 if (!RD || !RD->isLambda())
2336 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
2338 RD->getCaptureFields(Captures, ThisCapture);
2348 const ValueDecl *VD = LC.getCapturedVar();
2353 auto It = Captures.find(VD);
2354 assert(It != Captures.end() &&
"Found lambda capture without field.");
2368 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
2370 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
2371 switch(A->getAllocatorType()) {
2372 case OMPAllocateDeclAttr::OMPNullMemAlloc:
2373 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
2375 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
2376 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
2377 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
2378 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
2379 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
2382 case OMPAllocateDeclAttr::OMPConstMemAlloc:
2385 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
2388 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
2389 llvm_unreachable(
"Expected predefined allocator for the variables with the "
2398 StringRef CPU =
CGM.getTarget().getTargetOpts().CPU;
2399 if (
CGM.getTarget().getTriple().isNVPTX() &&
2400 !llvm::NVPTX::supportsUnifiedAddressing(llvm::NVPTX::parseArch(CPU))) {
2402 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
2403 CGM.getDiags().Report(Clause->getBeginLoc(),
2404 diag::err_omp_unified_shared_memory_unsupported)
2417 const char *LocSize =
"__kmpc_get_hardware_num_threads_in_block";
2418 llvm::Function *F = M->getFunction(LocSize);
2420 F = llvm::Function::Create(llvm::FunctionType::get(CGF.
Int32Ty, {},
false),
2421 llvm::GlobalVariable::ExternalLinkage, LocSize,
2424 return Bld.CreateCall(F, {},
"nvptx_num_threads");
2431 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
This is an opaque type for sizes expressed in character units.
bool isZero() const
Test whether the quantity equals zero.
llvm::Align getAsAlign() const
Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit bytes.
QuantityType getQuantity() const
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