clang 22.0.0git
CGStmtOpenMP.cpp
Go to the documentation of this file.
1//===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code to emit OpenMP nodes as LLVM code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CGCleanup.h"
14#include "CGDebugInfo.h"
15#include "CGOpenMPRuntime.h"
16#include "CodeGenFunction.h"
17#include "CodeGenModule.h"
18#include "CodeGenPGO.h"
19#include "TargetInfo.h"
21#include "clang/AST/Attr.h"
24#include "clang/AST/Stmt.h"
30#include "llvm/ADT/SmallSet.h"
31#include "llvm/BinaryFormat/Dwarf.h"
32#include "llvm/Frontend/OpenMP/OMPConstants.h"
33#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
34#include "llvm/IR/Constants.h"
35#include "llvm/IR/DebugInfoMetadata.h"
36#include "llvm/IR/Instructions.h"
37#include "llvm/IR/IntrinsicInst.h"
38#include "llvm/IR/Metadata.h"
39#include "llvm/Support/AtomicOrdering.h"
40#include "llvm/Support/Debug.h"
41#include <optional>
42using namespace clang;
43using namespace CodeGen;
44using namespace llvm::omp;
45
46#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
47
48static const VarDecl *getBaseDecl(const Expr *Ref);
51
52namespace {
53/// Lexical scope for OpenMP executable constructs, that handles correct codegen
54/// for captured expressions.
55class OMPLexicalScope : public CodeGenFunction::LexicalScope {
56 void emitPreInitStmt(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
57 for (const auto *C : S.clauses()) {
58 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
59 if (const auto *PreInit =
60 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
61 for (const auto *I : PreInit->decls()) {
62 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
63 CGF.EmitVarDecl(cast<VarDecl>(*I));
64 } else {
66 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
67 CGF.EmitAutoVarCleanups(Emission);
68 }
69 }
70 }
71 }
72 }
73 }
75
76 static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
77 return CGF.LambdaCaptureFields.lookup(VD) ||
78 (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
79 (isa_and_nonnull<BlockDecl>(CGF.CurCodeDecl) &&
80 cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD));
81 }
82
83public:
84 OMPLexicalScope(
86 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
87 const bool EmitPreInitStmt = true)
88 : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
89 InlinedShareds(CGF) {
90 if (EmitPreInitStmt)
91 emitPreInitStmt(CGF, S);
92 if (!CapturedRegion)
93 return;
94 assert(S.hasAssociatedStmt() &&
95 "Expected associated statement for inlined directive.");
96 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
97 for (const auto &C : CS->captures()) {
98 if (C.capturesVariable() || C.capturesVariableByCopy()) {
99 auto *VD = C.getCapturedVar();
100 assert(VD == VD->getCanonicalDecl() &&
101 "Canonical decl must be captured.");
102 DeclRefExpr DRE(
103 CGF.getContext(), const_cast<VarDecl *>(VD),
104 isCapturedVar(CGF, VD) || (CGF.CapturedStmtInfo &&
105 InlinedShareds.isGlobalVarCaptured(VD)),
106 VD->getType().getNonReferenceType(), VK_LValue, C.getLocation());
107 InlinedShareds.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
108 }
109 }
110 (void)InlinedShareds.Privatize();
111 }
112};
113
114/// Lexical scope for OpenMP parallel construct, that handles correct codegen
115/// for captured expressions.
116class OMPParallelScope final : public OMPLexicalScope {
117 bool EmitPreInitStmt(const OMPExecutableDirective &S) {
119 return !(isOpenMPTargetExecutionDirective(EKind) ||
122 }
123
124public:
125 OMPParallelScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
126 : OMPLexicalScope(CGF, S, /*CapturedRegion=*/std::nullopt,
127 EmitPreInitStmt(S)) {}
128};
129
130/// Lexical scope for OpenMP teams construct, that handles correct codegen
131/// for captured expressions.
132class OMPTeamsScope final : public OMPLexicalScope {
133 bool EmitPreInitStmt(const OMPExecutableDirective &S) {
135 return !isOpenMPTargetExecutionDirective(EKind) &&
137 }
138
139public:
140 OMPTeamsScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
141 : OMPLexicalScope(CGF, S, /*CapturedRegion=*/std::nullopt,
142 EmitPreInitStmt(S)) {}
143};
144
145/// Private scope for OpenMP loop-based directives, that supports capturing
146/// of used expression from loop statement.
147class OMPLoopScope : public CodeGenFunction::RunCleanupsScope {
148 void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopBasedDirective &S) {
149 const Stmt *PreInits;
150 CodeGenFunction::OMPMapVars PreCondVars;
151 if (auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
152 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
153 for (const auto *E : LD->counters()) {
154 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
155 EmittedAsPrivate.insert(VD->getCanonicalDecl());
156 (void)PreCondVars.setVarAddr(
157 CGF, VD, CGF.CreateMemTemp(VD->getType().getNonReferenceType()));
158 }
159 // Mark private vars as undefs.
160 for (const auto *C : LD->getClausesOfKind<OMPPrivateClause>()) {
161 for (const Expr *IRef : C->varlist()) {
162 const auto *OrigVD =
163 cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
164 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
165 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
166 (void)PreCondVars.setVarAddr(
167 CGF, OrigVD,
168 Address(llvm::UndefValue::get(CGF.ConvertTypeForMem(
169 CGF.getContext().getPointerType(OrigVDTy))),
170 CGF.ConvertTypeForMem(OrigVDTy),
171 CGF.getContext().getDeclAlign(OrigVD)));
172 }
173 }
174 }
175 (void)PreCondVars.apply(CGF);
176 // Emit init, __range and __end variables for C++ range loops.
178 LD->getInnermostCapturedStmt()->getCapturedStmt(),
179 /*TryImperfectlyNestedLoops=*/true, LD->getLoopsNumber(),
180 [&CGF](unsigned Cnt, const Stmt *CurStmt) {
181 if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
182 if (const Stmt *Init = CXXFor->getInit())
183 CGF.EmitStmt(Init);
184 CGF.EmitStmt(CXXFor->getRangeStmt());
185 CGF.EmitStmt(CXXFor->getEndStmt());
186 }
187 return false;
188 });
189 PreInits = LD->getPreInits();
190 } else if (const auto *Tile = dyn_cast<OMPTileDirective>(&S)) {
191 PreInits = Tile->getPreInits();
192 } else if (const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
193 PreInits = Stripe->getPreInits();
194 } else if (const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
195 PreInits = Unroll->getPreInits();
196 } else if (const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
197 PreInits = Reverse->getPreInits();
198 } else if (const auto *Interchange =
199 dyn_cast<OMPInterchangeDirective>(&S)) {
200 PreInits = Interchange->getPreInits();
201 } else {
202 llvm_unreachable("Unknown loop-based directive kind.");
203 }
204 if (PreInits) {
205 // CompoundStmts and DeclStmts are used as lists of PreInit statements and
206 // declarations. Since declarations must be visible in the the following
207 // that they initialize, unpack the CompoundStmt they are nested in.
208 SmallVector<const Stmt *> PreInitStmts;
209 if (auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
210 llvm::append_range(PreInitStmts, PreInitCompound->body());
211 else
212 PreInitStmts.push_back(PreInits);
213
214 for (const Stmt *S : PreInitStmts) {
215 // EmitStmt skips any OMPCapturedExprDecls, but needs to be emitted
216 // here.
217 if (auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
218 for (Decl *I : PreInitDecl->decls())
219 CGF.EmitVarDecl(cast<VarDecl>(*I));
220 continue;
221 }
222 CGF.EmitStmt(S);
223 }
224 }
225 PreCondVars.restore(CGF);
226 }
227
228public:
229 OMPLoopScope(CodeGenFunction &CGF, const OMPLoopBasedDirective &S)
230 : CodeGenFunction::RunCleanupsScope(CGF) {
231 emitPreInitStmt(CGF, S);
232 }
233};
234
235class OMPSimdLexicalScope : public CodeGenFunction::LexicalScope {
237
238 static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
239 return CGF.LambdaCaptureFields.lookup(VD) ||
240 (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
241 (isa_and_nonnull<BlockDecl>(CGF.CurCodeDecl) &&
242 cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD));
243 }
244
245public:
246 OMPSimdLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
247 : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
248 InlinedShareds(CGF) {
249 for (const auto *C : S.clauses()) {
250 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
251 if (const auto *PreInit =
252 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
253 for (const auto *I : PreInit->decls()) {
254 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
255 CGF.EmitVarDecl(cast<VarDecl>(*I));
256 } else {
258 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
259 CGF.EmitAutoVarCleanups(Emission);
260 }
261 }
262 }
263 } else if (const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(C)) {
264 for (const Expr *E : UDP->varlist()) {
265 const Decl *D = cast<DeclRefExpr>(E)->getDecl();
266 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
267 CGF.EmitVarDecl(*OED);
268 }
269 } else if (const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(C)) {
270 for (const Expr *E : UDP->varlist()) {
271 const Decl *D = getBaseDecl(E);
272 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
273 CGF.EmitVarDecl(*OED);
274 }
275 }
276 }
278 CGF.EmitOMPPrivateClause(S, InlinedShareds);
279 if (const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
280 if (const Expr *E = TG->getReductionRef())
281 CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()));
282 }
283 // Temp copy arrays for inscan reductions should not be emitted as they are
284 // not used in simd only mode.
285 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
286 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
287 if (C->getModifier() != OMPC_REDUCTION_inscan)
288 continue;
289 for (const Expr *E : C->copy_array_temps())
290 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
291 }
292 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
293 while (CS) {
294 for (auto &C : CS->captures()) {
295 if (C.capturesVariable() || C.capturesVariableByCopy()) {
296 auto *VD = C.getCapturedVar();
297 if (CopyArrayTemps.contains(VD))
298 continue;
299 assert(VD == VD->getCanonicalDecl() &&
300 "Canonical decl must be captured.");
301 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
302 isCapturedVar(CGF, VD) ||
303 (CGF.CapturedStmtInfo &&
304 InlinedShareds.isGlobalVarCaptured(VD)),
306 C.getLocation());
307 InlinedShareds.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
308 }
309 }
310 CS = dyn_cast<CapturedStmt>(CS->getCapturedStmt());
311 }
312 (void)InlinedShareds.Privatize();
313 }
314};
315
316} // namespace
317
318// The loop directive with a bind clause will be mapped to a different
319// directive with corresponding semantics.
322 OpenMPDirectiveKind Kind = S.getDirectiveKind();
323 if (Kind != OMPD_loop)
324 return Kind;
325
327 if (const auto *C = S.getSingleClause<OMPBindClause>())
328 BindKind = C->getBindKind();
329
330 switch (BindKind) {
331 case OMPC_BIND_parallel:
332 return OMPD_for;
333 case OMPC_BIND_teams:
334 return OMPD_distribute;
335 case OMPC_BIND_thread:
336 return OMPD_simd;
337 default:
338 return OMPD_loop;
339 }
340}
341
343 const OMPExecutableDirective &S,
344 const RegionCodeGenTy &CodeGen);
345
347 if (const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
348 if (const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
349 OrigVD = OrigVD->getCanonicalDecl();
350 bool IsCaptured =
351 LambdaCaptureFields.lookup(OrigVD) ||
353 (isa_and_nonnull<BlockDecl>(CurCodeDecl));
354 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), IsCaptured,
355 OrigDRE->getType(), VK_LValue, OrigDRE->getExprLoc());
356 return EmitLValue(&DRE);
357 }
358 }
359 return EmitLValue(E);
360}
361
364 llvm::Value *Size = nullptr;
365 auto SizeInChars = C.getTypeSizeInChars(Ty);
366 if (SizeInChars.isZero()) {
367 // getTypeSizeInChars() returns 0 for a VLA.
368 while (const VariableArrayType *VAT = C.getAsVariableArrayType(Ty)) {
369 VlaSizePair VlaSize = getVLASize(VAT);
370 Ty = VlaSize.Type;
371 Size =
372 Size ? Builder.CreateNUWMul(Size, VlaSize.NumElts) : VlaSize.NumElts;
373 }
374 SizeInChars = C.getTypeSizeInChars(Ty);
375 if (SizeInChars.isZero())
376 return llvm::ConstantInt::get(SizeTy, /*V=*/0);
377 return Builder.CreateNUWMul(Size, CGM.getSize(SizeInChars));
378 }
379 return CGM.getSize(SizeInChars);
380}
381
383 const CapturedStmt &S, SmallVectorImpl<llvm::Value *> &CapturedVars) {
384 const RecordDecl *RD = S.getCapturedRecordDecl();
385 auto CurField = RD->field_begin();
386 auto CurCap = S.captures().begin();
387 for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(),
388 E = S.capture_init_end();
389 I != E; ++I, ++CurField, ++CurCap) {
390 if (CurField->hasCapturedVLAType()) {
391 const VariableArrayType *VAT = CurField->getCapturedVLAType();
392 llvm::Value *Val = VLASizeMap[VAT->getSizeExpr()];
393 CapturedVars.push_back(Val);
394 } else if (CurCap->capturesThis()) {
395 CapturedVars.push_back(CXXThisValue);
396 } else if (CurCap->capturesVariableByCopy()) {
397 llvm::Value *CV = EmitLoadOfScalar(EmitLValue(*I), CurCap->getLocation());
398
399 // If the field is not a pointer, we need to save the actual value
400 // and load it as a void pointer.
401 if (!CurField->getType()->isAnyPointerType()) {
402 ASTContext &Ctx = getContext();
403 Address DstAddr = CreateMemTemp(
404 Ctx.getUIntPtrType(),
405 Twine(CurCap->getCapturedVar()->getName(), ".casted"));
406 LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
407
408 llvm::Value *SrcAddrVal = EmitScalarConversion(
409 DstAddr.emitRawPointer(*this),
411 Ctx.getPointerType(CurField->getType()), CurCap->getLocation());
412 LValue SrcLV =
413 MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType());
414
415 // Store the value using the source type pointer.
417
418 // Load the value using the destination type pointer.
419 CV = EmitLoadOfScalar(DstLV, CurCap->getLocation());
420 }
421 CapturedVars.push_back(CV);
422 } else {
423 assert(CurCap->capturesVariable() && "Expected capture by reference.");
424 CapturedVars.push_back(EmitLValue(*I).getAddress().emitRawPointer(*this));
425 }
426 }
427}
428
430 QualType DstType, StringRef Name,
431 LValue AddrLV) {
432 ASTContext &Ctx = CGF.getContext();
433
434 llvm::Value *CastedPtr = CGF.EmitScalarConversion(
435 AddrLV.getAddress().emitRawPointer(CGF), Ctx.getUIntPtrType(),
436 Ctx.getPointerType(DstType), Loc);
437 // FIXME: should the pointee type (DstType) be passed?
438 Address TmpAddr =
439 CGF.MakeNaturalAlignAddrLValue(CastedPtr, DstType).getAddress();
440 return TmpAddr;
441}
442
445 return C.getLValueReferenceType(
446 getCanonicalParamType(C, T.getNonReferenceType()),
447 /*SpelledAsLValue=*/false);
448 if (T->isPointerType())
449 return C.getPointerType(getCanonicalParamType(C, T->getPointeeType()));
450 if (const ArrayType *A = T->getAsArrayTypeUnsafe()) {
451 if (const auto *VLA = dyn_cast<VariableArrayType>(A))
452 return getCanonicalParamType(C, VLA->getElementType());
453 if (!A->isVariablyModifiedType())
454 return C.getCanonicalType(T);
455 }
456 return C.getCanonicalParamType(T);
457}
458
459namespace {
460/// Contains required data for proper outlined function codegen.
461struct FunctionOptions {
462 /// Captured statement for which the function is generated.
463 const CapturedStmt *S = nullptr;
464 /// true if cast to/from UIntPtr is required for variables captured by
465 /// value.
466 const bool UIntPtrCastRequired = true;
467 /// true if only casted arguments must be registered as local args or VLA
468 /// sizes.
469 const bool RegisterCastedArgsOnly = false;
470 /// Name of the generated function.
471 const StringRef FunctionName;
472 /// Location of the non-debug version of the outlined function.
474 explicit FunctionOptions(const CapturedStmt *S, bool UIntPtrCastRequired,
475 bool RegisterCastedArgsOnly, StringRef FunctionName,
477 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
478 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
479 FunctionName(FunctionName), Loc(Loc) {}
480};
481} // namespace
482
483static llvm::Function *emitOutlinedFunctionPrologue(
485 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
486 &LocalAddrs,
487 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
488 &VLASizes,
489 llvm::Value *&CXXThisValue, const FunctionOptions &FO) {
490 const CapturedDecl *CD = FO.S->getCapturedDecl();
491 const RecordDecl *RD = FO.S->getCapturedRecordDecl();
492 assert(CD->hasBody() && "missing CapturedDecl body");
493
494 CXXThisValue = nullptr;
495 // Build the argument list.
496 CodeGenModule &CGM = CGF.CGM;
497 ASTContext &Ctx = CGM.getContext();
498 FunctionArgList TargetArgs;
499 Args.append(CD->param_begin(),
500 std::next(CD->param_begin(), CD->getContextParamPosition()));
501 TargetArgs.append(
502 CD->param_begin(),
503 std::next(CD->param_begin(), CD->getContextParamPosition()));
504 auto I = FO.S->captures().begin();
505 FunctionDecl *DebugFunctionDecl = nullptr;
506 if (!FO.UIntPtrCastRequired) {
508 QualType FunctionTy = Ctx.getFunctionType(Ctx.VoidTy, {}, EPI);
509 DebugFunctionDecl = FunctionDecl::Create(
510 Ctx, Ctx.getTranslationUnitDecl(), FO.S->getBeginLoc(),
511 SourceLocation(), DeclarationName(), FunctionTy,
512 Ctx.getTrivialTypeSourceInfo(FunctionTy), SC_Static,
513 /*UsesFPIntrin=*/false, /*isInlineSpecified=*/false,
514 /*hasWrittenPrototype=*/false);
515 }
516 for (const FieldDecl *FD : RD->fields()) {
517 QualType ArgType = FD->getType();
518 IdentifierInfo *II = nullptr;
519 VarDecl *CapVar = nullptr;
520
521 // If this is a capture by copy and the type is not a pointer, the outlined
522 // function argument type should be uintptr and the value properly casted to
523 // uintptr. This is necessary given that the runtime library is only able to
524 // deal with pointers. We can pass in the same way the VLA type sizes to the
525 // outlined function.
526 if (FO.UIntPtrCastRequired &&
527 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
528 I->capturesVariableArrayType()))
529 ArgType = Ctx.getUIntPtrType();
530
531 if (I->capturesVariable() || I->capturesVariableByCopy()) {
532 CapVar = I->getCapturedVar();
533 II = CapVar->getIdentifier();
534 } else if (I->capturesThis()) {
535 II = &Ctx.Idents.get("this");
536 } else {
537 assert(I->capturesVariableArrayType());
538 II = &Ctx.Idents.get("vla");
539 }
540 if (ArgType->isVariablyModifiedType())
541 ArgType = getCanonicalParamType(Ctx, ArgType);
542 VarDecl *Arg;
543 if (CapVar && (CapVar->getTLSKind() != clang::VarDecl::TLS_None)) {
544 Arg = ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(),
545 II, ArgType,
547 } else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
549 Ctx, DebugFunctionDecl,
550 CapVar ? CapVar->getBeginLoc() : FD->getBeginLoc(),
551 CapVar ? CapVar->getLocation() : FD->getLocation(), II, ArgType,
552 /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr);
553 } else {
554 Arg = ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(),
555 II, ArgType, ImplicitParamKind::Other);
556 }
557 Args.emplace_back(Arg);
558 // Do not cast arguments if we emit function with non-original types.
559 TargetArgs.emplace_back(
560 FO.UIntPtrCastRequired
561 ? Arg
562 : CGM.getOpenMPRuntime().translateParameter(FD, Arg));
563 ++I;
564 }
565 Args.append(std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
566 CD->param_end());
567 TargetArgs.append(
568 std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
569 CD->param_end());
570
571 // Create the function declaration.
572 const CGFunctionInfo &FuncInfo =
574 llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
575
576 auto *F =
577 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
578 FO.FunctionName, &CGM.getModule());
579 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
580 if (CD->isNothrow())
581 F->setDoesNotThrow();
582 F->setDoesNotRecurse();
583
584 // Always inline the outlined function if optimizations are enabled.
585 if (CGM.getCodeGenOpts().OptimizationLevel != 0) {
586 F->removeFnAttr(llvm::Attribute::NoInline);
587 F->addFnAttr(llvm::Attribute::AlwaysInline);
588 }
589
590 // Generate the function.
591 CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, TargetArgs,
592 FO.UIntPtrCastRequired ? FO.Loc : FO.S->getBeginLoc(),
593 FO.UIntPtrCastRequired ? FO.Loc
594 : CD->getBody()->getBeginLoc());
595 unsigned Cnt = CD->getContextParamPosition();
596 I = FO.S->captures().begin();
597 for (const FieldDecl *FD : RD->fields()) {
598 // Do not map arguments if we emit function with non-original types.
599 Address LocalAddr(Address::invalid());
600 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
601 LocalAddr = CGM.getOpenMPRuntime().getParameterAddress(CGF, Args[Cnt],
602 TargetArgs[Cnt]);
603 } else {
604 LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]);
605 }
606 // If we are capturing a pointer by copy we don't need to do anything, just
607 // use the value that we get from the arguments.
608 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
609 const VarDecl *CurVD = I->getCapturedVar();
610 if (!FO.RegisterCastedArgsOnly)
611 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
612 ++Cnt;
613 ++I;
614 continue;
615 }
616
617 LValue ArgLVal = CGF.MakeAddrLValue(LocalAddr, Args[Cnt]->getType(),
619 if (FD->hasCapturedVLAType()) {
620 if (FO.UIntPtrCastRequired) {
621 ArgLVal = CGF.MakeAddrLValue(
622 castValueFromUintptr(CGF, I->getLocation(), FD->getType(),
623 Args[Cnt]->getName(), ArgLVal),
625 }
626 llvm::Value *ExprArg = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation());
627 const VariableArrayType *VAT = FD->getCapturedVLAType();
628 VLASizes.try_emplace(Args[Cnt], VAT->getSizeExpr(), ExprArg);
629 } else if (I->capturesVariable()) {
630 const VarDecl *Var = I->getCapturedVar();
631 QualType VarTy = Var->getType();
632 Address ArgAddr = ArgLVal.getAddress();
633 if (ArgLVal.getType()->isLValueReferenceType()) {
634 ArgAddr = CGF.EmitLoadOfReference(ArgLVal);
635 } else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) {
636 assert(ArgLVal.getType()->isPointerType());
637 ArgAddr = CGF.EmitLoadOfPointer(
638 ArgAddr, ArgLVal.getType()->castAs<PointerType>());
639 }
640 if (!FO.RegisterCastedArgsOnly) {
641 LocalAddrs.insert(
642 {Args[Cnt], {Var, ArgAddr.withAlignment(Ctx.getDeclAlign(Var))}});
643 }
644 } else if (I->capturesVariableByCopy()) {
645 assert(!FD->getType()->isAnyPointerType() &&
646 "Not expecting a captured pointer.");
647 const VarDecl *Var = I->getCapturedVar();
648 LocalAddrs.insert({Args[Cnt],
649 {Var, FO.UIntPtrCastRequired
651 CGF, I->getLocation(), FD->getType(),
652 Args[Cnt]->getName(), ArgLVal)
653 : ArgLVal.getAddress()}});
654 } else {
655 // If 'this' is captured, load it into CXXThisValue.
656 assert(I->capturesThis());
657 CXXThisValue = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation());
658 LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress()}});
659 }
660 ++Cnt;
661 ++I;
662 }
663
664 return F;
665}
666
667llvm::Function *
670 assert(
672 "CapturedStmtInfo should be set when generating the captured function");
673 const CapturedDecl *CD = S.getCapturedDecl();
674 // Build the argument list.
675 bool NeedWrapperFunction =
677 FunctionArgList Args, WrapperArgs;
678 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
679 WrapperLocalAddrs;
680 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
681 WrapperVLASizes;
682 SmallString<256> Buffer;
683 llvm::raw_svector_ostream Out(Buffer);
685
686 CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true);
687 llvm::Function *WrapperF = nullptr;
688 if (NeedWrapperFunction) {
689 // Emit the final kernel early to allow attributes to be added by the
690 // OpenMPI-IR-Builder.
691 FunctionOptions WrapperFO(&S, /*UIntPtrCastRequired=*/true,
692 /*RegisterCastedArgsOnly=*/true,
695 WrapperF =
696 emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes,
697 WrapperCGF.CXXThisValue, WrapperFO);
698 Out << "_debug__";
699 }
700 FunctionOptions FO(&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false,
701 Out.str(), Loc);
702 llvm::Function *F = emitOutlinedFunctionPrologue(
703 *this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
704 CodeGenFunction::OMPPrivateScope LocalScope(*this);
705 for (const auto &LocalAddrPair : WrapperLocalAddrs) {
706 if (LocalAddrPair.second.first) {
707 LocalScope.addPrivate(LocalAddrPair.second.first,
708 LocalAddrPair.second.second);
709 }
710 }
711 (void)LocalScope.Privatize();
712 for (const auto &VLASizePair : WrapperVLASizes)
713 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
714 PGO->assignRegionCounters(GlobalDecl(CD), F);
715 CapturedStmtInfo->EmitBody(*this, CD->getBody());
716 LocalScope.ForceCleanup();
718 if (!NeedWrapperFunction)
719 return F;
720
721 // Reverse the order.
722 WrapperF->removeFromParent();
723 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
724
726 auto *PI = F->arg_begin();
727 for (const auto *Arg : Args) {
728 llvm::Value *CallArg;
729 auto I = LocalAddrs.find(Arg);
730 if (I != LocalAddrs.end()) {
731 LValue LV = WrapperCGF.MakeAddrLValue(
732 I->second.second,
733 I->second.first ? I->second.first->getType() : Arg->getType(),
735 if (LV.getType()->isAnyComplexType())
736 LV.setAddress(LV.getAddress().withElementType(PI->getType()));
737 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
738 } else {
739 auto EI = VLASizes.find(Arg);
740 if (EI != VLASizes.end()) {
741 CallArg = EI->second.second;
742 } else {
743 LValue LV =
744 WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg),
746 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
747 }
748 }
749 CallArgs.emplace_back(WrapperCGF.EmitFromMemory(CallArg, Arg->getType()));
750 ++PI;
751 }
752 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
753 WrapperCGF.FinishFunction();
754 return WrapperF;
755}
756
757//===----------------------------------------------------------------------===//
758// OpenMP Directive Emission
759//===----------------------------------------------------------------------===//
761 Address DestAddr, Address SrcAddr, QualType OriginalType,
762 const llvm::function_ref<void(Address, Address)> CopyGen) {
763 // Perform element-by-element initialization.
764 QualType ElementTy;
765
766 // Drill down to the base element type on both arrays.
767 const ArrayType *ArrayTy = OriginalType->getAsArrayTypeUnsafe();
768 llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr);
769 SrcAddr = SrcAddr.withElementType(DestAddr.getElementType());
770
771 llvm::Value *SrcBegin = SrcAddr.emitRawPointer(*this);
772 llvm::Value *DestBegin = DestAddr.emitRawPointer(*this);
773 // Cast from pointer to array type to pointer to single element.
774 llvm::Value *DestEnd = Builder.CreateInBoundsGEP(DestAddr.getElementType(),
775 DestBegin, NumElements);
776
777 // The basic structure here is a while-do loop.
778 llvm::BasicBlock *BodyBB = createBasicBlock("omp.arraycpy.body");
779 llvm::BasicBlock *DoneBB = createBasicBlock("omp.arraycpy.done");
780 llvm::Value *IsEmpty =
781 Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
782 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
783
784 // Enter the loop body, making that address the current address.
785 llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
786 EmitBlock(BodyBB);
787
788 CharUnits ElementSize = getContext().getTypeSizeInChars(ElementTy);
789
790 llvm::PHINode *SrcElementPHI =
791 Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast");
792 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
793 Address SrcElementCurrent =
794 Address(SrcElementPHI, SrcAddr.getElementType(),
795 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
796
797 llvm::PHINode *DestElementPHI = Builder.CreatePHI(
798 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
799 DestElementPHI->addIncoming(DestBegin, EntryBB);
800 Address DestElementCurrent =
801 Address(DestElementPHI, DestAddr.getElementType(),
802 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
803
804 // Emit copy.
805 CopyGen(DestElementCurrent, SrcElementCurrent);
806
807 // Shift the address forward by one element.
808 llvm::Value *DestElementNext =
809 Builder.CreateConstGEP1_32(DestAddr.getElementType(), DestElementPHI,
810 /*Idx0=*/1, "omp.arraycpy.dest.element");
811 llvm::Value *SrcElementNext =
812 Builder.CreateConstGEP1_32(SrcAddr.getElementType(), SrcElementPHI,
813 /*Idx0=*/1, "omp.arraycpy.src.element");
814 // Check whether we've reached the end.
815 llvm::Value *Done =
816 Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
817 Builder.CreateCondBr(Done, DoneBB, BodyBB);
818 DestElementPHI->addIncoming(DestElementNext, Builder.GetInsertBlock());
819 SrcElementPHI->addIncoming(SrcElementNext, Builder.GetInsertBlock());
820
821 // Done.
822 EmitBlock(DoneBB, /*IsFinished=*/true);
823}
824
826 Address SrcAddr, const VarDecl *DestVD,
827 const VarDecl *SrcVD, const Expr *Copy) {
828 if (OriginalType->isArrayType()) {
829 const auto *BO = dyn_cast<BinaryOperator>(Copy);
830 if (BO && BO->getOpcode() == BO_Assign) {
831 // Perform simple memcpy for simple copying.
832 LValue Dest = MakeAddrLValue(DestAddr, OriginalType);
833 LValue Src = MakeAddrLValue(SrcAddr, OriginalType);
834 EmitAggregateAssign(Dest, Src, OriginalType);
835 } else {
836 // For arrays with complex element types perform element by element
837 // copying.
839 DestAddr, SrcAddr, OriginalType,
840 [this, Copy, SrcVD, DestVD](Address DestElement, Address SrcElement) {
841 // Working with the single array element, so have to remap
842 // destination and source variables to corresponding array
843 // elements.
845 Remap.addPrivate(DestVD, DestElement);
846 Remap.addPrivate(SrcVD, SrcElement);
847 (void)Remap.Privatize();
849 });
850 }
851 } else {
852 // Remap pseudo source variable to private copy.
854 Remap.addPrivate(SrcVD, SrcAddr);
855 Remap.addPrivate(DestVD, DestAddr);
856 (void)Remap.Privatize();
857 // Emit copying of the whole variable.
859 }
860}
861
863 OMPPrivateScope &PrivateScope) {
864 if (!HaveInsertPoint())
865 return false;
867 bool DeviceConstTarget = getLangOpts().OpenMPIsTargetDevice &&
869 bool FirstprivateIsLastprivate = false;
870 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
871 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
872 for (const auto *D : C->varlist())
873 Lastprivates.try_emplace(
874 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl(),
875 C->getKind());
876 }
877 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
879 getOpenMPCaptureRegions(CaptureRegions, EKind);
880 // Force emission of the firstprivate copy if the directive does not emit
881 // outlined function, like omp for, omp simd, omp distribute etc.
882 bool MustEmitFirstprivateCopy =
883 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
884 for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
885 const auto *IRef = C->varlist_begin();
886 const auto *InitsRef = C->inits().begin();
887 for (const Expr *IInit : C->private_copies()) {
888 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
889 bool ThisFirstprivateIsLastprivate =
890 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
891 const FieldDecl *FD = CapturedStmtInfo->lookup(OrigVD);
892 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
893 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
894 !FD->getType()->isReferenceType() &&
895 (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())) {
896 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
897 ++IRef;
898 ++InitsRef;
899 continue;
900 }
901 // Do not emit copy for firstprivate constant variables in target regions,
902 // captured by reference.
903 if (DeviceConstTarget && OrigVD->getType().isConstant(getContext()) &&
904 FD && FD->getType()->isReferenceType() &&
905 (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())) {
906 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
907 ++IRef;
908 ++InitsRef;
909 continue;
910 }
911 FirstprivateIsLastprivate =
912 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
913 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
914 const auto *VDInit =
915 cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
916 bool IsRegistered;
917 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
918 /*RefersToEnclosingVariableOrCapture=*/FD != nullptr,
919 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
920 LValue OriginalLVal;
921 if (!FD) {
922 // Check if the firstprivate variable is just a constant value.
924 if (CE && !CE.isReference()) {
925 // Constant value, no need to create a copy.
926 ++IRef;
927 ++InitsRef;
928 continue;
929 }
930 if (CE && CE.isReference()) {
931 OriginalLVal = CE.getReferenceLValue(*this, &DRE);
932 } else {
933 assert(!CE && "Expected non-constant firstprivate.");
934 OriginalLVal = EmitLValue(&DRE);
935 }
936 } else {
937 OriginalLVal = EmitLValue(&DRE);
938 }
939 QualType Type = VD->getType();
940 if (Type->isArrayType()) {
941 // Emit VarDecl with copy init for arrays.
942 // Get the address of the original variable captured in current
943 // captured region.
944 AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
945 const Expr *Init = VD->getInit();
946 if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) {
947 // Perform simple memcpy.
948 LValue Dest = MakeAddrLValue(Emission.getAllocatedAddress(), Type);
949 EmitAggregateAssign(Dest, OriginalLVal, Type);
950 } else {
952 Emission.getAllocatedAddress(), OriginalLVal.getAddress(), Type,
953 [this, VDInit, Init](Address DestElement, Address SrcElement) {
954 // Clean up any temporaries needed by the
955 // initialization.
956 RunCleanupsScope InitScope(*this);
957 // Emit initialization for single element.
958 setAddrOfLocalVar(VDInit, SrcElement);
959 EmitAnyExprToMem(Init, DestElement,
960 Init->getType().getQualifiers(),
961 /*IsInitializer*/ false);
962 LocalDeclMap.erase(VDInit);
963 });
964 }
965 EmitAutoVarCleanups(Emission);
966 IsRegistered =
967 PrivateScope.addPrivate(OrigVD, Emission.getAllocatedAddress());
968 } else {
969 Address OriginalAddr = OriginalLVal.getAddress();
970 // Emit private VarDecl with copy init.
971 // Remap temp VDInit variable to the address of the original
972 // variable (for proper handling of captured global variables).
973 setAddrOfLocalVar(VDInit, OriginalAddr);
974 EmitDecl(*VD);
975 LocalDeclMap.erase(VDInit);
976 Address VDAddr = GetAddrOfLocalVar(VD);
977 if (ThisFirstprivateIsLastprivate &&
978 Lastprivates[OrigVD->getCanonicalDecl()] ==
979 OMPC_LASTPRIVATE_conditional) {
980 // Create/init special variable for lastprivate conditionals.
981 llvm::Value *V =
982 EmitLoadOfScalar(MakeAddrLValue(VDAddr, (*IRef)->getType(),
984 (*IRef)->getExprLoc());
986 *this, OrigVD);
987 EmitStoreOfScalar(V, MakeAddrLValue(VDAddr, (*IRef)->getType(),
989 LocalDeclMap.erase(VD);
990 setAddrOfLocalVar(VD, VDAddr);
991 }
992 IsRegistered = PrivateScope.addPrivate(OrigVD, VDAddr);
993 }
994 assert(IsRegistered &&
995 "firstprivate var already registered as private");
996 // Silence the warning about unused variable.
997 (void)IsRegistered;
998 }
999 ++IRef;
1000 ++InitsRef;
1001 }
1002 }
1003 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1004}
1005
1008 CodeGenFunction::OMPPrivateScope &PrivateScope) {
1009 if (!HaveInsertPoint())
1010 return;
1011 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1012 for (const auto *C : D.getClausesOfKind<OMPPrivateClause>()) {
1013 auto IRef = C->varlist_begin();
1014 for (const Expr *IInit : C->private_copies()) {
1015 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
1016 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1017 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
1018 EmitDecl(*VD);
1019 // Emit private VarDecl with copy init.
1020 bool IsRegistered =
1021 PrivateScope.addPrivate(OrigVD, GetAddrOfLocalVar(VD));
1022 assert(IsRegistered && "private var already registered as private");
1023 // Silence the warning about unused variable.
1024 (void)IsRegistered;
1025 }
1026 ++IRef;
1027 }
1028 }
1029}
1030
1032 if (!HaveInsertPoint())
1033 return false;
1034 // threadprivate_var1 = master_threadprivate_var1;
1035 // operator=(threadprivate_var2, master_threadprivate_var2);
1036 // ...
1037 // __kmpc_barrier(&loc, global_tid);
1038 llvm::DenseSet<const VarDecl *> CopiedVars;
1039 llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr;
1040 for (const auto *C : D.getClausesOfKind<OMPCopyinClause>()) {
1041 auto IRef = C->varlist_begin();
1042 auto ISrcRef = C->source_exprs().begin();
1043 auto IDestRef = C->destination_exprs().begin();
1044 for (const Expr *AssignOp : C->assignment_ops()) {
1045 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
1046 QualType Type = VD->getType();
1047 if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
1048 // Get the address of the master variable. If we are emitting code with
1049 // TLS support, the address is passed from the master as field in the
1050 // captured declaration.
1051 Address MasterAddr = Address::invalid();
1052 if (getLangOpts().OpenMPUseTLS &&
1053 getContext().getTargetInfo().isTLSSupported()) {
1054 assert(CapturedStmtInfo->lookup(VD) &&
1055 "Copyin threadprivates should have been captured!");
1056 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD), true,
1057 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
1058 MasterAddr = EmitLValue(&DRE).getAddress();
1059 LocalDeclMap.erase(VD);
1060 } else {
1061 MasterAddr =
1063 : CGM.GetAddrOfGlobal(VD),
1065 getContext().getDeclAlign(VD));
1066 }
1067 // Get the address of the threadprivate variable.
1068 Address PrivateAddr = EmitLValue(*IRef).getAddress();
1069 if (CopiedVars.size() == 1) {
1070 // At first check if current thread is a master thread. If it is, no
1071 // need to copy data.
1072 CopyBegin = createBasicBlock("copyin.not.master");
1073 CopyEnd = createBasicBlock("copyin.not.master.end");
1074 // TODO: Avoid ptrtoint conversion.
1075 auto *MasterAddrInt = Builder.CreatePtrToInt(
1076 MasterAddr.emitRawPointer(*this), CGM.IntPtrTy);
1077 auto *PrivateAddrInt = Builder.CreatePtrToInt(
1078 PrivateAddr.emitRawPointer(*this), CGM.IntPtrTy);
1079 Builder.CreateCondBr(
1080 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1081 CopyEnd);
1082 EmitBlock(CopyBegin);
1083 }
1084 const auto *SrcVD =
1085 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
1086 const auto *DestVD =
1087 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
1088 EmitOMPCopy(Type, PrivateAddr, MasterAddr, DestVD, SrcVD, AssignOp);
1089 }
1090 ++IRef;
1091 ++ISrcRef;
1092 ++IDestRef;
1093 }
1094 }
1095 if (CopyEnd) {
1096 // Exit out of copying procedure for non-master thread.
1097 EmitBlock(CopyEnd, /*IsFinished=*/true);
1098 return true;
1099 }
1100 return false;
1101}
1102
1104 const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) {
1105 if (!HaveInsertPoint())
1106 return false;
1107 bool HasAtLeastOneLastprivate = false;
1109 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1110 if (isOpenMPSimdDirective(EKind)) {
1111 const auto *LoopDirective = cast<OMPLoopDirective>(&D);
1112 for (const Expr *C : LoopDirective->counters()) {
1113 SIMDLCVs.insert(
1114 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
1115 }
1116 }
1117 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1118 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
1119 HasAtLeastOneLastprivate = true;
1120 if (isOpenMPTaskLoopDirective(EKind) && !getLangOpts().OpenMPSimd)
1121 break;
1122 const auto *IRef = C->varlist_begin();
1123 const auto *IDestRef = C->destination_exprs().begin();
1124 for (const Expr *IInit : C->private_copies()) {
1125 // Keep the address of the original variable for future update at the end
1126 // of the loop.
1127 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
1128 // Taskloops do not require additional initialization, it is done in
1129 // runtime support library.
1130 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1131 const auto *DestVD =
1132 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
1133 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
1134 /*RefersToEnclosingVariableOrCapture=*/
1135 CapturedStmtInfo->lookup(OrigVD) != nullptr,
1136 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
1137 PrivateScope.addPrivate(DestVD, EmitLValue(&DRE).getAddress());
1138 // Check if the variable is also a firstprivate: in this case IInit is
1139 // not generated. Initialization of this variable will happen in codegen
1140 // for 'firstprivate' clause.
1141 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1142 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
1143 Address VDAddr = Address::invalid();
1144 if (C->getKind() == OMPC_LASTPRIVATE_conditional) {
1146 *this, OrigVD);
1147 setAddrOfLocalVar(VD, VDAddr);
1148 } else {
1149 // Emit private VarDecl with copy init.
1150 EmitDecl(*VD);
1151 VDAddr = GetAddrOfLocalVar(VD);
1152 }
1153 bool IsRegistered = PrivateScope.addPrivate(OrigVD, VDAddr);
1154 assert(IsRegistered &&
1155 "lastprivate var already registered as private");
1156 (void)IsRegistered;
1157 }
1158 }
1159 ++IRef;
1160 ++IDestRef;
1161 }
1162 }
1163 return HasAtLeastOneLastprivate;
1164}
1165
1167 const OMPExecutableDirective &D, bool NoFinals,
1168 llvm::Value *IsLastIterCond) {
1169 if (!HaveInsertPoint())
1170 return;
1171 // Emit following code:
1172 // if (<IsLastIterCond>) {
1173 // orig_var1 = private_orig_var1;
1174 // ...
1175 // orig_varn = private_orig_varn;
1176 // }
1177 llvm::BasicBlock *ThenBB = nullptr;
1178 llvm::BasicBlock *DoneBB = nullptr;
1179 if (IsLastIterCond) {
1180 // Emit implicit barrier if at least one lastprivate conditional is found
1181 // and this is not a simd mode.
1182 if (!getLangOpts().OpenMPSimd &&
1183 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1184 [](const OMPLastprivateClause *C) {
1185 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1186 })) {
1188 OMPD_unknown,
1189 /*EmitChecks=*/false,
1190 /*ForceSimpleCall=*/true);
1191 }
1192 ThenBB = createBasicBlock(".omp.lastprivate.then");
1193 DoneBB = createBasicBlock(".omp.lastprivate.done");
1194 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1195 EmitBlock(ThenBB);
1196 }
1197 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1198 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1199 if (const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1200 auto IC = LoopDirective->counters().begin();
1201 for (const Expr *F : LoopDirective->finals()) {
1202 const auto *D =
1203 cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl())->getCanonicalDecl();
1204 if (NoFinals)
1205 AlreadyEmittedVars.insert(D);
1206 else
1207 LoopCountersAndUpdates[D] = F;
1208 ++IC;
1209 }
1210 }
1211 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
1212 auto IRef = C->varlist_begin();
1213 auto ISrcRef = C->source_exprs().begin();
1214 auto IDestRef = C->destination_exprs().begin();
1215 for (const Expr *AssignOp : C->assignment_ops()) {
1216 const auto *PrivateVD =
1217 cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
1218 QualType Type = PrivateVD->getType();
1219 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1220 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1221 // If lastprivate variable is a loop control variable for loop-based
1222 // directive, update its value before copyin back to original
1223 // variable.
1224 if (const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1225 EmitIgnoredExpr(FinalExpr);
1226 const auto *SrcVD =
1227 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
1228 const auto *DestVD =
1229 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
1230 // Get the address of the private variable.
1231 Address PrivateAddr = GetAddrOfLocalVar(PrivateVD);
1232 if (const auto *RefTy = PrivateVD->getType()->getAs<ReferenceType>())
1233 PrivateAddr = Address(
1234 Builder.CreateLoad(PrivateAddr),
1235 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1236 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1237 // Store the last value to the private copy in the last iteration.
1238 if (C->getKind() == OMPC_LASTPRIVATE_conditional)
1240 *this, MakeAddrLValue(PrivateAddr, (*IRef)->getType()), PrivateVD,
1241 (*IRef)->getExprLoc());
1242 // Get the address of the original variable.
1243 Address OriginalAddr = GetAddrOfLocalVar(DestVD);
1244 EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1245 }
1246 ++IRef;
1247 ++ISrcRef;
1248 ++IDestRef;
1249 }
1250 if (const Expr *PostUpdate = C->getPostUpdateExpr())
1251 EmitIgnoredExpr(PostUpdate);
1252 }
1253 if (IsLastIterCond)
1254 EmitBlock(DoneBB, /*IsFinished=*/true);
1255}
1256
1259 CodeGenFunction::OMPPrivateScope &PrivateScope, bool ForInscan) {
1260 if (!HaveInsertPoint())
1261 return;
1264 SmallVector<const Expr *, 4> ReductionOps;
1270 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
1271 if (ForInscan != (C->getModifier() == OMPC_REDUCTION_inscan))
1272 continue;
1273 Shareds.append(C->varlist_begin(), C->varlist_end());
1274 Privates.append(C->privates().begin(), C->privates().end());
1275 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
1276 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
1277 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
1278 if (C->getModifier() == OMPC_REDUCTION_task) {
1279 Data.ReductionVars.append(C->privates().begin(), C->privates().end());
1280 Data.ReductionOrigs.append(C->varlist_begin(), C->varlist_end());
1281 Data.ReductionCopies.append(C->privates().begin(), C->privates().end());
1282 Data.ReductionOps.append(C->reduction_ops().begin(),
1283 C->reduction_ops().end());
1284 TaskLHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
1285 TaskRHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
1286 }
1287 }
1288 ReductionCodeGen RedCG(Shareds, Shareds, Privates, ReductionOps);
1289 unsigned Count = 0;
1290 auto *ILHS = LHSs.begin();
1291 auto *IRHS = RHSs.begin();
1292 auto *IPriv = Privates.begin();
1293 for (const Expr *IRef : Shareds) {
1294 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());
1295 // Emit private VarDecl with reduction init.
1296 RedCG.emitSharedOrigLValue(*this, Count);
1297 RedCG.emitAggregateType(*this, Count);
1298 AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD);
1299 RedCG.emitInitialization(*this, Count, Emission.getAllocatedAddress(),
1300 RedCG.getSharedLValue(Count).getAddress(),
1301 [&Emission](CodeGenFunction &CGF) {
1302 CGF.EmitAutoVarInit(Emission);
1303 return true;
1304 });
1305 EmitAutoVarCleanups(Emission);
1306 Address BaseAddr = RedCG.adjustPrivateAddress(
1307 *this, Count, Emission.getAllocatedAddress());
1308 bool IsRegistered =
1309 PrivateScope.addPrivate(RedCG.getBaseDecl(Count), BaseAddr);
1310 assert(IsRegistered && "private var already registered as private");
1311 // Silence the warning about unused variable.
1312 (void)IsRegistered;
1313
1314 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
1315 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
1316 QualType Type = PrivateVD->getType();
1317 bool isaOMPArraySectionExpr = isa<ArraySectionExpr>(IRef);
1318 if (isaOMPArraySectionExpr && Type->isVariablyModifiedType()) {
1319 // Store the address of the original variable associated with the LHS
1320 // implicit variable.
1321 PrivateScope.addPrivate(LHSVD, RedCG.getSharedLValue(Count).getAddress());
1322 PrivateScope.addPrivate(RHSVD, GetAddrOfLocalVar(PrivateVD));
1323 } else if ((isaOMPArraySectionExpr && Type->isScalarType()) ||
1324 isa<ArraySubscriptExpr>(IRef)) {
1325 // Store the address of the original variable associated with the LHS
1326 // implicit variable.
1327 PrivateScope.addPrivate(LHSVD, RedCG.getSharedLValue(Count).getAddress());
1328 PrivateScope.addPrivate(RHSVD,
1329 GetAddrOfLocalVar(PrivateVD).withElementType(
1330 ConvertTypeForMem(RHSVD->getType())));
1331 } else {
1332 QualType Type = PrivateVD->getType();
1333 bool IsArray = getContext().getAsArrayType(Type) != nullptr;
1334 Address OriginalAddr = RedCG.getSharedLValue(Count).getAddress();
1335 // Store the address of the original variable associated with the LHS
1336 // implicit variable.
1337 if (IsArray) {
1338 OriginalAddr =
1339 OriginalAddr.withElementType(ConvertTypeForMem(LHSVD->getType()));
1340 }
1341 PrivateScope.addPrivate(LHSVD, OriginalAddr);
1342 PrivateScope.addPrivate(
1343 RHSVD, IsArray ? GetAddrOfLocalVar(PrivateVD).withElementType(
1344 ConvertTypeForMem(RHSVD->getType()))
1345 : GetAddrOfLocalVar(PrivateVD));
1346 }
1347 ++ILHS;
1348 ++IRHS;
1349 ++IPriv;
1350 ++Count;
1351 }
1352 if (!Data.ReductionVars.empty()) {
1354 Data.IsReductionWithTaskMod = true;
1355 Data.IsWorksharingReduction = isOpenMPWorksharingDirective(EKind);
1356 llvm::Value *ReductionDesc = CGM.getOpenMPRuntime().emitTaskReductionInit(
1357 *this, D.getBeginLoc(), TaskLHSs, TaskRHSs, Data);
1358 const Expr *TaskRedRef = nullptr;
1359 switch (EKind) {
1360 case OMPD_parallel:
1361 TaskRedRef = cast<OMPParallelDirective>(D).getTaskReductionRefExpr();
1362 break;
1363 case OMPD_for:
1364 TaskRedRef = cast<OMPForDirective>(D).getTaskReductionRefExpr();
1365 break;
1366 case OMPD_sections:
1367 TaskRedRef = cast<OMPSectionsDirective>(D).getTaskReductionRefExpr();
1368 break;
1369 case OMPD_parallel_for:
1370 TaskRedRef = cast<OMPParallelForDirective>(D).getTaskReductionRefExpr();
1371 break;
1372 case OMPD_parallel_master:
1373 TaskRedRef =
1374 cast<OMPParallelMasterDirective>(D).getTaskReductionRefExpr();
1375 break;
1376 case OMPD_parallel_sections:
1377 TaskRedRef =
1378 cast<OMPParallelSectionsDirective>(D).getTaskReductionRefExpr();
1379 break;
1380 case OMPD_target_parallel:
1381 TaskRedRef =
1382 cast<OMPTargetParallelDirective>(D).getTaskReductionRefExpr();
1383 break;
1384 case OMPD_target_parallel_for:
1385 TaskRedRef =
1386 cast<OMPTargetParallelForDirective>(D).getTaskReductionRefExpr();
1387 break;
1388 case OMPD_distribute_parallel_for:
1389 TaskRedRef =
1390 cast<OMPDistributeParallelForDirective>(D).getTaskReductionRefExpr();
1391 break;
1392 case OMPD_teams_distribute_parallel_for:
1393 TaskRedRef = cast<OMPTeamsDistributeParallelForDirective>(D)
1394 .getTaskReductionRefExpr();
1395 break;
1396 case OMPD_target_teams_distribute_parallel_for:
1397 TaskRedRef = cast<OMPTargetTeamsDistributeParallelForDirective>(D)
1398 .getTaskReductionRefExpr();
1399 break;
1400 case OMPD_simd:
1401 case OMPD_for_simd:
1402 case OMPD_section:
1403 case OMPD_single:
1404 case OMPD_master:
1405 case OMPD_critical:
1406 case OMPD_parallel_for_simd:
1407 case OMPD_task:
1408 case OMPD_taskyield:
1409 case OMPD_error:
1410 case OMPD_barrier:
1411 case OMPD_taskwait:
1412 case OMPD_taskgroup:
1413 case OMPD_flush:
1414 case OMPD_depobj:
1415 case OMPD_scan:
1416 case OMPD_ordered:
1417 case OMPD_atomic:
1418 case OMPD_teams:
1419 case OMPD_target:
1420 case OMPD_cancellation_point:
1421 case OMPD_cancel:
1422 case OMPD_target_data:
1423 case OMPD_target_enter_data:
1424 case OMPD_target_exit_data:
1425 case OMPD_taskloop:
1426 case OMPD_taskloop_simd:
1427 case OMPD_master_taskloop:
1428 case OMPD_master_taskloop_simd:
1429 case OMPD_parallel_master_taskloop:
1430 case OMPD_parallel_master_taskloop_simd:
1431 case OMPD_distribute:
1432 case OMPD_target_update:
1433 case OMPD_distribute_parallel_for_simd:
1434 case OMPD_distribute_simd:
1435 case OMPD_target_parallel_for_simd:
1436 case OMPD_target_simd:
1437 case OMPD_teams_distribute:
1438 case OMPD_teams_distribute_simd:
1439 case OMPD_teams_distribute_parallel_for_simd:
1440 case OMPD_target_teams:
1441 case OMPD_target_teams_distribute:
1442 case OMPD_target_teams_distribute_parallel_for_simd:
1443 case OMPD_target_teams_distribute_simd:
1444 case OMPD_declare_target:
1445 case OMPD_end_declare_target:
1446 case OMPD_threadprivate:
1447 case OMPD_allocate:
1448 case OMPD_declare_reduction:
1449 case OMPD_declare_mapper:
1450 case OMPD_declare_simd:
1451 case OMPD_requires:
1452 case OMPD_declare_variant:
1453 case OMPD_begin_declare_variant:
1454 case OMPD_end_declare_variant:
1455 case OMPD_unknown:
1456 default:
1457 llvm_unreachable("Unexpected directive with task reductions.");
1458 }
1459
1460 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(TaskRedRef)->getDecl());
1461 EmitVarDecl(*VD);
1462 EmitStoreOfScalar(ReductionDesc, GetAddrOfLocalVar(VD),
1463 /*Volatile=*/false, TaskRedRef->getType());
1464 }
1465}
1466
1468 const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind) {
1469 if (!HaveInsertPoint())
1470 return;
1475 llvm::SmallVector<bool, 8> IsPrivateVarReduction;
1476 bool HasAtLeastOneReduction = false;
1477 bool IsReductionWithTaskMod = false;
1478 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
1479 // Do not emit for inscan reductions.
1480 if (C->getModifier() == OMPC_REDUCTION_inscan)
1481 continue;
1482 HasAtLeastOneReduction = true;
1483 Privates.append(C->privates().begin(), C->privates().end());
1484 LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
1485 RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
1486 IsPrivateVarReduction.append(C->private_var_reduction_flags().begin(),
1487 C->private_var_reduction_flags().end());
1488 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
1489 IsReductionWithTaskMod =
1490 IsReductionWithTaskMod || C->getModifier() == OMPC_REDUCTION_task;
1491 }
1492 if (HasAtLeastOneReduction) {
1494 if (IsReductionWithTaskMod) {
1496 *this, D.getBeginLoc(), isOpenMPWorksharingDirective(EKind));
1497 }
1498 bool TeamsLoopCanBeParallel = false;
1499 if (auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1500 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1501 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1503 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1504 bool SimpleReduction = ReductionKind == OMPD_simd;
1505 // Emit nowait reduction if nowait clause is present or directive is a
1506 // parallel directive (it always has implicit barrier).
1508 *this, D.getEndLoc(), Privates, LHSExprs, RHSExprs, ReductionOps,
1509 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1510 }
1511}
1512
1515 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
1516 if (!CGF.HaveInsertPoint())
1517 return;
1518 llvm::BasicBlock *DoneBB = nullptr;
1519 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
1520 if (const Expr *PostUpdate = C->getPostUpdateExpr()) {
1521 if (!DoneBB) {
1522 if (llvm::Value *Cond = CondGen(CGF)) {
1523 // If the first post-update expression is found, emit conditional
1524 // block if it was requested.
1525 llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".omp.reduction.pu");
1526 DoneBB = CGF.createBasicBlock(".omp.reduction.pu.done");
1527 CGF.Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1528 CGF.EmitBlock(ThenBB);
1529 }
1530 }
1531 CGF.EmitIgnoredExpr(PostUpdate);
1532 }
1533 }
1534 if (DoneBB)
1535 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
1536}
1537
1538namespace {
1539/// Codegen lambda for appending distribute lower and upper bounds to outlined
1540/// parallel function. This is necessary for combined constructs such as
1541/// 'distribute parallel for'
1542typedef llvm::function_ref<void(CodeGenFunction &,
1543 const OMPExecutableDirective &,
1545 CodeGenBoundParametersTy;
1546} // anonymous namespace
1547
1548static void
1550 const OMPExecutableDirective &S) {
1551 if (CGF.getLangOpts().OpenMP < 50)
1552 return;
1553 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1554 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
1555 for (const Expr *Ref : C->varlist()) {
1556 if (!Ref->getType()->isScalarType())
1557 continue;
1558 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1559 if (!DRE)
1560 continue;
1561 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1563 }
1564 }
1565 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
1566 for (const Expr *Ref : C->varlist()) {
1567 if (!Ref->getType()->isScalarType())
1568 continue;
1569 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1570 if (!DRE)
1571 continue;
1572 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1574 }
1575 }
1576 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
1577 for (const Expr *Ref : C->varlist()) {
1578 if (!Ref->getType()->isScalarType())
1579 continue;
1580 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1581 if (!DRE)
1582 continue;
1583 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1585 }
1586 }
1587 // Privates should ne analyzed since they are not captured at all.
1588 // Task reductions may be skipped - tasks are ignored.
1589 // Firstprivates do not return value but may be passed by reference - no need
1590 // to check for updated lastprivate conditional.
1591 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1592 for (const Expr *Ref : C->varlist()) {
1593 if (!Ref->getType()->isScalarType())
1594 continue;
1595 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1596 if (!DRE)
1597 continue;
1598 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1599 }
1600 }
1602 CGF, S, PrivateDecls);
1603}
1604
1607 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1608 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1609 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1610 llvm::Value *NumThreads = nullptr;
1612 // OpenMP 6.0, 10.4: "If no severity clause is specified then the effect is as
1613 // if sev-level is fatal."
1614 OpenMPSeverityClauseKind Severity = OMPC_SEVERITY_fatal;
1615 clang::Expr *Message = nullptr;
1616 llvm::Function *OutlinedFn =
1618 CGF, S, *CS->getCapturedDecl()->param_begin(), InnermostKind,
1619 CodeGen);
1620 if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) {
1621 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
1622 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
1623 /*IgnoreResultAssign=*/true);
1624 Modifier = NumThreadsClause->getModifier();
1625 if (const auto *MessageClause = S.getSingleClause<OMPMessageClause>())
1626 Message = MessageClause->getMessageString();
1627 if (const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>())
1628 Severity = SeverityClause->getSeverityKind();
1630 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1631 Message);
1632 }
1633 if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
1634 CodeGenFunction::RunCleanupsScope ProcBindScope(CGF);
1636 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1637 }
1638 const Expr *IfCond = nullptr;
1639 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
1640 if (C->getNameModifier() == OMPD_unknown ||
1641 C->getNameModifier() == OMPD_parallel) {
1642 IfCond = C->getCondition();
1643 break;
1644 }
1645 }
1646
1647 OMPParallelScope Scope(CGF, S);
1649 // Combining 'distribute' with 'for' requires sharing each 'distribute' chunk
1650 // lower and upper bounds with the pragma 'for' chunking mechanism.
1651 // The following lambda takes care of appending the lower and upper bound
1652 // parameters when necessary
1653 CodeGenBoundParameters(CGF, S, CapturedVars);
1654 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
1655 CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getBeginLoc(), OutlinedFn,
1656 CapturedVars, IfCond, NumThreads,
1657 Modifier, Severity, Message);
1658}
1659
1660static bool isAllocatableDecl(const VarDecl *VD) {
1661 const VarDecl *CVD = VD->getCanonicalDecl();
1662 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
1663 return false;
1664 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
1665 // Use the default allocation.
1666 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1667 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1668 !AA->getAllocator());
1669}
1670
1672 const OMPExecutableDirective &,
1674
1676 const OMPExecutableDirective &S) {
1677 bool Copyins = CGF.EmitOMPCopyinClause(S);
1678 if (Copyins) {
1679 // Emit implicit barrier to synchronize threads and avoid data races on
1680 // propagation master's thread values of threadprivate variables to local
1681 // instances of that variables of all other implicit threads.
1683 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
1684 /*ForceSimpleCall=*/true);
1685 }
1686}
1687
1689 CodeGenFunction &CGF, const VarDecl *VD) {
1690 CodeGenModule &CGM = CGF.CGM;
1691 auto &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
1692
1693 if (!VD)
1694 return Address::invalid();
1695 const VarDecl *CVD = VD->getCanonicalDecl();
1696 if (!isAllocatableDecl(CVD))
1697 return Address::invalid();
1698 llvm::Value *Size;
1699 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
1700 if (CVD->getType()->isVariablyModifiedType()) {
1701 Size = CGF.getTypeSize(CVD->getType());
1702 // Align the size: ((size + align - 1) / align) * align
1703 Size = CGF.Builder.CreateNUWAdd(
1704 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
1705 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
1706 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
1707 } else {
1709 Size = CGM.getSize(Sz.alignTo(Align));
1710 }
1711
1712 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
1713 assert(AA->getAllocator() &&
1714 "Expected allocator expression for non-default allocator.");
1715 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
1716 // According to the standard, the original allocator type is a enum (integer).
1717 // Convert to pointer type, if required.
1718 if (Allocator->getType()->isIntegerTy())
1719 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
1720 else if (Allocator->getType()->isPointerTy())
1721 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
1722 CGM.VoidPtrTy);
1723
1724 llvm::Value *Addr = OMPBuilder.createOMPAlloc(
1725 CGF.Builder, Size, Allocator,
1726 getNameWithSeparators({CVD->getName(), ".void.addr"}, ".", "."));
1727 llvm::CallInst *FreeCI =
1728 OMPBuilder.createOMPFree(CGF.Builder, Addr, Allocator);
1729
1730 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FreeCI);
1732 Addr,
1734 getNameWithSeparators({CVD->getName(), ".addr"}, ".", "."));
1735 return Address(Addr, CGF.ConvertTypeForMem(CVD->getType()), Align);
1736}
1737
1739 CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr,
1741 CodeGenModule &CGM = CGF.CGM;
1742 if (CGM.getLangOpts().OpenMPUseTLS &&
1744 return VDAddr;
1745
1746 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
1747
1748 llvm::Type *VarTy = VDAddr.getElementType();
1749 llvm::Value *Data =
1750 CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy);
1751 llvm::ConstantInt *Size = CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy));
1752 std::string Suffix = getNameWithSeparators({"cache", ""});
1753 llvm::Twine CacheName = Twine(CGM.getMangledName(VD)).concat(Suffix);
1754
1755 llvm::CallInst *ThreadPrivateCacheCall =
1756 OMPBuilder.createCachedThreadPrivate(CGF.Builder, Data, Size, CacheName);
1757
1758 return Address(ThreadPrivateCacheCall, CGM.Int8Ty, VDAddr.getAlignment());
1759}
1760
1762 ArrayRef<StringRef> Parts, StringRef FirstSeparator, StringRef Separator) {
1763 SmallString<128> Buffer;
1764 llvm::raw_svector_ostream OS(Buffer);
1765 StringRef Sep = FirstSeparator;
1766 for (StringRef Part : Parts) {
1767 OS << Sep << Part;
1768 Sep = Separator;
1769 }
1770 return OS.str().str();
1771}
1772
1774 CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP,
1775 InsertPointTy CodeGenIP, Twine RegionName) {
1777 Builder.restoreIP(CodeGenIP);
1778 llvm::BasicBlock *FiniBB = splitBBWithSuffix(Builder, /*CreateBranch=*/false,
1779 "." + RegionName + ".after");
1780
1781 {
1782 OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(CGF, AllocaIP, *FiniBB);
1783 CGF.EmitStmt(RegionBodyStmt);
1784 }
1785
1786 if (Builder.saveIP().isSet())
1787 Builder.CreateBr(FiniBB);
1788}
1789
1791 CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP,
1792 InsertPointTy CodeGenIP, Twine RegionName) {
1794 Builder.restoreIP(CodeGenIP);
1795 llvm::BasicBlock *FiniBB = splitBBWithSuffix(Builder, /*CreateBranch=*/false,
1796 "." + RegionName + ".after");
1797
1798 {
1799 OMPBuilderCBHelpers::OutlinedRegionBodyRAII IRB(CGF, AllocaIP, *FiniBB);
1800 CGF.EmitStmt(RegionBodyStmt);
1801 }
1802
1803 if (Builder.saveIP().isSet())
1804 Builder.CreateBr(FiniBB);
1805}
1806
1808 if (CGM.getLangOpts().OpenMPIRBuilder) {
1809 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
1810 // Check if we have any if clause associated with the directive.
1811 llvm::Value *IfCond = nullptr;
1812 if (const auto *C = S.getSingleClause<OMPIfClause>())
1813 IfCond = EmitScalarExpr(C->getCondition(),
1814 /*IgnoreResultAssign=*/true);
1815
1816 llvm::Value *NumThreads = nullptr;
1817 if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>())
1818 NumThreads = EmitScalarExpr(NumThreadsClause->getNumThreads(),
1819 /*IgnoreResultAssign=*/true);
1820
1821 ProcBindKind ProcBind = OMP_PROC_BIND_default;
1822 if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
1823 ProcBind = ProcBindClause->getProcBindKind();
1824
1825 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1826
1827 // The cleanup callback that finalizes all variables at the given location,
1828 // thus calls destructors etc.
1829 auto FiniCB = [this](InsertPointTy IP) {
1831 return llvm::Error::success();
1832 };
1833
1834 // Privatization callback that performs appropriate action for
1835 // shared/private/firstprivate/lastprivate/copyin/... variables.
1836 //
1837 // TODO: This defaults to shared right now.
1838 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1839 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
1840 // The next line is appropriate only for variables (Val) with the
1841 // data-sharing attribute "shared".
1842 ReplVal = &Val;
1843
1844 return CodeGenIP;
1845 };
1846
1847 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1848 const Stmt *ParallelRegionBodyStmt = CS->getCapturedStmt();
1849
1850 auto BodyGenCB = [&, this](InsertPointTy AllocaIP,
1851 InsertPointTy CodeGenIP) {
1853 *this, ParallelRegionBodyStmt, AllocaIP, CodeGenIP, "parallel");
1854 return llvm::Error::success();
1855 };
1856
1857 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP);
1858 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
1859 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
1860 AllocaInsertPt->getParent(), AllocaInsertPt->getIterator());
1861 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
1862 OMPBuilder.createParallel(Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1863 IfCond, NumThreads, ProcBind, S.hasCancel()));
1864 Builder.restoreIP(AfterIP);
1865 return;
1866 }
1867
1868 // Emit parallel region as a standalone region.
1869 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
1870 Action.Enter(CGF);
1871 OMPPrivateScope PrivateScope(CGF);
1872 emitOMPCopyinClause(CGF, S);
1873 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
1874 CGF.EmitOMPPrivateClause(S, PrivateScope);
1875 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
1876 (void)PrivateScope.Privatize();
1877 CGF.EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
1878 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
1879 };
1880 {
1881 auto LPCRegion =
1883 emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen,
1886 [](CodeGenFunction &) { return nullptr; });
1887 }
1888 // Check for outer lastprivate conditional update.
1890}
1891
1893 EmitStmt(S.getIfStmt());
1894}
1895
1896namespace {
1897/// RAII to handle scopes for loop transformation directives.
1898class OMPTransformDirectiveScopeRAII {
1899 OMPLoopScope *Scope = nullptr;
1901 CodeGenFunction::CGCapturedStmtRAII *CapInfoRAII = nullptr;
1902
1903 OMPTransformDirectiveScopeRAII(const OMPTransformDirectiveScopeRAII &) =
1904 delete;
1905 OMPTransformDirectiveScopeRAII &
1906 operator=(const OMPTransformDirectiveScopeRAII &) = delete;
1907
1908public:
1909 OMPTransformDirectiveScopeRAII(CodeGenFunction &CGF, const Stmt *S) {
1910 if (const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
1911 Scope = new OMPLoopScope(CGF, *Dir);
1913 CapInfoRAII = new CodeGenFunction::CGCapturedStmtRAII(CGF, CGSI);
1914 }
1915 }
1916 ~OMPTransformDirectiveScopeRAII() {
1917 if (!Scope)
1918 return;
1919 delete CapInfoRAII;
1920 delete CGSI;
1921 delete Scope;
1922 }
1923};
1924} // namespace
1925
1926static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop,
1927 int MaxLevel, int Level = 0) {
1928 assert(Level < MaxLevel && "Too deep lookup during loop body codegen.");
1929 const Stmt *SimplifiedS = S->IgnoreContainers();
1930 if (const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1931 PrettyStackTraceLoc CrashInfo(
1932 CGF.getContext().getSourceManager(), CS->getLBracLoc(),
1933 "LLVM IR generation of compound statement ('{}')");
1934
1935 // Keep track of the current cleanup stack depth, including debug scopes.
1936 CodeGenFunction::LexicalScope Scope(CGF, S->getSourceRange());
1937 for (const Stmt *CurStmt : CS->body())
1938 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1939 return;
1940 }
1941 if (SimplifiedS == NextLoop) {
1942 if (auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
1943 SimplifiedS = Dir->getTransformedStmt();
1944 if (const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
1945 SimplifiedS = CanonLoop->getLoopStmt();
1946 if (const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
1947 S = For->getBody();
1948 } else {
1949 assert(isa<CXXForRangeStmt>(SimplifiedS) &&
1950 "Expected canonical for loop or range-based for loop.");
1951 const auto *CXXFor = cast<CXXForRangeStmt>(SimplifiedS);
1952 CGF.EmitStmt(CXXFor->getLoopVarStmt());
1953 S = CXXFor->getBody();
1954 }
1955 if (Level + 1 < MaxLevel) {
1957 S, /*TryImperfectlyNestedLoops=*/true);
1958 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
1959 return;
1960 }
1961 }
1962 CGF.EmitStmt(S);
1963}
1964
1967 RunCleanupsScope BodyScope(*this);
1968 // Update counters values on current iteration.
1969 for (const Expr *UE : D.updates())
1970 EmitIgnoredExpr(UE);
1971 // Update the linear variables.
1972 // In distribute directives only loop counters may be marked as linear, no
1973 // need to generate the code for them.
1975 if (!isOpenMPDistributeDirective(EKind)) {
1976 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
1977 for (const Expr *UE : C->updates())
1978 EmitIgnoredExpr(UE);
1979 }
1980 }
1981
1982 // On a continue in the body, jump to the end.
1983 JumpDest Continue = getJumpDestInCurrentScope("omp.body.continue");
1984 BreakContinueStack.push_back(BreakContinue(D, LoopExit, Continue));
1985 for (const Expr *E : D.finals_conditions()) {
1986 if (!E)
1987 continue;
1988 // Check that loop counter in non-rectangular nest fits into the iteration
1989 // space.
1990 llvm::BasicBlock *NextBB = createBasicBlock("omp.body.next");
1991 EmitBranchOnBoolExpr(E, NextBB, Continue.getBlock(),
1993 EmitBlock(NextBB);
1994 }
1995
1996 OMPPrivateScope InscanScope(*this);
1997 EmitOMPReductionClauseInit(D, InscanScope, /*ForInscan=*/true);
1998 bool IsInscanRegion = InscanScope.Privatize();
1999 if (IsInscanRegion) {
2000 // Need to remember the block before and after scan directive
2001 // to dispatch them correctly depending on the clause used in
2002 // this directive, inclusive or exclusive. For inclusive scan the natural
2003 // order of the blocks is used, for exclusive clause the blocks must be
2004 // executed in reverse order.
2005 OMPBeforeScanBlock = createBasicBlock("omp.before.scan.bb");
2006 OMPAfterScanBlock = createBasicBlock("omp.after.scan.bb");
2007 // No need to allocate inscan exit block, in simd mode it is selected in the
2008 // codegen for the scan directive.
2009 if (EKind != OMPD_simd && !getLangOpts().OpenMPSimd)
2010 OMPScanExitBlock = createBasicBlock("omp.exit.inscan.bb");
2011 OMPScanDispatch = createBasicBlock("omp.inscan.dispatch");
2014 }
2015
2016 // Emit loop variables for C++ range loops.
2017 const Stmt *Body =
2018 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2019 // Emit loop body.
2020 emitBody(*this, Body,
2022 Body, /*TryImperfectlyNestedLoops=*/true),
2023 D.getLoopsNumber());
2024
2025 // Jump to the dispatcher at the end of the loop body.
2026 if (IsInscanRegion)
2028
2029 // The end (updates/cleanups).
2030 EmitBlock(Continue.getBlock());
2031 BreakContinueStack.pop_back();
2032}
2033
2034using EmittedClosureTy = std::pair<llvm::Function *, llvm::Value *>;
2035
2036/// Emit a captured statement and return the function as well as its captured
2037/// closure context.
2039 const CapturedStmt *S) {
2040 LValue CapStruct = ParentCGF.InitCapturedStruct(*S);
2041 CodeGenFunction CGF(ParentCGF.CGM, /*suppressNewContext=*/true);
2042 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2043 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2044 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, CSI.get());
2045 llvm::Function *F = CGF.GenerateCapturedStmtFunction(*S);
2046
2047 return {F, CapStruct.getPointer(ParentCGF)};
2048}
2049
2050/// Emit a call to a previously captured closure.
2051static llvm::CallInst *
2054 // Append the closure context to the argument.
2055 SmallVector<llvm::Value *> EffectiveArgs;
2056 EffectiveArgs.reserve(Args.size() + 1);
2057 llvm::append_range(EffectiveArgs, Args);
2058 EffectiveArgs.push_back(Cap.second);
2059
2060 return ParentCGF.Builder.CreateCall(Cap.first, EffectiveArgs);
2061}
2062
2063llvm::CanonicalLoopInfo *
2065 assert(Depth == 1 && "Nested loops with OpenMPIRBuilder not yet implemented");
2066
2067 // The caller is processing the loop-associated directive processing the \p
2068 // Depth loops nested in \p S. Put the previous pending loop-associated
2069 // directive to the stack. If the current loop-associated directive is a loop
2070 // transformation directive, it will push its generated loops onto the stack
2071 // such that together with the loops left here they form the combined loop
2072 // nest for the parent loop-associated directive.
2073 int ParentExpectedOMPLoopDepth = ExpectedOMPLoopDepth;
2074 ExpectedOMPLoopDepth = Depth;
2075
2076 EmitStmt(S);
2077 assert(OMPLoopNestStack.size() >= (size_t)Depth && "Found too few loops");
2078
2079 // The last added loop is the outermost one.
2080 llvm::CanonicalLoopInfo *Result = OMPLoopNestStack.back();
2081
2082 // Pop the \p Depth loops requested by the call from that stack and restore
2083 // the previous context.
2084 OMPLoopNestStack.pop_back_n(Depth);
2085 ExpectedOMPLoopDepth = ParentExpectedOMPLoopDepth;
2086
2087 return Result;
2088}
2089
2091 const Stmt *SyntacticalLoop = S->getLoopStmt();
2092 if (!getLangOpts().OpenMPIRBuilder) {
2093 // Ignore if OpenMPIRBuilder is not enabled.
2094 EmitStmt(SyntacticalLoop);
2095 return;
2096 }
2097
2098 LexicalScope ForScope(*this, S->getSourceRange());
2099
2100 // Emit init statements. The Distance/LoopVar funcs may reference variable
2101 // declarations they contain.
2102 const Stmt *BodyStmt;
2103 if (const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2104 if (const Stmt *InitStmt = For->getInit())
2105 EmitStmt(InitStmt);
2106 BodyStmt = For->getBody();
2107 } else if (const auto *RangeFor =
2108 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2109 if (const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2110 EmitStmt(RangeStmt);
2111 if (const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2112 EmitStmt(BeginStmt);
2113 if (const DeclStmt *EndStmt = RangeFor->getEndStmt())
2114 EmitStmt(EndStmt);
2115 if (const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2116 EmitStmt(LoopVarStmt);
2117 BodyStmt = RangeFor->getBody();
2118 } else
2119 llvm_unreachable("Expected for-stmt or range-based for-stmt");
2120
2121 // Emit closure for later use. By-value captures will be captured here.
2122 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2123 EmittedClosureTy DistanceClosure = emitCapturedStmtFunc(*this, DistanceFunc);
2124 const CapturedStmt *LoopVarFunc = S->getLoopVarFunc();
2125 EmittedClosureTy LoopVarClosure = emitCapturedStmtFunc(*this, LoopVarFunc);
2126
2127 // Call the distance function to get the number of iterations of the loop to
2128 // come.
2129 QualType LogicalTy = DistanceFunc->getCapturedDecl()
2130 ->getParam(0)
2131 ->getType()
2133 RawAddress CountAddr = CreateMemTemp(LogicalTy, ".count.addr");
2134 emitCapturedStmtCall(*this, DistanceClosure, {CountAddr.getPointer()});
2135 llvm::Value *DistVal = Builder.CreateLoad(CountAddr, ".count");
2136
2137 // Emit the loop structure.
2138 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
2139 auto BodyGen = [&, this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2140 llvm::Value *IndVar) {
2141 Builder.restoreIP(CodeGenIP);
2142
2143 // Emit the loop body: Convert the logical iteration number to the loop
2144 // variable and emit the body.
2145 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2146 LValue LCVal = EmitLValue(LoopVarRef);
2147 Address LoopVarAddress = LCVal.getAddress();
2148 emitCapturedStmtCall(*this, LoopVarClosure,
2149 {LoopVarAddress.emitRawPointer(*this), IndVar});
2150
2151 RunCleanupsScope BodyScope(*this);
2152 EmitStmt(BodyStmt);
2153 return llvm::Error::success();
2154 };
2155
2156 llvm::CanonicalLoopInfo *CL =
2157 cantFail(OMPBuilder.createCanonicalLoop(Builder, BodyGen, DistVal));
2158
2159 // Finish up the loop.
2160 Builder.restoreIP(CL->getAfterIP());
2161 ForScope.ForceCleanup();
2162
2163 // Remember the CanonicalLoopInfo for parent AST nodes consuming it.
2164 OMPLoopNestStack.push_back(CL);
2165}
2166
2168 const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond,
2169 const Expr *IncExpr,
2170 const llvm::function_ref<void(CodeGenFunction &)> BodyGen,
2171 const llvm::function_ref<void(CodeGenFunction &)> PostIncGen) {
2172 auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
2173
2174 // Start the loop with a block that tests the condition.
2175 auto CondBlock = createBasicBlock("omp.inner.for.cond");
2176 EmitBlock(CondBlock);
2177 const SourceRange R = S.getSourceRange();
2178
2179 // If attributes are attached, push to the basic block with them.
2180 const auto &OMPED = cast<OMPExecutableDirective>(S);
2181 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2182 const Stmt *SS = ICS->getCapturedStmt();
2183 const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(SS);
2184 OMPLoopNestStack.clear();
2185 if (AS)
2189 else
2192
2193 // If there are any cleanups between here and the loop-exit scope,
2194 // create a block to stage a loop exit along.
2195 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
2196 if (RequiresCleanup)
2197 ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
2198
2199 llvm::BasicBlock *LoopBody = createBasicBlock("omp.inner.for.body");
2200
2201 // Emit condition.
2202 EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S));
2203 if (ExitBlock != LoopExit.getBlock()) {
2204 EmitBlock(ExitBlock);
2206 }
2207
2208 EmitBlock(LoopBody);
2210
2211 // Create a block for the increment.
2212 JumpDest Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
2213 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
2214
2215 BodyGen(*this);
2216
2217 // Emit "IV = IV + 1" and a back-edge to the condition block.
2218 EmitBlock(Continue.getBlock());
2219 EmitIgnoredExpr(IncExpr);
2220 PostIncGen(*this);
2221 BreakContinueStack.pop_back();
2222 EmitBranch(CondBlock);
2223 LoopStack.pop();
2224 // Emit the fall-through block.
2225 EmitBlock(LoopExit.getBlock());
2226}
2227
2229 if (!HaveInsertPoint())
2230 return false;
2231 // Emit inits for the linear variables.
2232 bool HasLinears = false;
2233 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
2234 for (const Expr *Init : C->inits()) {
2235 HasLinears = true;
2236 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
2237 if (const auto *Ref =
2238 dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) {
2239 AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
2240 const auto *OrigVD = cast<VarDecl>(Ref->getDecl());
2241 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
2242 CapturedStmtInfo->lookup(OrigVD) != nullptr,
2243 VD->getInit()->getType(), VK_LValue,
2244 VD->getInit()->getExprLoc());
2246 &DRE, VD,
2247 MakeAddrLValue(Emission.getAllocatedAddress(), VD->getType()),
2248 /*capturedByInit=*/false);
2249 EmitAutoVarCleanups(Emission);
2250 } else {
2251 EmitVarDecl(*VD);
2252 }
2253 }
2254 // Emit the linear steps for the linear clauses.
2255 // If a step is not constant, it is pre-calculated before the loop.
2256 if (const auto *CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
2257 if (const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
2258 EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
2259 // Emit calculation of the linear step.
2260 EmitIgnoredExpr(CS);
2261 }
2262 }
2263 return HasLinears;
2264}
2265
2267 const OMPLoopDirective &D,
2268 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2269 if (!HaveInsertPoint())
2270 return;
2271 llvm::BasicBlock *DoneBB = nullptr;
2272 // Emit the final values of the linear variables.
2273 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
2274 auto IC = C->varlist_begin();
2275 for (const Expr *F : C->finals()) {
2276 if (!DoneBB) {
2277 if (llvm::Value *Cond = CondGen(*this)) {
2278 // If the first post-update expression is found, emit conditional
2279 // block if it was requested.
2280 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.linear.pu");
2281 DoneBB = createBasicBlock(".omp.linear.pu.done");
2282 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2283 EmitBlock(ThenBB);
2284 }
2285 }
2286 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
2287 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
2288 CapturedStmtInfo->lookup(OrigVD) != nullptr,
2289 (*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
2290 Address OrigAddr = EmitLValue(&DRE).getAddress();
2291 CodeGenFunction::OMPPrivateScope VarScope(*this);
2292 VarScope.addPrivate(OrigVD, OrigAddr);
2293 (void)VarScope.Privatize();
2294 EmitIgnoredExpr(F);
2295 ++IC;
2296 }
2297 if (const Expr *PostUpdate = C->getPostUpdateExpr())
2298 EmitIgnoredExpr(PostUpdate);
2299 }
2300 if (DoneBB)
2301 EmitBlock(DoneBB, /*IsFinished=*/true);
2302}
2303
2305 const OMPExecutableDirective &D) {
2306 if (!CGF.HaveInsertPoint())
2307 return;
2308 for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) {
2309 llvm::APInt ClauseAlignment(64, 0);
2310 if (const Expr *AlignmentExpr = Clause->getAlignment()) {
2311 auto *AlignmentCI =
2312 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
2313 ClauseAlignment = AlignmentCI->getValue();
2314 }
2315 for (const Expr *E : Clause->varlist()) {
2316 llvm::APInt Alignment(ClauseAlignment);
2317 if (Alignment == 0) {
2318 // OpenMP [2.8.1, Description]
2319 // If no optional parameter is specified, implementation-defined default
2320 // alignments for SIMD instructions on the target platforms are assumed.
2321 Alignment =
2322 CGF.getContext()
2324 E->getType()->getPointeeType()))
2325 .getQuantity();
2326 }
2327 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2328 "alignment is not power of 2");
2329 if (Alignment != 0) {
2330 llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
2332 PtrValue, E, /*No second loc needed*/ SourceLocation(),
2333 llvm::ConstantInt::get(CGF.getLLVMContext(), Alignment));
2334 }
2335 }
2336 }
2337}
2338
2341 if (!HaveInsertPoint())
2342 return;
2343 auto I = S.private_counters().begin();
2344 for (const Expr *E : S.counters()) {
2345 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2346 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
2347 // Emit var without initialization.
2348 AutoVarEmission VarEmission = EmitAutoVarAlloca(*PrivateVD);
2349 EmitAutoVarCleanups(VarEmission);
2350 LocalDeclMap.erase(PrivateVD);
2351 (void)LoopScope.addPrivate(VD, VarEmission.getAllocatedAddress());
2352 if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) ||
2353 VD->hasGlobalStorage()) {
2354 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD),
2355 LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD),
2356 E->getType(), VK_LValue, E->getExprLoc());
2357 (void)LoopScope.addPrivate(PrivateVD, EmitLValue(&DRE).getAddress());
2358 } else {
2359 (void)LoopScope.addPrivate(PrivateVD, VarEmission.getAllocatedAddress());
2360 }
2361 ++I;
2362 }
2363 // Privatize extra loop counters used in loops for ordered(n) clauses.
2364 for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) {
2365 if (!C->getNumForLoops())
2366 continue;
2367 for (unsigned I = S.getLoopsNumber(), E = C->getLoopNumIterations().size();
2368 I < E; ++I) {
2369 const auto *DRE = cast<DeclRefExpr>(C->getLoopCounter(I));
2370 const auto *VD = cast<VarDecl>(DRE->getDecl());
2371 // Override only those variables that can be captured to avoid re-emission
2372 // of the variables declared within the loops.
2373 if (DRE->refersToEnclosingVariableOrCapture()) {
2374 (void)LoopScope.addPrivate(
2375 VD, CreateMemTemp(DRE->getType(), VD->getName()));
2376 }
2377 }
2378 }
2379}
2380
2382 const Expr *Cond, llvm::BasicBlock *TrueBlock,
2383 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2384 if (!CGF.HaveInsertPoint())
2385 return;
2386 {
2387 CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
2388 CGF.EmitOMPPrivateLoopCounters(S, PreCondScope);
2389 (void)PreCondScope.Privatize();
2390 // Get initial values of real counters.
2391 for (const Expr *I : S.inits()) {
2392 CGF.EmitIgnoredExpr(I);
2393 }
2394 }
2395 // Create temp loop control variables with their init values to support
2396 // non-rectangular loops.
2397 CodeGenFunction::OMPMapVars PreCondVars;
2398 for (const Expr *E : S.dependent_counters()) {
2399 if (!E)
2400 continue;
2401 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2402 "dependent counter must not be an iterator.");
2403 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2404 Address CounterAddr =
2406 (void)PreCondVars.setVarAddr(CGF, VD, CounterAddr);
2407 }
2408 (void)PreCondVars.apply(CGF);
2409 for (const Expr *E : S.dependent_inits()) {
2410 if (!E)
2411 continue;
2412 CGF.EmitIgnoredExpr(E);
2413 }
2414 // Check that loop is executed at least one time.
2415 CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount);
2416 PreCondVars.restore(CGF);
2417}
2418
2420 const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope) {
2421 if (!HaveInsertPoint())
2422 return;
2423 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2425 if (isOpenMPSimdDirective(EKind)) {
2426 const auto *LoopDirective = cast<OMPLoopDirective>(&D);
2427 for (const Expr *C : LoopDirective->counters()) {
2428 SIMDLCVs.insert(
2429 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
2430 }
2431 }
2432 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
2433 auto CurPrivate = C->privates().begin();
2434 for (const Expr *E : C->varlist()) {
2435 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2436 const auto *PrivateVD =
2437 cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
2438 if (!SIMDLCVs.count(VD->getCanonicalDecl())) {
2439 // Emit private VarDecl with copy init.
2440 EmitVarDecl(*PrivateVD);
2441 bool IsRegistered =
2442 PrivateScope.addPrivate(VD, GetAddrOfLocalVar(PrivateVD));
2443 assert(IsRegistered && "linear var already registered as private");
2444 // Silence the warning about unused variable.
2445 (void)IsRegistered;
2446 } else {
2447 EmitVarDecl(*PrivateVD);
2448 }
2449 ++CurPrivate;
2450 }
2451 }
2452}
2453
2455 const OMPExecutableDirective &D) {
2456 if (!CGF.HaveInsertPoint())
2457 return;
2458 if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) {
2459 RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
2460 /*ignoreResult=*/true);
2461 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
2462 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
2463 // In presence of finite 'safelen', it may be unsafe to mark all
2464 // the memory instructions parallel, because loop-carried
2465 // dependences of 'safelen' iterations are possible.
2466 CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>());
2467 } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) {
2468 RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
2469 /*ignoreResult=*/true);
2470 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
2471 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
2472 // In presence of finite 'safelen', it may be unsafe to mark all
2473 // the memory instructions parallel, because loop-carried
2474 // dependences of 'safelen' iterations are possible.
2475 CGF.LoopStack.setParallel(/*Enable=*/false);
2476 }
2477}
2478
2479// Check for the presence of an `OMPOrderedDirective`,
2480// i.e., `ordered` in `#pragma omp ordered simd`.
2481//
2482// Consider the following source code:
2483// ```
2484// __attribute__((noinline)) void omp_simd_loop(float X[ARRAY_SIZE][ARRAY_SIZE])
2485// {
2486// for (int r = 1; r < ARRAY_SIZE; ++r) {
2487// for (int c = 1; c < ARRAY_SIZE; ++c) {
2488// #pragma omp simd
2489// for (int k = 2; k < ARRAY_SIZE; ++k) {
2490// #pragma omp ordered simd
2491// X[r][k] = X[r][k - 2] + sinf((float)(r / c));
2492// }
2493// }
2494// }
2495// }
2496// ```
2497//
2498// Suppose we are in `CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective
2499// &D)`. By examining `D.dump()` we have the following AST containing
2500// `OMPOrderedDirective`:
2501//
2502// ```
2503// OMPSimdDirective 0x1c32950
2504// `-CapturedStmt 0x1c32028
2505// |-CapturedDecl 0x1c310e8
2506// | |-ForStmt 0x1c31e30
2507// | | |-DeclStmt 0x1c31298
2508// | | | `-VarDecl 0x1c31208 used k 'int' cinit
2509// | | | `-IntegerLiteral 0x1c31278 'int' 2
2510// | | |-<<<NULL>>>
2511// | | |-BinaryOperator 0x1c31308 'int' '<'
2512// | | | |-ImplicitCastExpr 0x1c312f0 'int' <LValueToRValue>
2513// | | | | `-DeclRefExpr 0x1c312b0 'int' lvalue Var 0x1c31208 'k' 'int'
2514// | | | `-IntegerLiteral 0x1c312d0 'int' 256
2515// | | |-UnaryOperator 0x1c31348 'int' prefix '++'
2516// | | | `-DeclRefExpr 0x1c31328 'int' lvalue Var 0x1c31208 'k' 'int'
2517// | | `-CompoundStmt 0x1c31e18
2518// | | `-OMPOrderedDirective 0x1c31dd8
2519// | | |-OMPSimdClause 0x1c31380
2520// | | `-CapturedStmt 0x1c31cd0
2521// ```
2522//
2523// Note the presence of `OMPOrderedDirective` above:
2524// It's (transitively) nested in a `CapturedStmt` representing the pragma
2525// annotated compound statement. Thus, we need to consider this nesting and
2526// include checking the `getCapturedStmt` in this case.
2527static bool hasOrderedDirective(const Stmt *S) {
2528 if (isa<OMPOrderedDirective>(S))
2529 return true;
2530
2531 if (const auto *CS = dyn_cast<CapturedStmt>(S))
2533
2534 for (const Stmt *Child : S->children()) {
2535 if (Child && hasOrderedDirective(Child))
2536 return true;
2537 }
2538
2539 return false;
2540}
2541
2542static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt,
2544 // Check for the presence of an `OMPOrderedDirective`
2545 // i.e., `ordered` in `#pragma omp ordered simd`
2546 bool HasOrderedDirective = hasOrderedDirective(&AssociatedStmt);
2547 // If present then conservatively disable loop vectorization
2548 // analogously to how `emitSimdlenSafelenClause` does.
2549 if (HasOrderedDirective)
2550 LoopStack.setParallel(/*Enable=*/false);
2551}
2552
2554 // Walk clauses and process safelen/lastprivate.
2555 LoopStack.setParallel(/*Enable=*/true);
2557 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2560 if (const auto *C = D.getSingleClause<OMPOrderClause>())
2561 if (C->getKind() == OMPC_ORDER_concurrent)
2562 LoopStack.setParallel(/*Enable=*/true);
2564 if ((EKind == OMPD_simd ||
2565 (getLangOpts().OpenMPSimd && isOpenMPSimdDirective(EKind))) &&
2566 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2567 [](const OMPReductionClause *C) {
2568 return C->getModifier() == OMPC_REDUCTION_inscan;
2569 }))
2570 // Disable parallel access in case of prefix sum.
2571 LoopStack.setParallel(/*Enable=*/false);
2572}
2573
2575 const OMPLoopDirective &D,
2576 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2577 if (!HaveInsertPoint())
2578 return;
2579 llvm::BasicBlock *DoneBB = nullptr;
2580 auto IC = D.counters().begin();
2581 auto IPC = D.private_counters().begin();
2582 for (const Expr *F : D.finals()) {
2583 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
2584 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
2585 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2586 if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) ||
2587 OrigVD->hasGlobalStorage() || CED) {
2588 if (!DoneBB) {
2589 if (llvm::Value *Cond = CondGen(*this)) {
2590 // If the first post-update expression is found, emit conditional
2591 // block if it was requested.
2592 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.final.then");
2593 DoneBB = createBasicBlock(".omp.final.done");
2594 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2595 EmitBlock(ThenBB);
2596 }
2597 }
2598 Address OrigAddr = Address::invalid();
2599 if (CED) {
2600 OrigAddr = EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress();
2601 } else {
2602 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(PrivateVD),
2603 /*RefersToEnclosingVariableOrCapture=*/false,
2604 (*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc());
2605 OrigAddr = EmitLValue(&DRE).getAddress();
2606 }
2607 OMPPrivateScope VarScope(*this);
2608 VarScope.addPrivate(OrigVD, OrigAddr);
2609 (void)VarScope.Privatize();
2610 EmitIgnoredExpr(F);
2611 }
2612 ++IC;
2613 ++IPC;
2614 }
2615 if (DoneBB)
2616 EmitBlock(DoneBB, /*IsFinished=*/true);
2617}
2618
2620 const OMPLoopDirective &S,
2622 CGF.EmitOMPLoopBody(S, LoopExit);
2623 CGF.EmitStopPoint(&S);
2624}
2625
2626/// Emit a helper variable and return corresponding lvalue.
2628 const DeclRefExpr *Helper) {
2629 auto VDecl = cast<VarDecl>(Helper->getDecl());
2630 CGF.EmitVarDecl(*VDecl);
2631 return CGF.EmitLValue(Helper);
2632}
2633
2635 const RegionCodeGenTy &SimdInitGen,
2636 const RegionCodeGenTy &BodyCodeGen) {
2637 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](CodeGenFunction &CGF,
2638 PrePostActionTy &) {
2639 CGOpenMPRuntime::NontemporalDeclsRAII NontemporalsRegion(CGF.CGM, S);
2641 SimdInitGen(CGF);
2642
2643 BodyCodeGen(CGF);
2644 };
2645 auto &&ElseGen = [&BodyCodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
2647 CGF.LoopStack.setVectorizeEnable(/*Enable=*/false);
2648
2649 BodyCodeGen(CGF);
2650 };
2651 const Expr *IfCond = nullptr;
2653 if (isOpenMPSimdDirective(EKind)) {
2654 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
2655 if (CGF.getLangOpts().OpenMP >= 50 &&
2656 (C->getNameModifier() == OMPD_unknown ||
2657 C->getNameModifier() == OMPD_simd)) {
2658 IfCond = C->getCondition();
2659 break;
2660 }
2661 }
2662 }
2663 if (IfCond) {
2664 CGF.CGM.getOpenMPRuntime().emitIfClause(CGF, IfCond, ThenGen, ElseGen);
2665 } else {
2666 RegionCodeGenTy ThenRCG(ThenGen);
2667 ThenRCG(CGF);
2668 }
2669}
2670
2672 PrePostActionTy &Action) {
2673 Action.Enter(CGF);
2674 OMPLoopScope PreInitScope(CGF, S);
2675 // if (PreCond) {
2676 // for (IV in 0..LastIteration) BODY;
2677 // <Final counter/linear vars updates>;
2678 // }
2679
2680 // The presence of lower/upper bound variable depends on the actual directive
2681 // kind in the AST node. The variables must be emitted because some of the
2682 // expressions associated with the loop will use them.
2683 OpenMPDirectiveKind DKind = S.getDirectiveKind();
2684 if (isOpenMPDistributeDirective(DKind) ||
2687 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()));
2688 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()));
2689 }
2690
2692 // Emit: if (PreCond) - begin.
2693 // If the condition constant folds and can be elided, avoid emitting the
2694 // whole loop.
2695 bool CondConstant;
2696 llvm::BasicBlock *ContBlock = nullptr;
2697 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
2698 if (!CondConstant)
2699 return;
2700 } else {
2701 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("simd.if.then");
2702 ContBlock = CGF.createBasicBlock("simd.if.end");
2703 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2704 CGF.getProfileCount(&S));
2705 CGF.EmitBlock(ThenBlock);
2707 }
2708
2709 // Emit the loop iteration variable.
2710 const Expr *IVExpr = S.getIterationVariable();
2711 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
2712 CGF.EmitVarDecl(*IVDecl);
2713 CGF.EmitIgnoredExpr(S.getInit());
2714
2715 // Emit the iterations count variable.
2716 // If it is not a variable, Sema decided to calculate iterations count on
2717 // each iteration (e.g., it is foldable into a constant).
2718 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
2719 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2720 // Emit calculation of the iterations count.
2721 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
2722 }
2723
2724 emitAlignedClause(CGF, S);
2725 (void)CGF.EmitOMPLinearClauseInit(S);
2726 {
2727 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
2728 CGF.EmitOMPPrivateClause(S, LoopScope);
2729 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
2730 CGF.EmitOMPLinearClause(S, LoopScope);
2731 CGF.EmitOMPReductionClauseInit(S, LoopScope);
2733 CGF, S, CGF.EmitLValue(S.getIterationVariable()));
2734 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
2735 (void)LoopScope.Privatize();
2738
2740 CGF, S,
2741 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2742 CGF.EmitOMPSimdInit(S);
2743 },
2744 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
2745 CGF.EmitOMPInnerLoop(
2746 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
2747 [&S](CodeGenFunction &CGF) {
2748 emitOMPLoopBodyWithStopPoint(CGF, S,
2749 CodeGenFunction::JumpDest());
2750 },
2751 [](CodeGenFunction &) {});
2752 });
2753 CGF.EmitOMPSimdFinal(S, [](CodeGenFunction &) { return nullptr; });
2754 // Emit final copy of the lastprivate variables at the end of loops.
2755 if (HasLastprivateClause)
2756 CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true);
2757 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd);
2759 [](CodeGenFunction &) { return nullptr; });
2760 LoopScope.restoreMap();
2761 CGF.EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; });
2762 }
2763 // Emit: if (PreCond) - end.
2764 if (ContBlock) {
2765 CGF.EmitBranch(ContBlock);
2766 CGF.EmitBlock(ContBlock, true);
2767 }
2768}
2769
2770// Pass OMPLoopDirective (instead of OMPSimdDirective) to make this function
2771// available for "loop bind(thread)", which maps to "simd".
2773 // Check for unsupported clauses
2774 for (OMPClause *C : S.clauses()) {
2775 // Currently only order, simdlen and safelen clauses are supported
2776 if (!(isa<OMPSimdlenClause>(C) || isa<OMPSafelenClause>(C) ||
2777 isa<OMPOrderClause>(C) || isa<OMPAlignedClause>(C)))
2778 return false;
2779 }
2780
2781 // Check if we have a statement with the ordered directive.
2782 // Visit the statement hierarchy to find a compound statement
2783 // with a ordered directive in it.
2784 if (const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
2785 if (const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
2786 for (const Stmt *SubStmt : SyntacticalLoop->children()) {
2787 if (!SubStmt)
2788 continue;
2789 if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
2790 for (const Stmt *CSSubStmt : CS->children()) {
2791 if (!CSSubStmt)
2792 continue;
2793 if (isa<OMPOrderedDirective>(CSSubStmt)) {
2794 return false;
2795 }
2796 }
2797 }
2798 }
2799 }
2800 }
2801 return true;
2802}
2803
2804static llvm::MapVector<llvm::Value *, llvm::Value *>
2806 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
2807 for (const auto *Clause : S.getClausesOfKind<OMPAlignedClause>()) {
2808 llvm::APInt ClauseAlignment(64, 0);
2809 if (const Expr *AlignmentExpr = Clause->getAlignment()) {
2810 auto *AlignmentCI =
2811 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
2812 ClauseAlignment = AlignmentCI->getValue();
2813 }
2814 for (const Expr *E : Clause->varlist()) {
2815 llvm::APInt Alignment(ClauseAlignment);
2816 if (Alignment == 0) {
2817 // OpenMP [2.8.1, Description]
2818 // If no optional parameter is specified, implementation-defined default
2819 // alignments for SIMD instructions on the target platforms are assumed.
2820 Alignment =
2821 CGF.getContext()
2823 E->getType()->getPointeeType()))
2824 .getQuantity();
2825 }
2826 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2827 "alignment is not power of 2");
2828 llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
2829 AlignedVars[PtrValue] = CGF.Builder.getInt64(Alignment.getSExtValue());
2830 }
2831 }
2832 return AlignedVars;
2833}
2834
2835// Pass OMPLoopDirective (instead of OMPSimdDirective) to make this function
2836// available for "loop bind(thread)", which maps to "simd".
2839 bool UseOMPIRBuilder =
2840 CGM.getLangOpts().OpenMPIRBuilder && isSimdSupportedByOpenMPIRBuilder(S);
2841 if (UseOMPIRBuilder) {
2842 auto &&CodeGenIRBuilder = [&S, &CGM, UseOMPIRBuilder](CodeGenFunction &CGF,
2843 PrePostActionTy &) {
2844 // Use the OpenMPIRBuilder if enabled.
2845 if (UseOMPIRBuilder) {
2846 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
2847 GetAlignedMapping(S, CGF);
2848 // Emit the associated statement and get its loop representation.
2849 const Stmt *Inner = S.getRawStmt();
2850 llvm::CanonicalLoopInfo *CLI =
2851 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
2852
2853 llvm::OpenMPIRBuilder &OMPBuilder =
2855 // Add SIMD specific metadata
2856 llvm::ConstantInt *Simdlen = nullptr;
2857 if (const auto *C = S.getSingleClause<OMPSimdlenClause>()) {
2858 RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
2859 /*ignoreResult=*/true);
2860 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
2861 Simdlen = Val;
2862 }
2863 llvm::ConstantInt *Safelen = nullptr;
2864 if (const auto *C = S.getSingleClause<OMPSafelenClause>()) {
2865 RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
2866 /*ignoreResult=*/true);
2867 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
2868 Safelen = Val;
2869 }
2870 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
2871 if (const auto *C = S.getSingleClause<OMPOrderClause>()) {
2872 if (C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
2873 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
2874 }
2875 }
2876 // Add simd metadata to the collapsed loop. Do not generate
2877 // another loop for if clause. Support for if clause is done earlier.
2878 OMPBuilder.applySimd(CLI, AlignedVars,
2879 /*IfCond*/ nullptr, Order, Simdlen, Safelen);
2880 return;
2881 }
2882 };
2883 {
2884 auto LPCRegion =
2886 OMPLexicalScope Scope(CGF, S, OMPD_unknown);
2887 CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
2888 CodeGenIRBuilder);
2889 }
2890 return;
2891 }
2892
2894 CGF.OMPFirstScanLoop = true;
2895 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2896 emitOMPSimdRegion(CGF, S, Action);
2897 };
2898 {
2899 auto LPCRegion =
2901 OMPLexicalScope Scope(CGF, S, OMPD_unknown);
2902 CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd, CodeGen);
2903 }
2904 // Check for outer lastprivate conditional update.
2906}
2907
2909 emitOMPSimdDirective(S, *this, CGM);
2910}
2911
2913 // Emit the de-sugared statement.
2914 OMPTransformDirectiveScopeRAII TileScope(*this, &S);
2915 EmitStmt(S.getTransformedStmt());
2916}
2917
2919 // Emit the de-sugared statement.
2920 OMPTransformDirectiveScopeRAII StripeScope(*this, &S);
2921 EmitStmt(S.getTransformedStmt());
2922}
2923
2925 // Emit the de-sugared statement.
2926 OMPTransformDirectiveScopeRAII ReverseScope(*this, &S);
2927 EmitStmt(S.getTransformedStmt());
2928}
2929
2931 const OMPInterchangeDirective &S) {
2932 // Emit the de-sugared statement.
2933 OMPTransformDirectiveScopeRAII InterchangeScope(*this, &S);
2934 EmitStmt(S.getTransformedStmt());
2935}
2936
2938 bool UseOMPIRBuilder = CGM.getLangOpts().OpenMPIRBuilder;
2939
2940 if (UseOMPIRBuilder) {
2941 auto DL = SourceLocToDebugLoc(S.getBeginLoc());
2942 const Stmt *Inner = S.getRawStmt();
2943
2944 // Consume nested loop. Clear the entire remaining loop stack because a
2945 // fully unrolled loop is non-transformable. For partial unrolling the
2946 // generated outer loop is pushed back to the stack.
2947 llvm::CanonicalLoopInfo *CLI = EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
2948 OMPLoopNestStack.clear();
2949
2950 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
2951
2952 bool NeedsUnrolledCLI = ExpectedOMPLoopDepth >= 1;
2953 llvm::CanonicalLoopInfo *UnrolledCLI = nullptr;
2954
2955 if (S.hasClausesOfKind<OMPFullClause>()) {
2956 assert(ExpectedOMPLoopDepth == 0);
2957 OMPBuilder.unrollLoopFull(DL, CLI);
2958 } else if (auto *PartialClause = S.getSingleClause<OMPPartialClause>()) {
2959 uint64_t Factor = 0;
2960 if (Expr *FactorExpr = PartialClause->getFactor()) {
2961 Factor = FactorExpr->EvaluateKnownConstInt(getContext()).getZExtValue();
2962 assert(Factor >= 1 && "Only positive factors are valid");
2963 }
2964 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
2965 NeedsUnrolledCLI ? &UnrolledCLI : nullptr);
2966 } else {
2967 OMPBuilder.unrollLoopHeuristic(DL, CLI);
2968 }
2969
2970 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
2971 "NeedsUnrolledCLI implies UnrolledCLI to be set");
2972 if (UnrolledCLI)
2973 OMPLoopNestStack.push_back(UnrolledCLI);
2974
2975 return;
2976 }
2977
2978 // This function is only called if the unrolled loop is not consumed by any
2979 // other loop-associated construct. Such a loop-associated construct will have
2980 // used the transformed AST.
2981
2982 // Set the unroll metadata for the next emitted loop.
2984
2985 if (S.hasClausesOfKind<OMPFullClause>()) {
2987 } else if (auto *PartialClause = S.getSingleClause<OMPPartialClause>()) {
2988 if (Expr *FactorExpr = PartialClause->getFactor()) {
2989 uint64_t Factor =
2990 FactorExpr->EvaluateKnownConstInt(getContext()).getZExtValue();
2991 assert(Factor >= 1 && "Only positive factors are valid");
2992 LoopStack.setUnrollCount(Factor);
2993 }
2994 }
2995
2996 EmitStmt(S.getAssociatedStmt());
2997}
2998
2999void CodeGenFunction::EmitOMPOuterLoop(
3000 bool DynamicOrOrdered, bool IsMonotonic, const OMPLoopDirective &S,
3002 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3003 const CodeGenFunction::CodeGenLoopTy &CodeGenLoop,
3004 const CodeGenFunction::CodeGenOrderedTy &CodeGenOrdered) {
3006
3007 const Expr *IVExpr = S.getIterationVariable();
3008 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3009 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3010
3011 JumpDest LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
3012
3013 // Start the loop with a block that tests the condition.
3014 llvm::BasicBlock *CondBlock = createBasicBlock("omp.dispatch.cond");
3015 EmitBlock(CondBlock);
3016 const SourceRange R = S.getSourceRange();
3017 OMPLoopNestStack.clear();
3020
3021 llvm::Value *BoolCondVal = nullptr;
3022 if (!DynamicOrOrdered) {
3023 // UB = min(UB, GlobalUB) or
3024 // UB = min(UB, PrevUB) for combined loop sharing constructs (e.g.
3025 // 'distribute parallel for')
3026 EmitIgnoredExpr(LoopArgs.EUB);
3027 // IV = LB
3028 EmitIgnoredExpr(LoopArgs.Init);
3029 // IV < UB
3030 BoolCondVal = EvaluateExprAsBool(LoopArgs.Cond);
3031 } else {
3032 BoolCondVal =
3033 RT.emitForNext(*this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3034 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3035 }
3036
3037 // If there are any cleanups between here and the loop-exit scope,
3038 // create a block to stage a loop exit along.
3039 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
3040 if (LoopScope.requiresCleanups())
3041 ExitBlock = createBasicBlock("omp.dispatch.cleanup");
3042
3043 llvm::BasicBlock *LoopBody = createBasicBlock("omp.dispatch.body");
3044 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3045 if (ExitBlock != LoopExit.getBlock()) {
3046 EmitBlock(ExitBlock);
3048 }
3049 EmitBlock(LoopBody);
3050
3051 // Emit "IV = LB" (in case of static schedule, we have already calculated new
3052 // LB for loop condition and emitted it above).
3053 if (DynamicOrOrdered)
3054 EmitIgnoredExpr(LoopArgs.Init);
3055
3056 // Create a block for the increment.
3057 JumpDest Continue = getJumpDestInCurrentScope("omp.dispatch.inc");
3058 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3059
3062 *this, S,
3063 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3064 // Generate !llvm.loop.parallel metadata for loads and stores for loops
3065 // with dynamic/guided scheduling and without ordered clause.
3066 if (!isOpenMPSimdDirective(EKind)) {
3067 CGF.LoopStack.setParallel(!IsMonotonic);
3068 if (const auto *C = S.getSingleClause<OMPOrderClause>())
3069 if (C->getKind() == OMPC_ORDER_concurrent)
3070 CGF.LoopStack.setParallel(/*Enable=*/true);
3071 } else {
3072 CGF.EmitOMPSimdInit(S);
3073 }
3074 },
3075 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3076 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3077 SourceLocation Loc = S.getBeginLoc();
3078 // when 'distribute' is not combined with a 'for':
3079 // while (idx <= UB) { BODY; ++idx; }
3080 // when 'distribute' is combined with a 'for'
3081 // (e.g. 'distribute parallel for')
3082 // while (idx <= UB) { <CodeGen rest of pragma>; idx += ST; }
3083 CGF.EmitOMPInnerLoop(
3084 S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr,
3085 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3086 CodeGenLoop(CGF, S, LoopExit);
3087 },
3088 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3089 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3090 });
3091 });
3092
3093 EmitBlock(Continue.getBlock());
3094 BreakContinueStack.pop_back();
3095 if (!DynamicOrOrdered) {
3096 // Emit "LB = LB + Stride", "UB = UB + Stride".
3097 EmitIgnoredExpr(LoopArgs.NextLB);
3098 EmitIgnoredExpr(LoopArgs.NextUB);
3099 }
3100
3101 EmitBranch(CondBlock);
3102 OMPLoopNestStack.clear();
3103 LoopStack.pop();
3104 // Emit the fall-through block.
3105 EmitBlock(LoopExit.getBlock());
3106
3107 // Tell the runtime we are done.
3108 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3109 if (!DynamicOrOrdered)
3110 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3111 LoopArgs.DKind);
3112 };
3113 OMPCancelStack.emitExit(*this, EKind, CodeGen);
3114}
3115
3116void CodeGenFunction::EmitOMPForOuterLoop(
3117 const OpenMPScheduleTy &ScheduleKind, bool IsMonotonic,
3118 const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered,
3119 const OMPLoopArguments &LoopArgs,
3120 const CodeGenDispatchBoundsTy &CGDispatchBounds) {
3122
3123 // Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime).
3124 const bool DynamicOrOrdered = Ordered || RT.isDynamic(ScheduleKind.Schedule);
3125
3126 assert((Ordered || !RT.isStaticNonchunked(ScheduleKind.Schedule,
3127 LoopArgs.Chunk != nullptr)) &&
3128 "static non-chunked schedule does not need outer loop");
3129
3130 // Emit outer loop.
3131 //
3132 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
3133 // When schedule(dynamic,chunk_size) is specified, the iterations are
3134 // distributed to threads in the team in chunks as the threads request them.
3135 // Each thread executes a chunk of iterations, then requests another chunk,
3136 // until no chunks remain to be distributed. Each chunk contains chunk_size
3137 // iterations, except for the last chunk to be distributed, which may have
3138 // fewer iterations. When no chunk_size is specified, it defaults to 1.
3139 //
3140 // When schedule(guided,chunk_size) is specified, the iterations are assigned
3141 // to threads in the team in chunks as the executing threads request them.
3142 // Each thread executes a chunk of iterations, then requests another chunk,
3143 // until no chunks remain to be assigned. For a chunk_size of 1, the size of
3144 // each chunk is proportional to the number of unassigned iterations divided
3145 // by the number of threads in the team, decreasing to 1. For a chunk_size
3146 // with value k (greater than 1), the size of each chunk is determined in the
3147 // same way, with the restriction that the chunks do not contain fewer than k
3148 // iterations (except for the last chunk to be assigned, which may have fewer
3149 // than k iterations).
3150 //
3151 // When schedule(auto) is specified, the decision regarding scheduling is
3152 // delegated to the compiler and/or runtime system. The programmer gives the
3153 // implementation the freedom to choose any possible mapping of iterations to
3154 // threads in the team.
3155 //
3156 // When schedule(runtime) is specified, the decision regarding scheduling is
3157 // deferred until run time, and the schedule and chunk size are taken from the
3158 // run-sched-var ICV. If the ICV is set to auto, the schedule is
3159 // implementation defined
3160 //
3161 // __kmpc_dispatch_init();
3162 // while(__kmpc_dispatch_next(&LB, &UB)) {
3163 // idx = LB;
3164 // while (idx <= UB) { BODY; ++idx;
3165 // __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only.
3166 // } // inner loop
3167 // }
3168 // __kmpc_dispatch_deinit();
3169 //
3170 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
3171 // When schedule(static, chunk_size) is specified, iterations are divided into
3172 // chunks of size chunk_size, and the chunks are assigned to the threads in
3173 // the team in a round-robin fashion in the order of the thread number.
3174 //
3175 // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) {
3176 // while (idx <= UB) { BODY; ++idx; } // inner loop
3177 // LB = LB + ST;
3178 // UB = UB + ST;
3179 // }
3180 //
3181
3182 const Expr *IVExpr = S.getIterationVariable();
3183 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3184 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3185
3186 if (DynamicOrOrdered) {
3187 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3188 CGDispatchBounds(*this, S, LoopArgs.LB, LoopArgs.UB);
3189 llvm::Value *LBVal = DispatchBounds.first;
3190 llvm::Value *UBVal = DispatchBounds.second;
3191 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3192 LoopArgs.Chunk};
3193 RT.emitForDispatchInit(*this, S.getBeginLoc(), ScheduleKind, IVSize,
3194 IVSigned, Ordered, DipatchRTInputValues);
3195 } else {
3197 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3198 LoopArgs.ST, LoopArgs.Chunk);
3200 RT.emitForStaticInit(*this, S.getBeginLoc(), EKind, ScheduleKind,
3201 StaticInit);
3202 }
3203
3204 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3205 const unsigned IVSize,
3206 const bool IVSigned) {
3207 if (Ordered) {
3209 IVSigned);
3210 }
3211 };
3212
3213 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3214 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3215 OuterLoopArgs.IncExpr = S.getInc();
3216 OuterLoopArgs.Init = S.getInit();
3217 OuterLoopArgs.Cond = S.getCond();
3218 OuterLoopArgs.NextLB = S.getNextLowerBound();
3219 OuterLoopArgs.NextUB = S.getNextUpperBound();
3220 OuterLoopArgs.DKind = LoopArgs.DKind;
3221 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3222 emitOMPLoopBodyWithStopPoint, CodeGenOrdered);
3223 if (DynamicOrOrdered) {
3224 RT.emitForDispatchDeinit(*this, S.getBeginLoc());
3225 }
3226}
3227
3229 const unsigned IVSize, const bool IVSigned) {}
3230
3231void CodeGenFunction::EmitOMPDistributeOuterLoop(
3232 OpenMPDistScheduleClauseKind ScheduleKind, const OMPLoopDirective &S,
3233 OMPPrivateScope &LoopScope, const OMPLoopArguments &LoopArgs,
3234 const CodeGenLoopTy &CodeGenLoopContent) {
3235
3237
3238 // Emit outer loop.
3239 // Same behavior as a OMPForOuterLoop, except that schedule cannot be
3240 // dynamic
3241 //
3242
3243 const Expr *IVExpr = S.getIterationVariable();
3244 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3245 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3247
3249 IVSize, IVSigned, /* Ordered = */ false, LoopArgs.IL, LoopArgs.LB,
3250 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3251 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, StaticInit);
3252
3253 // for combined 'distribute' and 'for' the increment expression of distribute
3254 // is stored in DistInc. For 'distribute' alone, it is in Inc.
3255 Expr *IncExpr;
3257 IncExpr = S.getDistInc();
3258 else
3259 IncExpr = S.getInc();
3260
3261 // this routine is shared by 'omp distribute parallel for' and
3262 // 'omp distribute': select the right EUB expression depending on the
3263 // directive
3264 OMPLoopArguments OuterLoopArgs;
3265 OuterLoopArgs.LB = LoopArgs.LB;
3266 OuterLoopArgs.UB = LoopArgs.UB;
3267 OuterLoopArgs.ST = LoopArgs.ST;
3268 OuterLoopArgs.IL = LoopArgs.IL;
3269 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3270 OuterLoopArgs.EUB = isOpenMPLoopBoundSharingDirective(EKind)
3271 ? S.getCombinedEnsureUpperBound()
3272 : S.getEnsureUpperBound();
3273 OuterLoopArgs.IncExpr = IncExpr;
3274 OuterLoopArgs.Init = isOpenMPLoopBoundSharingDirective(EKind)
3275 ? S.getCombinedInit()
3276 : S.getInit();
3277 OuterLoopArgs.Cond = isOpenMPLoopBoundSharingDirective(EKind)
3278 ? S.getCombinedCond()
3279 : S.getCond();
3280 OuterLoopArgs.NextLB = isOpenMPLoopBoundSharingDirective(EKind)
3281 ? S.getCombinedNextLowerBound()
3282 : S.getNextLowerBound();
3283 OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(EKind)
3284 ? S.getCombinedNextUpperBound()
3285 : S.getNextUpperBound();
3286 OuterLoopArgs.DKind = OMPD_distribute;
3287
3288 EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S,
3289 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3291}
3292
3293static std::pair<LValue, LValue>
3295 const OMPExecutableDirective &S) {
3296 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S);
3297 LValue LB =
3298 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
3299 LValue UB =
3300 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable()));
3301
3302 // When composing 'distribute' with 'for' (e.g. as in 'distribute
3303 // parallel for') we need to use the 'distribute'
3304 // chunk lower and upper bounds rather than the whole loop iteration
3305 // space. These are parameters to the outlined function for 'parallel'
3306 // and we copy the bounds of the previous schedule into the
3307 // the current ones.
3308 LValue PrevLB = CGF.EmitLValue(LS.getPrevLowerBoundVariable());
3309 LValue PrevUB = CGF.EmitLValue(LS.getPrevUpperBoundVariable());
3310 llvm::Value *PrevLBVal = CGF.EmitLoadOfScalar(
3311 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3312 PrevLBVal = CGF.EmitScalarConversion(
3313 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3316 llvm::Value *PrevUBVal = CGF.EmitLoadOfScalar(
3317 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3318 PrevUBVal = CGF.EmitScalarConversion(
3319 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3322
3323 CGF.EmitStoreOfScalar(PrevLBVal, LB);
3324 CGF.EmitStoreOfScalar(PrevUBVal, UB);
3325
3326 return {LB, UB};
3327}
3328
3329/// if the 'for' loop has a dispatch schedule (e.g. dynamic, guided) then
3330/// we need to use the LB and UB expressions generated by the worksharing
3331/// code generation support, whereas in non combined situations we would
3332/// just emit 0 and the LastIteration expression
3333/// This function is necessary due to the difference of the LB and UB
3334/// types for the RT emission routines for 'for_static_init' and
3335/// 'for_dispatch_init'
3336static std::pair<llvm::Value *, llvm::Value *>
3338 const OMPExecutableDirective &S,
3339 Address LB, Address UB) {
3340 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S);
3341 const Expr *IVExpr = LS.getIterationVariable();
3342 // when implementing a dynamic schedule for a 'for' combined with a
3343 // 'distribute' (e.g. 'distribute parallel for'), the 'for' loop
3344 // is not normalized as each team only executes its own assigned
3345 // distribute chunk
3346 QualType IteratorTy = IVExpr->getType();
3347 llvm::Value *LBVal =
3348 CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
3349 llvm::Value *UBVal =
3350 CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
3351 return {LBVal, UBVal};
3352}
3353
3357 const auto &Dir = cast<OMPLoopDirective>(S);
3358 LValue LB =
3359 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable()));
3360 llvm::Value *LBCast = CGF.Builder.CreateIntCast(
3361 CGF.Builder.CreateLoad(LB.getAddress()), CGF.SizeTy, /*isSigned=*/false);
3362 CapturedVars.push_back(LBCast);
3363 LValue UB =
3364 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable()));
3365
3366 llvm::Value *UBCast = CGF.Builder.CreateIntCast(
3367 CGF.Builder.CreateLoad(UB.getAddress()), CGF.SizeTy, /*isSigned=*/false);
3368 CapturedVars.push_back(UBCast);
3369}
3370
3371static void
3373 const OMPLoopDirective &S,
3376 auto &&CGInlinedWorksharingLoop = [&S, EKind](CodeGenFunction &CGF,
3377 PrePostActionTy &Action) {
3378 Action.Enter(CGF);
3379 bool HasCancel = false;
3380 if (!isOpenMPSimdDirective(EKind)) {
3381 if (const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3382 HasCancel = D->hasCancel();
3383 else if (const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3384 HasCancel = D->hasCancel();
3385 else if (const auto *D =
3386 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3387 HasCancel = D->hasCancel();
3388 }
3389 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
3390 CGF.EmitOMPWorksharingLoop(S, S.getPrevEnsureUpperBound(),
3393 };
3394
3396 CGF, S, isOpenMPSimdDirective(EKind) ? OMPD_for_simd : OMPD_for,
3397 CGInlinedWorksharingLoop,
3399}
3400
3403 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
3405 S.getDistInc());
3406 };
3407 OMPLexicalScope Scope(*this, S, OMPD_parallel);
3408 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
3409}
3410
3413 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
3415 S.getDistInc());
3416 };
3417 OMPLexicalScope Scope(*this, S, OMPD_parallel);
3418 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
3419}
3420
3422 const OMPDistributeSimdDirective &S) {
3423 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
3425 };
3426 OMPLexicalScope Scope(*this, S, OMPD_unknown);
3427 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
3428}
3429
3431 CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S) {
3432 // Emit SPMD target parallel for region as a standalone region.
3433 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3434 emitOMPSimdRegion(CGF, S, Action);
3435 };
3436 llvm::Function *Fn;
3437 llvm::Constant *Addr;
3438 // Emit target region as a standalone region.
3440 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
3441 assert(Fn && Addr && "Target device function emission failed.");
3442}
3443
3445 const OMPTargetSimdDirective &S) {
3446 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3447 emitOMPSimdRegion(CGF, S, Action);
3448 };
3449 emitCommonOMPTargetDirective(*this, S, CodeGen);
3450}
3451
3452namespace {
3453struct ScheduleKindModifiersTy {
3457 ScheduleKindModifiersTy(OpenMPScheduleClauseKind Kind,
3460 : Kind(Kind), M1(M1), M2(M2) {}
3461};
3462} // namespace
3463
3465 const OMPLoopDirective &S, Expr *EUB,
3466 const CodeGenLoopBoundsTy &CodeGenLoopBounds,
3467 const CodeGenDispatchBoundsTy &CGDispatchBounds) {
3468 // Emit the loop iteration variable.
3469 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
3470 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
3471 EmitVarDecl(*IVDecl);
3472
3473 // Emit the iterations count variable.
3474 // If it is not a variable, Sema decided to calculate iterations count on each
3475 // iteration (e.g., it is foldable into a constant).
3476 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3477 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
3478 // Emit calculation of the iterations count.
3479 EmitIgnoredExpr(S.getCalcLastIteration());
3480 }
3481
3483
3484 bool HasLastprivateClause;
3485 // Check pre-condition.
3486 {
3487 OMPLoopScope PreInitScope(*this, S);
3488 // Skip the entire loop if we don't meet the precondition.
3489 // If the condition constant folds and can be elided, avoid emitting the
3490 // whole loop.
3491 bool CondConstant;
3492 llvm::BasicBlock *ContBlock = nullptr;
3493 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
3494 if (!CondConstant)
3495 return false;
3496 } else {
3497 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
3498 ContBlock = createBasicBlock("omp.precond.end");
3499 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
3500 getProfileCount(&S));
3501 EmitBlock(ThenBlock);
3503 }
3504
3505 RunCleanupsScope DoacrossCleanupScope(*this);
3506 bool Ordered = false;
3507 if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3508 if (OrderedClause->getNumForLoops())
3509 RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations());
3510 else
3511 Ordered = true;
3512 }
3513
3514 emitAlignedClause(*this, S);
3515 bool HasLinears = EmitOMPLinearClauseInit(S);
3516 // Emit helper vars inits.
3517
3518 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*this, S);
3519 LValue LB = Bounds.first;
3520 LValue UB = Bounds.second;
3521 LValue ST =
3522 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
3523 LValue IL =
3524 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
3525
3526 // Emit 'then' code.
3527 {
3529 OMPPrivateScope LoopScope(*this);
3530 if (EmitOMPFirstprivateClause(S, LoopScope) || HasLinears) {
3531 // Emit implicit barrier to synchronize threads and avoid data races on
3532 // initialization of firstprivate variables and post-update of
3533 // lastprivate variables.
3535 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
3536 /*ForceSimpleCall=*/true);
3537 }
3538 EmitOMPPrivateClause(S, LoopScope);
3540 *this, S, EmitLValue(S.getIterationVariable()));
3541 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
3542 EmitOMPReductionClauseInit(S, LoopScope);
3543 EmitOMPPrivateLoopCounters(S, LoopScope);
3544 EmitOMPLinearClause(S, LoopScope);
3545 (void)LoopScope.Privatize();
3548
3549 // Detect the loop schedule kind and chunk.
3550 const Expr *ChunkExpr = nullptr;
3551 OpenMPScheduleTy ScheduleKind;
3552 if (const auto *C = S.getSingleClause<OMPScheduleClause>()) {
3553 ScheduleKind.Schedule = C->getScheduleKind();
3554 ScheduleKind.M1 = C->getFirstScheduleModifier();
3555 ScheduleKind.M2 = C->getSecondScheduleModifier();
3556 ChunkExpr = C->getChunkSize();
3557 } else {
3558 // Default behaviour for schedule clause.
3560 *this, S, ScheduleKind.Schedule, ChunkExpr);
3561 }
3562 bool HasChunkSizeOne = false;
3563 llvm::Value *Chunk = nullptr;
3564 if (ChunkExpr) {
3565 Chunk = EmitScalarExpr(ChunkExpr);
3566 Chunk = EmitScalarConversion(Chunk, ChunkExpr->getType(),
3567 S.getIterationVariable()->getType(),
3568 S.getBeginLoc());
3570 if (ChunkExpr->EvaluateAsInt(Result, getContext())) {
3571 llvm::APSInt EvaluatedChunk = Result.Val.getInt();
3572 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3573 }
3574 }
3575 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3576 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3577 // OpenMP 4.5, 2.7.1 Loop Construct, Description.
3578 // If the static schedule kind is specified or if the ordered clause is
3579 // specified, and if no monotonic modifier is specified, the effect will
3580 // be as if the monotonic modifier was specified.
3581 bool StaticChunkedOne =
3582 RT.isStaticChunked(ScheduleKind.Schedule,
3583 /* Chunked */ Chunk != nullptr) &&
3584 HasChunkSizeOne && isOpenMPLoopBoundSharingDirective(EKind);
3585 bool IsMonotonic =
3586 Ordered ||
3587 (ScheduleKind.Schedule == OMPC_SCHEDULE_static &&
3588 !(ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3589 ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3590 ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3591 ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3592 if ((RT.isStaticNonchunked(ScheduleKind.Schedule,
3593 /* Chunked */ Chunk != nullptr) ||
3594 StaticChunkedOne) &&
3595 !Ordered) {
3599 *this, S,
3600 [&S, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3601 if (isOpenMPSimdDirective(EKind)) {
3602 CGF.EmitOMPSimdInit(S);
3603 } else if (const auto *C = S.getSingleClause<OMPOrderClause>()) {
3604 if (C->getKind() == OMPC_ORDER_concurrent)
3605 CGF.LoopStack.setParallel(/*Enable=*/true);
3606 }
3607 },
3608 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3609 &S, ScheduleKind, LoopExit, EKind,
3610 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3611 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
3612 // When no chunk_size is specified, the iteration space is divided
3613 // into chunks that are approximately equal in size, and at most
3614 // one chunk is distributed to each thread. Note that the size of
3615 // the chunks is unspecified in this case.
3617 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3618 UB.getAddress(), ST.getAddress(),
3619 StaticChunkedOne ? Chunk : nullptr);
3621 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3622 // UB = min(UB, GlobalUB);
3623 if (!StaticChunkedOne)
3624 CGF.EmitIgnoredExpr(S.getEnsureUpperBound());
3625 // IV = LB;
3626 CGF.EmitIgnoredExpr(S.getInit());
3627 // For unchunked static schedule generate:
3628 //
3629 // while (idx <= UB) {
3630 // BODY;
3631 // ++idx;
3632 // }
3633 //
3634 // For static schedule with chunk one:
3635 //
3636 // while (IV <= PrevUB) {
3637 // BODY;
3638 // IV += ST;
3639 // }
3640 CGF.EmitOMPInnerLoop(
3641 S, LoopScope.requiresCleanups(),
3642 StaticChunkedOne ? S.getCombinedParForInDistCond()
3643 : S.getCond(),
3644 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3645 [&S, LoopExit](CodeGenFunction &CGF) {
3646 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3647 },
3648 [](CodeGenFunction &) {});
3649 });
3650 EmitBlock(LoopExit.getBlock());
3651 // Tell the runtime we are done.
3652 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
3653 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3654 OMPD_for);
3655 };
3656 OMPCancelStack.emitExit(*this, EKind, CodeGen);
3657 } else {
3658 // Emit the outer loop, which requests its work chunk [LB..UB] from
3659 // runtime and runs the inner loop to process it.
3660 OMPLoopArguments LoopArguments(LB.getAddress(), UB.getAddress(),
3661 ST.getAddress(), IL.getAddress(), Chunk,
3662 EUB);
3663 LoopArguments.DKind = OMPD_for;
3664 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3665 LoopArguments, CGDispatchBounds);
3666 }
3667 if (isOpenMPSimdDirective(EKind)) {
3668 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
3669 return CGF.Builder.CreateIsNotNull(
3670 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
3671 });
3672 }
3674 S, /*ReductionKind=*/isOpenMPSimdDirective(EKind)
3675 ? /*Parallel and Simd*/ OMPD_parallel_for_simd
3676 : /*Parallel only*/ OMPD_parallel);
3677 // Emit post-update of the reduction variables if IsLastIter != 0.
3679 *this, S, [IL, &S](CodeGenFunction &CGF) {
3680 return CGF.Builder.CreateIsNotNull(
3681 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
3682 });
3683 // Emit final copy of the lastprivate variables if IsLastIter != 0.
3684 if (HasLastprivateClause)
3686 S, isOpenMPSimdDirective(EKind),
3687 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
3688 LoopScope.restoreMap();
3689 EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) {
3690 return CGF.Builder.CreateIsNotNull(
3691 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
3692 });
3693 }
3694 DoacrossCleanupScope.ForceCleanup();
3695 // We're now done with the loop, so jump to the continuation block.
3696 if (ContBlock) {
3697 EmitBranch(ContBlock);
3698 EmitBlock(ContBlock, /*IsFinished=*/true);
3699 }
3700 }
3701 return HasLastprivateClause;
3702}
3703
3704/// The following two functions generate expressions for the loop lower
3705/// and upper bounds in case of static and dynamic (dispatch) schedule
3706/// of the associated 'for' or 'distribute' loop.
3707static std::pair<LValue, LValue>
3709 const auto &LS = cast<OMPLoopDirective>(S);
3710 LValue LB =
3711 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
3712 LValue UB =
3713 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable()));
3714 return {LB, UB};
3715}
3716
3717/// When dealing with dispatch schedules (e.g. dynamic, guided) we do not
3718/// consider the lower and upper bound expressions generated by the
3719/// worksharing loop support, but we use 0 and the iteration space size as
3720/// constants
3721static std::pair<llvm::Value *, llvm::Value *>
3723 Address LB, Address UB) {
3724 const auto &LS = cast<OMPLoopDirective>(S);
3725 const Expr *IVExpr = LS.getIterationVariable();
3726 const unsigned IVSize = CGF.getContext().getTypeSize(IVExpr->getType());
3727 llvm::Value *LBVal = CGF.Builder.getIntN(IVSize, 0);
3728 llvm::Value *UBVal = CGF.EmitScalarExpr(LS.getLastIteration());
3729 return {LBVal, UBVal};
3730}
3731
3732/// Emits internal temp array declarations for the directive with inscan
3733/// reductions.
3734/// The code is the following:
3735/// \code
3736/// size num_iters = <num_iters>;
3737/// <type> buffer[num_iters];
3738/// \endcode
3740 CodeGenFunction &CGF, const OMPLoopDirective &S,
3741 llvm::function_ref<llvm::Value *(CodeGenFunction &)> NumIteratorsGen) {
3742 llvm::Value *OMPScanNumIterations = CGF.Builder.CreateIntCast(
3743 NumIteratorsGen(CGF), CGF.SizeTy, /*isSigned=*/false);
3746 SmallVector<const Expr *, 4> ReductionOps;
3747 SmallVector<const Expr *, 4> CopyArrayTemps;
3748 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
3749 assert(C->getModifier() == OMPC_REDUCTION_inscan &&
3750 "Only inscan reductions are expected.");
3751 Shareds.append(C->varlist_begin(), C->varlist_end());
3752 Privates.append(C->privates().begin(), C->privates().end());
3753 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
3754 CopyArrayTemps.append(C->copy_array_temps().begin(),
3755 C->copy_array_temps().end());
3756 }
3757 {
3758 // Emit buffers for each reduction variables.
3759 // ReductionCodeGen is required to emit correctly the code for array
3760 // reductions.
3761 ReductionCodeGen RedCG(Shareds, Shareds, Privates, ReductionOps);
3762 unsigned Count = 0;
3763 auto *ITA = CopyArrayTemps.begin();
3764 for (const Expr *IRef : Privates) {
3765 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
3766 // Emit variably modified arrays, used for arrays/array sections
3767 // reductions.
3768 if (PrivateVD->getType()->isVariablyModifiedType()) {
3769 RedCG.emitSharedOrigLValue(CGF, Count);
3770 RedCG.emitAggregateType(CGF, Count);
3771 }
3773 CGF,
3774 cast<OpaqueValueExpr>(
3775 cast<VariableArrayType>((*ITA)->getType()->getAsArrayTypeUnsafe())
3776 ->getSizeExpr()),
3777 RValue::get(OMPScanNumIterations));
3778 // Emit temp buffer.
3779 CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(*ITA)->getDecl()));
3780 ++ITA;
3781 ++Count;
3782 }
3783 }
3784}
3785
3786/// Copies final inscan reductions values to the original variables.
3787/// The code is the following:
3788/// \code
3789/// <orig_var> = buffer[num_iters-1];
3790/// \endcode
3792 CodeGenFunction &CGF, const OMPLoopDirective &S,
3793 llvm::function_ref<llvm::Value *(CodeGenFunction &)> NumIteratorsGen) {
3794 llvm::Value *OMPScanNumIterations = CGF.Builder.CreateIntCast(
3795 NumIteratorsGen(CGF), CGF.SizeTy, /*isSigned=*/false);
3801 SmallVector<const Expr *, 4> CopyArrayElems;
3802 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
3803 assert(C->getModifier() == OMPC_REDUCTION_inscan &&
3804 "Only inscan reductions are expected.");
3805 Shareds.append(C->varlist_begin(), C->varlist_end());
3806 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
3807 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
3808 Privates.append(C->privates().begin(), C->privates().end());
3809 CopyOps.append(C->copy_ops().begin(), C->copy_ops().end());
3810 CopyArrayElems.append(C->copy_array_elems().begin(),
3811 C->copy_array_elems().end());
3812 }
3813 // Create temp var and copy LHS value to this temp value.
3814 // LHS = TMP[LastIter];
3815 llvm::Value *OMPLast = CGF.Builder.CreateNSWSub(
3816 OMPScanNumIterations,
3817 llvm::ConstantInt::get(CGF.SizeTy, 1, /*isSigned=*/false));
3818 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
3819 const Expr *PrivateExpr = Privates[I];
3820 const Expr *OrigExpr = Shareds[I];
3821 const Expr *CopyArrayElem = CopyArrayElems[I];
3823 CGF,
3824 cast<OpaqueValueExpr>(
3825 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
3826 RValue::get(OMPLast));
3827 LValue DestLVal = CGF.EmitLValue(OrigExpr);
3828 LValue SrcLVal = CGF.EmitLValue(CopyArrayElem);
3829 CGF.EmitOMPCopy(
3830 PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
3831 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
3832 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
3833 }
3834}
3835
3836/// Emits the code for the directive with inscan reductions.
3837/// The code is the following:
3838/// \code
3839/// #pragma omp ...
3840/// for (i: 0..<num_iters>) {
3841/// <input phase>;
3842/// buffer[i] = red;
3843/// }
3844/// #pragma omp master // in parallel region
3845/// for (int k = 0; k != ceil(log2(num_iters)); ++k)
3846/// for (size cnt = last_iter; cnt >= pow(2, k); --k)
3847/// buffer[i] op= buffer[i-pow(2,k)];
3848/// #pragma omp barrier // in parallel region
3849/// #pragma omp ...
3850/// for (0..<num_iters>) {
3851/// red = InclusiveScan ? buffer[i] : buffer[i-1];
3852/// <scan phase>;
3853/// }
3854/// \endcode
3856 CodeGenFunction &CGF, const OMPLoopDirective &S,
3857 llvm::function_ref<llvm::Value *(CodeGenFunction &)> NumIteratorsGen,
3858 llvm::function_ref<void(CodeGenFunction &)> FirstGen,
3859 llvm::function_ref<void(CodeGenFunction &)> SecondGen) {
3860 llvm::Value *OMPScanNumIterations = CGF.Builder.CreateIntCast(
3861 NumIteratorsGen(CGF), CGF.SizeTy, /*isSigned=*/false);
3863 SmallVector<const Expr *, 4> ReductionOps;
3866 SmallVector<const Expr *, 4> CopyArrayElems;
3867 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
3868 assert(C->getModifier() == OMPC_REDUCTION_inscan &&
3869 "Only inscan reductions are expected.");
3870 Privates.append(C->privates().begin(), C->privates().end());
3871 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
3872 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
3873 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
3874 CopyArrayElems.append(C->copy_array_elems().begin(),
3875 C->copy_array_elems().end());
3876 }
3878 {
3879 // Emit loop with input phase:
3880 // #pragma omp ...
3881 // for (i: 0..<num_iters>) {
3882 // <input phase>;
3883 // buffer[i] = red;
3884 // }
3885 CGF.OMPFirstScanLoop = true;
3887 FirstGen(CGF);
3888 }
3889 // #pragma omp barrier // in parallel region
3890 auto &&CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
3891 &ReductionOps,
3892 &Privates](CodeGenFunction &CGF, PrePostActionTy &Action) {
3893 Action.Enter(CGF);
3894 // Emit prefix reduction:
3895 // #pragma omp master // in parallel region
3896 // for (int k = 0; k <= ceil(log2(n)); ++k)
3897 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
3898 llvm::BasicBlock *LoopBB = CGF.createBasicBlock("omp.outer.log.scan.body");
3899 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("omp.outer.log.scan.exit");
3900 llvm::Function *F =
3901 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
3902 llvm::Value *Arg =
3903 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
3904 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
3905 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
3906 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
3907 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
3908 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
3909 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
3910 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, S.getBeginLoc());
3911 CGF.EmitBlock(LoopBB);
3912 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
3913 // size pow2k = 1;
3914 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3915 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
3916 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
3917 // for (size i = n - 1; i >= 2 ^ k; --i)
3918 // tmp[i] op= tmp[i-pow2k];
3919 llvm::BasicBlock *InnerLoopBB =
3920 CGF.createBasicBlock("omp.inner.log.scan.body");
3921 llvm::BasicBlock *InnerExitBB =
3922 CGF.createBasicBlock("omp.inner.log.scan.exit");
3923 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
3924 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3925 CGF.EmitBlock(InnerLoopBB);
3926 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3927 IVal->addIncoming(NMin1, LoopBB);
3928 {
3929 CodeGenFunction::OMPPrivateScope PrivScope(CGF);
3930 auto *ILHS = LHSs.begin();
3931 auto *IRHS = RHSs.begin();
3932 for (const Expr *CopyArrayElem : CopyArrayElems) {
3933 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3934 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3935 Address LHSAddr = Address::invalid();
3936 {
3938 CGF,
3939 cast<OpaqueValueExpr>(
3940 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
3941 RValue::get(IVal));
3942 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
3943 }
3944 PrivScope.addPrivate(LHSVD, LHSAddr);
3945 Address RHSAddr = Address::invalid();
3946 {
3947 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
3949 CGF,
3950 cast<OpaqueValueExpr>(
3951 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
3952 RValue::get(OffsetIVal));
3953 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
3954 }
3955 PrivScope.addPrivate(RHSVD, RHSAddr);
3956 ++ILHS;
3957 ++IRHS;
3958 }
3959 PrivScope.Privatize();
3960 CGF.CGM.getOpenMPRuntime().emitReduction(
3961 CGF, S.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
3962 {/*WithNowait=*/true, /*SimpleReduction=*/true,
3963 /*IsPrivateVarReduction*/ {}, OMPD_unknown});
3964 }
3965 llvm::Value *NextIVal =
3966 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
3967 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
3968 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
3969 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3970 CGF.EmitBlock(InnerExitBB);
3971 llvm::Value *Next =
3972 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
3973 Counter->addIncoming(Next, CGF.Builder.GetInsertBlock());
3974 // pow2k <<= 1;
3975 llvm::Value *NextPow2K =
3976 CGF.Builder.CreateShl(Pow2K, 1, "", /*HasNUW=*/true);
3977 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
3978 llvm::Value *Cmp = CGF.Builder.CreateICmpNE(Next, LogVal);
3979 CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
3980 auto DL1 = ApplyDebugLocation::CreateDefaultArtificial(CGF, S.getEndLoc());
3981 CGF.EmitBlock(ExitBB);
3982 };
3984 if (isOpenMPParallelDirective(EKind)) {
3985 CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc());
3987 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
3988 /*ForceSimpleCall=*/true);
3989 } else {
3990 RegionCodeGenTy RCG(CodeGen);
3991 RCG(CGF);
3992 }
3993
3994 CGF.OMPFirstScanLoop = false;
3995 SecondGen(CGF);
3996}
3997
3999 const OMPLoopDirective &S,
4000 bool HasCancel) {
4001 bool HasLastprivates;
4003 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4004 [](const OMPReductionClause *C) {
4005 return C->getModifier() == OMPC_REDUCTION_inscan;
4006 })) {
4007 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4009 OMPLoopScope LoopScope(CGF, S);
4010 return CGF.EmitScalarExpr(S.getNumIterations());
4011 };
4012 const auto &&FirstGen = [&S, HasCancel, EKind](CodeGenFunction &CGF) {
4013 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
4014 (void)CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
4017 // Emit an implicit barrier at the end.
4018 CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getBeginLoc(),
4019 OMPD_for);
4020 };
4021 const auto &&SecondGen = [&S, HasCancel, EKind,
4022 &HasLastprivates](CodeGenFunction &CGF) {
4023 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
4024 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
4027 };
4028 if (!isOpenMPParallelDirective(EKind))
4029 emitScanBasedDirectiveDecls(CGF, S, NumIteratorsGen);
4030 emitScanBasedDirective(CGF, S, NumIteratorsGen, FirstGen, SecondGen);
4031 if (!isOpenMPParallelDirective(EKind))
4032 emitScanBasedDirectiveFinals(CGF, S, NumIteratorsGen);
4033 } else {
4034 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
4035 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
4038 }
4039 return HasLastprivates;
4040}
4041
4042// Pass OMPLoopDirective (instead of OMPForDirective) to make this check
4043// available for "loop bind(parallel)", which maps to "for".
4045 bool HasCancel) {
4046 if (HasCancel)
4047 return false;
4048 for (OMPClause *C : S.clauses()) {
4049 if (isa<OMPNowaitClause, OMPBindClause>(C))
4050 continue;
4051
4052 if (auto *SC = dyn_cast<OMPScheduleClause>(C)) {
4053 if (SC->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown)
4054 return false;
4055 if (SC->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown)
4056 return false;
4057 switch (SC->getScheduleKind()) {
4058 case OMPC_SCHEDULE_auto:
4059 case OMPC_SCHEDULE_dynamic:
4060 case OMPC_SCHEDULE_runtime:
4061 case OMPC_SCHEDULE_guided:
4062 case OMPC_SCHEDULE_static:
4063 continue;
4065 return false;
4066 }
4067 }
4068
4069 return false;
4070 }
4071
4072 return true;
4073}
4074
4075static llvm::omp::ScheduleKind
4077 switch (ScheduleClauseKind) {
4079 return llvm::omp::OMP_SCHEDULE_Default;
4080 case OMPC_SCHEDULE_auto:
4081 return llvm::omp::OMP_SCHEDULE_Auto;
4082 case OMPC_SCHEDULE_dynamic:
4083 return llvm::omp::OMP_SCHEDULE_Dynamic;
4084 case OMPC_SCHEDULE_guided:
4085 return llvm::omp::OMP_SCHEDULE_Guided;
4086 case OMPC_SCHEDULE_runtime:
4087 return llvm::omp::OMP_SCHEDULE_Runtime;
4088 case OMPC_SCHEDULE_static:
4089 return llvm::omp::OMP_SCHEDULE_Static;
4090 }
4091 llvm_unreachable("Unhandled schedule kind");
4092}
4093
4094// Pass OMPLoopDirective (instead of OMPForDirective) to make this function
4095// available for "loop bind(parallel)", which maps to "for".
4097 CodeGenModule &CGM, bool HasCancel) {
4098 bool HasLastprivates = false;
4099 bool UseOMPIRBuilder = CGM.getLangOpts().OpenMPIRBuilder &&
4100 isForSupportedByOpenMPIRBuilder(S, HasCancel);
4101 auto &&CodeGen = [&S, &CGM, HasCancel, &HasLastprivates,
4102 UseOMPIRBuilder](CodeGenFunction &CGF, PrePostActionTy &) {
4103 // Use the OpenMPIRBuilder if enabled.
4104 if (UseOMPIRBuilder) {
4105 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4106
4107 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4108 llvm::Value *ChunkSize = nullptr;
4109 if (auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4110 SchedKind =
4111 convertClauseKindToSchedKind(SchedClause->getScheduleKind());
4112 if (const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4113 ChunkSize = CGF.EmitScalarExpr(ChunkSizeExpr);
4114 }
4115
4116 // Emit the associated statement and get its loop representation.
4117 const Stmt *Inner = S.getRawStmt();
4118 llvm::CanonicalLoopInfo *CLI =
4120
4121 llvm::OpenMPIRBuilder &OMPBuilder =
4123 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4124 CGF.AllocaInsertPt->getParent(), CGF.AllocaInsertPt->getIterator());
4125 cantFail(OMPBuilder.applyWorkshareLoop(
4126 CGF.Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4127 SchedKind, ChunkSize, /*HasSimdModifier=*/false,
4128 /*HasMonotonicModifier=*/false, /*HasNonmonotonicModifier=*/false,
4129 /*HasOrderedClause=*/false));
4130 return;
4131 }
4132
4133 HasLastprivates = emitWorksharingDirective(CGF, S, HasCancel);
4134 };
4135 {
4136 auto LPCRegion =
4138 OMPLexicalScope Scope(CGF, S, OMPD_unknown);
4139 CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_for, CodeGen,
4140 HasCancel);
4141 }
4142
4143 if (!UseOMPIRBuilder) {
4144 // Emit an implicit barrier at the end.
4145 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4146 CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getBeginLoc(), OMPD_for);
4147 }
4148 // Check for outer lastprivate conditional update.
4150}
4151
4153 return emitOMPForDirective(S, *this, CGM, S.hasCancel());
4154}
4155
4157 bool HasLastprivates = false;
4158 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4159 PrePostActionTy &) {
4160 HasLastprivates = emitWorksharingDirective(CGF, S, /*HasCancel=*/false);
4161 };
4162 {
4163 auto LPCRegion =
4165 OMPLexicalScope Scope(*this, S, OMPD_unknown);
4166 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
4167 }
4168
4169 // Emit an implicit barrier at the end.
4170 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4171 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
4172 // Check for outer lastprivate conditional update.
4174}
4175
4177 const Twine &Name,
4178 llvm::Value *Init = nullptr) {
4179 LValue LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
4180 if (Init)
4181 CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true);
4182 return LVal;
4183}
4184
4185void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
4186 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4187 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4188 bool HasLastprivates = false;
4190 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4191 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4192 const ASTContext &C = CGF.getContext();
4193 QualType KmpInt32Ty =
4194 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
4195 // Emit helper vars inits.
4196 LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
4197 CGF.Builder.getInt32(0));
4198 llvm::ConstantInt *GlobalUBVal = CS != nullptr
4199 ? CGF.Builder.getInt32(CS->size() - 1)
4200 : CGF.Builder.getInt32(0);
4201 LValue UB =
4202 createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
4203 LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
4204 CGF.Builder.getInt32(1));
4205 LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.",
4206 CGF.Builder.getInt32(0));
4207 // Loop counter.
4208 LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
4209 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
4210 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4211 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
4212 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4213 // Generate condition for loop.
4215 C, &IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_PRValue, OK_Ordinary,
4216 S.getBeginLoc(), FPOptionsOverride());
4217 // Increment for loop counter.
4219 C, &IVRefExpr, UO_PreInc, KmpInt32Ty, VK_PRValue, OK_Ordinary,
4220 S.getBeginLoc(), true, FPOptionsOverride());
4221 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4222 // Iterate through all sections and emit a switch construct:
4223 // switch (IV) {
4224 // case 0:
4225 // <SectionStmt[0]>;
4226 // break;
4227 // ...
4228 // case <NumSection> - 1:
4229 // <SectionStmt[<NumSection> - 1]>;
4230 // break;
4231 // }
4232 // .omp.sections.exit:
4233 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
4234 llvm::SwitchInst *SwitchStmt =
4235 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getBeginLoc()),
4236 ExitBB, CS == nullptr ? 1 : CS->size());
4237 if (CS) {
4238 unsigned CaseNumber = 0;
4239 for (const Stmt *SubStmt : CS->children()) {
4240 auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
4241 CGF.EmitBlock(CaseBB);
4242 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4243 CGF.EmitStmt(SubStmt);
4244 CGF.EmitBranch(ExitBB);
4245 ++CaseNumber;
4246 }
4247 } else {
4248 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(".omp.sections.case");
4249 CGF.EmitBlock(CaseBB);
4250 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4251 CGF.EmitStmt(CapturedStmt);
4252 CGF.EmitBranch(ExitBB);
4253 }
4254 CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
4255 };
4256
4257 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4258 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4259 // Emit implicit barrier to synchronize threads and avoid data races on
4260 // initialization of firstprivate variables and post-update of lastprivate
4261 // variables.
4262 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4263 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
4264 /*ForceSimpleCall=*/true);
4265 }
4266 CGF.EmitOMPPrivateClause(S, LoopScope);
4267 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4268 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4269 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4270 (void)LoopScope.Privatize();
4272 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4273
4274 // Emit static non-chunked loop.
4275 OpenMPScheduleTy ScheduleKind;
4276 ScheduleKind.Schedule = OMPC_SCHEDULE_static;
4278 /*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(),
4279 LB.getAddress(), UB.getAddress(), ST.getAddress());
4280 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.getBeginLoc(), EKind,
4281 ScheduleKind, StaticInit);
4282 // UB = min(UB, GlobalUB);
4283 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getBeginLoc());
4284 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4285 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4286 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4287 // IV = LB;
4288 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV);
4289 // while (idx <= UB) { BODY; ++idx; }
4290 CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, Cond, Inc, BodyGen,
4291 [](CodeGenFunction &) {});
4292 // Tell the runtime we are done.
4293 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4294 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
4295 OMPD_sections);
4296 };
4297 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4298 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
4299 // Emit post-update of the reduction variables if IsLastIter != 0.
4300 emitPostUpdateForReductionClause(CGF, S, [IL, &S](CodeGenFunction &CGF) {
4301 return CGF.Builder.CreateIsNotNull(
4302 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
4303 });
4304
4305 // Emit final copy of the lastprivate variables if IsLastIter != 0.
4306 if (HasLastprivates)
4308 S, /*NoFinals=*/false,
4309 CGF.Builder.CreateIsNotNull(
4310 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())));
4311 };
4312
4313 bool HasCancel = false;
4314 if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4315 HasCancel = OSD->hasCancel();
4316 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4317 HasCancel = OPSD->hasCancel();
4318 OMPCancelStackRAII CancelRegion(*this, EKind, HasCancel);
4319 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen,
4320 HasCancel);
4321 // Emit barrier for lastprivates only if 'sections' directive has 'nowait'
4322 // clause. Otherwise the barrier will be generated by the codegen for the
4323 // directive.
4324 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4325 // Emit implicit barrier to synchronize threads and avoid data races on
4326 // initialization of firstprivate variables.
4327 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
4328 OMPD_unknown);
4329 }
4330}
4331
4333 {
4334 // Emit code for 'scope' region
4335 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4336 Action.Enter(CGF);
4337 OMPPrivateScope PrivateScope(CGF);
4338 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4339 CGF.EmitOMPPrivateClause(S, PrivateScope);
4340 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4341 (void)PrivateScope.Privatize();
4342 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4343 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
4344 };
4345 auto LPCRegion =
4347 OMPLexicalScope Scope(*this, S, OMPD_unknown);
4348 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_scope, CodeGen);
4349 }
4350 // Emit an implicit barrier at the end.
4351 if (!S.getSingleClause<OMPNowaitClause>()) {
4352 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_scope);
4353 }
4354 // Check for outer lastprivate conditional update.
4356}
4357
4359 if (CGM.getLangOpts().OpenMPIRBuilder) {
4360 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
4361 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4362 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4363
4364 auto FiniCB = [](InsertPointTy IP) {
4365 // Don't FinalizeOMPRegion because this is done inside of OMPIRBuilder for
4366 // sections.
4367 return llvm::Error::success();
4368 };
4369
4370 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4371 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4372 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4374 if (CS) {
4375 for (const Stmt *SubStmt : CS->children()) {
4376 auto SectionCB = [this, SubStmt](InsertPointTy AllocaIP,
4377 InsertPointTy CodeGenIP) {
4379 *this, SubStmt, AllocaIP, CodeGenIP, "section");
4380 return llvm::Error::success();
4381 };
4382 SectionCBVector.push_back(SectionCB);
4383 }
4384 } else {
4385 auto SectionCB = [this, CapturedStmt](InsertPointTy AllocaIP,
4386 InsertPointTy CodeGenIP) {
4388 *this, CapturedStmt, AllocaIP, CodeGenIP, "section");
4389 return llvm::Error::success();
4390 };
4391 SectionCBVector.push_back(SectionCB);
4392 }
4393
4394 // Privatization callback that performs appropriate action for
4395 // shared/private/firstprivate/lastprivate/copyin/... variables.
4396 //
4397 // TODO: This defaults to shared right now.
4398 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4399 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4400 // The next line is appropriate only for variables (Val) with the
4401 // data-sharing attribute "shared".
4402 ReplVal = &Val;
4403
4404 return CodeGenIP;
4405 };
4406
4407 CGCapturedStmtInfo CGSI(*ICS, CR_OpenMP);
4408 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
4409 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4410 AllocaInsertPt->getParent(), AllocaInsertPt->getIterator());
4411 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4412 cantFail(OMPBuilder.createSections(
4413 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4414 S.getSingleClause<OMPNowaitClause>()));
4415 Builder.restoreIP(AfterIP);
4416 return;
4417 }
4418 {
4419 auto LPCRegion =
4421 OMPLexicalScope Scope(*this, S, OMPD_unknown);
4422 EmitSections(S);
4423 }
4424 // Emit an implicit barrier at the end.
4425 if (!S.getSingleClause<OMPNowaitClause>()) {
4426 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
4427 OMPD_sections);
4428 }
4429 // Check for outer lastprivate conditional update.
4431}
4432
4434 if (CGM.getLangOpts().OpenMPIRBuilder) {
4435 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
4436 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4437
4438 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4439 auto FiniCB = [this](InsertPointTy IP) {
4441 return llvm::Error::success();
4442 };
4443
4444 auto BodyGenCB = [SectionRegionBodyStmt, this](InsertPointTy AllocaIP,
4445 InsertPointTy CodeGenIP) {
4447 *this, SectionRegionBodyStmt, AllocaIP, CodeGenIP, "section");
4448 return llvm::Error::success();
4449 };
4450
4451 LexicalScope Scope(*this, S.getSourceRange());
4452 EmitStopPoint(&S);
4453 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4454 cantFail(OMPBuilder.createSection(Builder, BodyGenCB, FiniCB));
4455 Builder.restoreIP(AfterIP);
4456
4457 return;
4458 }
4459 LexicalScope Scope(*this, S.getSourceRange());
4460 EmitStopPoint(&S);
4461 EmitStmt(S.getAssociatedStmt());
4462}
4463
4465 llvm::SmallVector<const Expr *, 8> CopyprivateVars;
4469 // Check if there are any 'copyprivate' clauses associated with this
4470 // 'single' construct.
4471 // Build a list of copyprivate variables along with helper expressions
4472 // (<source>, <destination>, <destination>=<source> expressions)
4473 for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) {
4474 CopyprivateVars.append(C->varlist_begin(), C->varlist_end());
4475 DestExprs.append(C->destination_exprs().begin(),
4476 C->destination_exprs().end());
4477 SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end());
4478 AssignmentOps.append(C->assignment_ops().begin(),
4479 C->assignment_ops().end());
4480 }
4481 // Emit code for 'single' region along with 'copyprivate' clauses
4482 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4483 Action.Enter(CGF);
4487 (void)SingleScope.Privatize();
4488 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4489 };
4490 {
4491 auto LPCRegion =
4493 OMPLexicalScope Scope(*this, S, OMPD_unknown);
4494 CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getBeginLoc(),
4495 CopyprivateVars, DestExprs,
4496 SrcExprs, AssignmentOps);
4497 }
4498 // Emit an implicit barrier at the end (to avoid data race on firstprivate
4499 // init or if no 'nowait' clause was specified and no 'copyprivate' clause).
4500 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4502 *this, S.getBeginLoc(),
4503 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4504 }
4505 // Check for outer lastprivate conditional update.
4507}
4508
4510 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4511 Action.Enter(CGF);
4512 CGF.EmitStmt(S.getRawStmt());
4513 };
4514 CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc());
4515}
4516
4518 if (CGM.getLangOpts().OpenMPIRBuilder) {
4519 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
4520 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4521
4522 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4523
4524 auto FiniCB = [this](InsertPointTy IP) {
4526 return llvm::Error::success();
4527 };
4528
4529 auto BodyGenCB = [MasterRegionBodyStmt, this](InsertPointTy AllocaIP,
4530 InsertPointTy CodeGenIP) {
4532 *this, MasterRegionBodyStmt, AllocaIP, CodeGenIP, "master");
4533 return llvm::Error::success();
4534 };
4535
4536 LexicalScope Scope(*this, S.getSourceRange());
4537 EmitStopPoint(&S);
4538 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4539 cantFail(OMPBuilder.createMaster(Builder, BodyGenCB, FiniCB));
4540 Builder.restoreIP(AfterIP);
4541
4542 return;
4543 }
4544 LexicalScope Scope(*this, S.getSourceRange());
4545 EmitStopPoint(&S);
4546 emitMaster(*this, S);
4547}
4548
4550 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4551 Action.Enter(CGF);
4552 CGF.EmitStmt(S.getRawStmt());
4553 };
4554 Expr *Filter = nullptr;
4555 if (const auto *FilterClause = S.getSingleClause<OMPFilterClause>())
4556 Filter = FilterClause->getThreadID();
4557 CGF.CGM.getOpenMPRuntime().emitMaskedRegion(CGF, CodeGen, S.getBeginLoc(),
4558 Filter);
4559}
4560
4562 if (CGM.getLangOpts().OpenMPIRBuilder) {
4563 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
4564 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4565
4566 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4567 const Expr *Filter = nullptr;
4568 if (const auto *FilterClause = S.getSingleClause<OMPFilterClause>())
4569 Filter = FilterClause->getThreadID();
4570 llvm::Value *FilterVal = Filter
4571 ? EmitScalarExpr(Filter, CGM.Int32Ty)
4572 : llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/0);
4573
4574 auto FiniCB = [this](InsertPointTy IP) {
4576 return llvm::Error::success();
4577 };
4578
4579 auto BodyGenCB = [MaskedRegionBodyStmt, this](InsertPointTy AllocaIP,
4580 InsertPointTy CodeGenIP) {
4582 *this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP, "masked");
4583 return llvm::Error::success();
4584 };
4585
4586 LexicalScope Scope(*this, S.getSourceRange());
4587 EmitStopPoint(&S);
4588 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4589 OMPBuilder.createMasked(Builder, BodyGenCB, FiniCB, FilterVal));
4590 Builder.restoreIP(AfterIP);
4591
4592 return;
4593 }
4594 LexicalScope Scope(*this, S.getSourceRange());
4595 EmitStopPoint(&S);
4596 emitMasked(*this, S);
4597}
4598
4600 if (CGM.getLangOpts().OpenMPIRBuilder) {
4601 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
4602 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4603
4604 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4605 const Expr *Hint = nullptr;
4606 if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
4607 Hint = HintClause->getHint();
4608
4609 // TODO: This is slightly different from what's currently being done in
4610 // clang. Fix the Int32Ty to IntPtrTy (pointer width size) when everything
4611 // about typing is final.
4612 llvm::Value *HintInst = nullptr;
4613 if (Hint)
4614 HintInst =
4615 Builder.CreateIntCast(EmitScalarExpr(Hint), CGM.Int32Ty, false);
4616
4617 auto FiniCB = [this](InsertPointTy IP) {
4619 return llvm::Error::success();
4620 };
4621
4622 auto BodyGenCB = [CriticalRegionBodyStmt, this](InsertPointTy AllocaIP,
4623 InsertPointTy CodeGenIP) {
4625 *this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP, "critical");
4626 return llvm::Error::success();
4627 };
4628
4629 LexicalScope Scope(*this, S.getSourceRange());
4630 EmitStopPoint(&S);
4631 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4632 cantFail(OMPBuilder.createCritical(Builder, BodyGenCB, FiniCB,
4633 S.getDirectiveName().getAsString(),
4634 HintInst));
4635 Builder.restoreIP(AfterIP);
4636
4637 return;
4638 }
4639
4640 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4641 Action.Enter(CGF);
4642 CGF.EmitStmt(S.getAssociatedStmt());
4643 };
4644 const Expr *Hint = nullptr;
4645 if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
4646 Hint = HintClause->getHint();
4647 LexicalScope Scope(*this, S.getSourceRange());
4648 EmitStopPoint(&S);
4650 S.getDirectiveName().getAsString(),
4651 CodeGen, S.getBeginLoc(), Hint);
4652}
4653
4655 const OMPParallelForDirective &S) {
4656 // Emit directive as a combined directive that consists of two implicit
4657 // directives: 'parallel' with 'for' directive.
4658 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4659 Action.Enter(CGF);
4660 emitOMPCopyinClause(CGF, S);
4661 (void)emitWorksharingDirective(CGF, S, S.hasCancel());
4662 };
4663 {
4664 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4667 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGSI);
4668 OMPLoopScope LoopScope(CGF, S);
4669 return CGF.EmitScalarExpr(S.getNumIterations());
4670 };
4671 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4672 [](const OMPReductionClause *C) {
4673 return C->getModifier() == OMPC_REDUCTION_inscan;
4674 });
4675 if (IsInscan)
4676 emitScanBasedDirectiveDecls(*this, S, NumIteratorsGen);
4677 auto LPCRegion =
4679 emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen,
4681 if (IsInscan)
4682 emitScanBasedDirectiveFinals(*this, S, NumIteratorsGen);
4683 }
4684 // Check for outer lastprivate conditional update.
4686}
4687
4689 const OMPParallelForSimdDirective &S) {
4690 // Emit directive as a combined directive that consists of two implicit
4691 // directives: 'parallel' with 'for' directive.
4692 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4693 Action.Enter(CGF);
4694 emitOMPCopyinClause(CGF, S);
4695 (void)emitWorksharingDirective(CGF, S, /*HasCancel=*/false);
4696 };
4697 {
4698 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4701 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGSI);
4702 OMPLoopScope LoopScope(CGF, S);
4703 return CGF.EmitScalarExpr(S.getNumIterations());
4704 };
4705 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4706 [](const OMPReductionClause *C) {
4707 return C->getModifier() == OMPC_REDUCTION_inscan;
4708 });
4709 if (IsInscan)
4710 emitScanBasedDirectiveDecls(*this, S, NumIteratorsGen);
4711 auto LPCRegion =
4713 emitCommonOMPParallelDirective(*this, S, OMPD_for_simd, CodeGen,
4715 if (IsInscan)
4716 emitScanBasedDirectiveFinals(*this, S, NumIteratorsGen);
4717 }
4718 // Check for outer lastprivate conditional update.
4720}
4721
4723 const OMPParallelMasterDirective &S) {
4724 // Emit directive as a combined directive that consists of two implicit
4725 // directives: 'parallel' with 'master' directive.
4726 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4727 Action.Enter(CGF);
4728 OMPPrivateScope PrivateScope(CGF);
4729 emitOMPCopyinClause(CGF, S);
4730 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4731 CGF.EmitOMPPrivateClause(S, PrivateScope);
4732 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4733 (void)PrivateScope.Privatize();
4734 emitMaster(CGF, S);
4735 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
4736 };
4737 {
4738 auto LPCRegion =
4740 emitCommonOMPParallelDirective(*this, S, OMPD_master, CodeGen,
4743 [](CodeGenFunction &) { return nullptr; });
4744 }
4745 // Check for outer lastprivate conditional update.
4747}
4748
4750 const OMPParallelMaskedDirective &S) {
4751 // Emit directive as a combined directive that consists of two implicit
4752 // directives: 'parallel' with 'masked' directive.
4753 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4754 Action.Enter(CGF);
4755 OMPPrivateScope PrivateScope(CGF);
4756 emitOMPCopyinClause(CGF, S);
4757 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4758 CGF.EmitOMPPrivateClause(S, PrivateScope);
4759 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4760 (void)PrivateScope.Privatize();
4761 emitMasked(CGF, S);
4762 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
4763 };
4764 {
4765 auto LPCRegion =
4767 emitCommonOMPParallelDirective(*this, S, OMPD_masked, CodeGen,
4770 [](CodeGenFunction &) { return nullptr; });
4771 }
4772 // Check for outer lastprivate conditional update.
4774}
4775
4778 // Emit directive as a combined directive that consists of two implicit
4779 // directives: 'parallel' with 'sections' directive.
4780 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4781 Action.Enter(CGF);
4782 emitOMPCopyinClause(CGF, S);
4783 CGF.EmitSections(S);
4784 };
4785 {
4786 auto LPCRegion =
4788 emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen,
4790 }
4791 // Check for outer lastprivate conditional update.
4793}
4794
4795namespace {
4796/// Get the list of variables declared in the context of the untied tasks.
4797class CheckVarsEscapingUntiedTaskDeclContext final
4798 : public ConstStmtVisitor<CheckVarsEscapingUntiedTaskDeclContext> {
4800
4801public:
4802 explicit CheckVarsEscapingUntiedTaskDeclContext() = default;
4803 ~CheckVarsEscapingUntiedTaskDeclContext() = default;
4804 void VisitDeclStmt(const DeclStmt *S) {
4805 if (!S)
4806 return;
4807 // Need to privatize only local vars, static locals can be processed as is.
4808 for (const Decl *D : S->decls()) {
4809 if (const auto *VD = dyn_cast_or_null<VarDecl>(D))
4810 if (VD->hasLocalStorage())
4811 PrivateDecls.push_back(VD);
4812 }
4813 }
4814 void VisitOMPExecutableDirective(const OMPExecutableDirective *) {}
4815 void VisitCapturedStmt(const CapturedStmt *) {}
4816 void VisitLambdaExpr(const LambdaExpr *) {}
4817 void VisitBlockExpr(const BlockExpr *) {}
4818 void VisitStmt(const Stmt *S) {
4819 if (!S)
4820 return;
4821 for (const Stmt *Child : S->children())
4822 if (Child)
4823 Visit(Child);
4824 }
4825
4826 /// Swaps list of vars with the provided one.
4827 ArrayRef<const VarDecl *> getPrivateDecls() const { return PrivateDecls; }
4828};
4829} // anonymous namespace
4830
4833
4834 // First look for 'omp_all_memory' and add this first.
4835 bool OmpAllMemory = false;
4836 if (llvm::any_of(
4837 S.getClausesOfKind<OMPDependClause>(), [](const OMPDependClause *C) {
4838 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
4839 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
4840 })) {
4841 OmpAllMemory = true;
4842 // Since both OMPC_DEPEND_outallmemory and OMPC_DEPEND_inoutallmemory are
4843 // equivalent to the runtime, always use OMPC_DEPEND_outallmemory to
4844 // simplify.
4846 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
4847 /*IteratorExpr=*/nullptr);
4848 // Add a nullptr Expr to simplify the codegen in emitDependData.
4849 DD.DepExprs.push_back(nullptr);
4850 }
4851 // Add remaining dependences skipping any 'out' or 'inout' if they are
4852 // overridden by 'omp_all_memory'.
4853 for (const auto *C : S.getClausesOfKind<OMPDependClause>()) {
4854 OpenMPDependClauseKind Kind = C->getDependencyKind();
4855 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
4856 continue;
4857 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
4858 continue;
4860 Data.Dependences.emplace_back(C->getDependencyKind(), C->getModifier());
4861 DD.DepExprs.append(C->varlist_begin(), C->varlist_end());
4862 }
4863}
4864
4866 const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion,
4867 const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen,
4869 // Emit outlined function for task construct.
4870 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
4871 auto I = CS->getCapturedDecl()->param_begin();
4872 auto PartId = std::next(I);
4873 auto TaskT = std::next(I, 4);
4874 // Check if the task is final
4875 if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
4876 // If the condition constant folds and can be elided, try to avoid emitting
4877 // the condition and the dead arm of the if/else.
4878 const Expr *Cond = Clause->getCondition();
4879 bool CondConstant;
4880 if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
4881 Data.Final.setInt(CondConstant);
4882 else
4883 Data.Final.setPointer(EvaluateExprAsBool(Cond));
4884 } else {
4885 // By default the task is not final.
4886 Data.Final.setInt(/*IntVal=*/false);
4887 }
4888 // Check if the task has 'priority' clause.
4889 if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) {
4890 const Expr *Prio = Clause->getPriority();
4891 Data.Priority.setInt(/*IntVal=*/true);
4892 Data.Priority.setPointer(EmitScalarConversion(
4893 EmitScalarExpr(Prio), Prio->getType(),
4894 getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
4895 Prio->getExprLoc()));
4896 }
4897 // The first function argument for tasks is a thread id, the second one is a
4898 // part id (0 for tied tasks, >=0 for untied task).
4899 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
4900 // Get list of private variables.
4901 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
4902 auto IRef = C->varlist_begin();
4903 for (const Expr *IInit : C->private_copies()) {
4904 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
4905 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4906 Data.PrivateVars.push_back(*IRef);
4907 Data.PrivateCopies.push_back(IInit);
4908 }
4909 ++IRef;
4910 }
4911 }
4912 EmittedAsPrivate.clear();
4913 // Get list of firstprivate variables.
4914 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
4915 auto IRef = C->varlist_begin();
4916 auto IElemInitRef = C->inits().begin();
4917 for (const Expr *IInit : C->private_copies()) {
4918 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
4919 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4920 Data.FirstprivateVars.push_back(*IRef);
4921 Data.FirstprivateCopies.push_back(IInit);
4922 Data.FirstprivateInits.push_back(*IElemInitRef);
4923 }
4924 ++IRef;
4925 ++IElemInitRef;
4926 }
4927 }
4928 // Get list of lastprivate variables (for taskloops).
4929 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
4930 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
4931 auto IRef = C->varlist_begin();
4932 auto ID = C->destination_exprs().begin();
4933 for (const Expr *IInit : C->private_copies()) {
4934 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
4935 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4936 Data.LastprivateVars.push_back(*IRef);
4937 Data.LastprivateCopies.push_back(IInit);
4938 }
4939 LastprivateDstsOrigs.insert(
4940 std::make_pair(cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
4941 cast<DeclRefExpr>(*IRef)));
4942 ++IRef;
4943 ++ID;
4944 }
4945 }
4948 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
4949 Data.ReductionVars.append(C->varlist_begin(), C->varlist_end());
4950 Data.ReductionOrigs.append(C->varlist_begin(), C->varlist_end());
4951 Data.ReductionCopies.append(C->privates().begin(), C->privates().end());
4952 Data.ReductionOps.append(C->reduction_ops().begin(),
4953 C->reduction_ops().end());
4954 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
4955 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
4956 }
4958 *this, S.getBeginLoc(), LHSs, RHSs, Data);
4959 // Build list of dependences.
4961 // Get list of local vars for untied tasks.
4962 if (!Data.Tied) {
4963 CheckVarsEscapingUntiedTaskDeclContext Checker;
4964 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
4965 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
4966 Checker.getPrivateDecls().end());
4967 }
4968 auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
4969 CapturedRegion](CodeGenFunction &CGF,
4970 PrePostActionTy &Action) {
4971 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
4972 std::pair<Address, Address>>
4973 UntiedLocalVars;
4974 // Set proper addresses for generated private copies.
4976 // Generate debug info for variables present in shared clause.
4977 if (auto *DI = CGF.getDebugInfo()) {
4978 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
4979 CGF.CapturedStmtInfo->getCaptureFields();
4980 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
4981 if (CaptureFields.size() && ContextValue) {
4982 unsigned CharWidth = CGF.getContext().getCharWidth();
4983 // The shared variables are packed together as members of structure.
4984 // So the address of each shared variable can be computed by adding
4985 // offset of it (within record) to the base address of record. For each
4986 // shared variable, debug intrinsic llvm.dbg.declare is generated with
4987 // appropriate expressions (DIExpression).
4988 // Ex:
4989 // %12 = load %struct.anon*, %struct.anon** %__context.addr.i
4990 // call void @llvm.dbg.declare(metadata %struct.anon* %12,
4991 // metadata !svar1,
4992 // metadata !DIExpression(DW_OP_deref))
4993 // call void @llvm.dbg.declare(metadata %struct.anon* %12,
4994 // metadata !svar2,
4995 // metadata !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref))
4996 for (auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
4997 const VarDecl *SharedVar = It->first;
4998 RecordDecl *CaptureRecord = It->second->getParent();
4999 const ASTRecordLayout &Layout =
5000 CGF.getContext().getASTRecordLayout(CaptureRecord);
5001 unsigned Offset =
5002 Layout.getFieldOffset(It->second->getFieldIndex()) / CharWidth;
5003 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5004 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5005 CGF.Builder, false);
5006 // Get the call dbg.declare instruction we just created and update
5007 // its DIExpression to add offset to base address.
5008 auto UpdateExpr = [](llvm::LLVMContext &Ctx, auto *Declare,
5009 unsigned Offset) {
5011 // Add offset to the base address if non zero.
5012 if (Offset) {
5013 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5014 Ops.push_back(Offset);
5015 }
5016 Ops.push_back(llvm::dwarf::DW_OP_deref);
5017 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5018 };
5019 llvm::Instruction &Last = CGF.Builder.GetInsertBlock()->back();
5020 if (auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&Last))
5021 UpdateExpr(DDI->getContext(), DDI, Offset);
5022 // If we're emitting using the new debug info format into a block
5023 // without a terminator, the record will be "trailing".
5024 assert(!Last.isTerminator() && "unexpected terminator");
5025 if (auto *Marker =
5026 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5027 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5028 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5029 UpdateExpr(Last.getContext(), &DVR, Offset);
5030 break;
5031 }
5032 }
5033 }
5034 }
5035 }
5037 if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() ||
5038 !Data.LastprivateVars.empty() || !Data.PrivateLocals.empty()) {
5039 enum { PrivatesParam = 2, CopyFnParam = 3 };
5040 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5041 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
5042 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5043 CS->getCapturedDecl()->getParam(PrivatesParam)));
5044 // Map privates.
5048 CallArgs.push_back(PrivatesPtr);
5049 ParamTypes.push_back(PrivatesPtr->getType());
5050 for (const Expr *E : Data.PrivateVars) {
5051 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5052 RawAddress PrivatePtr = CGF.CreateMemTemp(
5053 CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr");
5054 PrivatePtrs.emplace_back(VD, PrivatePtr);
5055 CallArgs.push_back(PrivatePtr.getPointer());
5056 ParamTypes.push_back(PrivatePtr.getType());
5057 }
5058 for (const Expr *E : Data.FirstprivateVars) {
5059 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5060 RawAddress PrivatePtr =
5061 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
5062 ".firstpriv.ptr.addr");
5063 PrivatePtrs.emplace_back(VD, PrivatePtr);
5064 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5065 CallArgs.push_back(PrivatePtr.getPointer());
5066 ParamTypes.push_back(PrivatePtr.getType());
5067 }
5068 for (const Expr *E : Data.LastprivateVars) {
5069 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5070 RawAddress PrivatePtr =
5071 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
5072 ".lastpriv.ptr.addr");
5073 PrivatePtrs.emplace_back(VD, PrivatePtr);
5074 CallArgs.push_back(PrivatePtr.getPointer());
5075 ParamTypes.push_back(PrivatePtr.getType());
5076 }
5077 for (const VarDecl *VD : Data.PrivateLocals) {
5079 if (VD->getType()->isLValueReferenceType())
5080 Ty = CGF.getContext().getPointerType(Ty);
5081 if (isAllocatableDecl(VD))
5082 Ty = CGF.getContext().getPointerType(Ty);
5083 RawAddress PrivatePtr = CGF.CreateMemTemp(
5084 CGF.getContext().getPointerType(Ty), ".local.ptr.addr");
5085 auto Result = UntiedLocalVars.insert(
5086 std::make_pair(VD, std::make_pair(PrivatePtr, Address::invalid())));
5087 // If key exists update in place.
5088 if (Result.second == false)
5089 *Result.first = std::make_pair(
5090 VD, std::make_pair(PrivatePtr, Address::invalid()));
5091 CallArgs.push_back(PrivatePtr.getPointer());
5092 ParamTypes.push_back(PrivatePtr.getType());
5093 }
5094 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5095 ParamTypes, /*isVarArg=*/false);
5096 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5097 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5098 for (const auto &Pair : LastprivateDstsOrigs) {
5099 const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
5100 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(OrigVD),
5101 /*RefersToEnclosingVariableOrCapture=*/
5102 CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,
5103 Pair.second->getType(), VK_LValue,
5104 Pair.second->getExprLoc());
5105 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5106 }
5107 for (const auto &Pair : PrivatePtrs) {
5108 Address Replacement = Address(
5109 CGF.Builder.CreateLoad(Pair.second),
5110 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5111 CGF.getContext().getDeclAlign(Pair.first));
5112 Scope.addPrivate(Pair.first, Replacement);
5113 if (auto *DI = CGF.getDebugInfo())
5114 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5115 (void)DI->EmitDeclareOfAutoVariable(
5116 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5117 /*UsePointerValue*/ true);
5118 }
5119 // Adjust mapping for internal locals by mapping actual memory instead of
5120 // a pointer to this memory.
5121 for (auto &Pair : UntiedLocalVars) {
5122 QualType VDType = Pair.first->getType().getNonReferenceType();
5123 if (Pair.first->getType()->isLValueReferenceType())
5124 VDType = CGF.getContext().getPointerType(VDType);
5125 if (isAllocatableDecl(Pair.first)) {
5126 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5127 Address Replacement(
5128 Ptr,
5129 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5130 CGF.getPointerAlign());
5131 Pair.second.first = Replacement;
5132 Ptr = CGF.Builder.CreateLoad(Replacement);
5133 Replacement = Address(Ptr, CGF.ConvertTypeForMem(VDType),
5134 CGF.getContext().getDeclAlign(Pair.first));
5135 Pair.second.second = Replacement;
5136 } else {
5137 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5138 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5139 CGF.getContext().getDeclAlign(Pair.first));
5140 Pair.second.first = Replacement;
5141 }
5142 }
5143 }
5144 if (Data.Reductions) {
5145 OMPPrivateScope FirstprivateScope(CGF);
5146 for (const auto &Pair : FirstprivatePtrs) {
5147 Address Replacement(
5148 CGF.Builder.CreateLoad(Pair.second),
5149 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5150 CGF.getContext().getDeclAlign(Pair.first));
5151 FirstprivateScope.addPrivate(Pair.first, Replacement);
5152 }
5153 (void)FirstprivateScope.Privatize();
5154 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5155 ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionVars,
5156 Data.ReductionCopies, Data.ReductionOps);
5157 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5158 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9)));
5159 for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5160 RedCG.emitSharedOrigLValue(CGF, Cnt);
5161 RedCG.emitAggregateType(CGF, Cnt);
5162 // FIXME: This must removed once the runtime library is fixed.
5163 // Emit required threadprivate variables for
5164 // initializer/combiner/finalizer.
5165 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5166 RedCG, Cnt);
5167 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5168 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5169 Replacement = Address(
5170 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5171 CGF.getContext().VoidPtrTy,
5172 CGF.getContext().getPointerType(
5173 Data.ReductionCopies[Cnt]->getType()),
5174 Data.ReductionCopies[Cnt]->getExprLoc()),
5175 CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()),
5176 Replacement.getAlignment());
5177 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5178 Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5179 }
5180 }
5181 // Privatize all private variables except for in_reduction items.
5182 (void)Scope.Privatize();
5186 SmallVector<const Expr *, 4> TaskgroupDescriptors;
5187 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) {
5188 auto IPriv = C->privates().begin();
5189 auto IRed = C->reduction_ops().begin();
5190 auto ITD = C->taskgroup_descriptors().begin();
5191 for (const Expr *Ref : C->varlist()) {
5192 InRedVars.emplace_back(Ref);
5193 InRedPrivs.emplace_back(*IPriv);
5194 InRedOps.emplace_back(*IRed);
5195 TaskgroupDescriptors.emplace_back(*ITD);
5196 std::advance(IPriv, 1);
5197 std::advance(IRed, 1);
5198 std::advance(ITD, 1);
5199 }
5200 }
5201 // Privatize in_reduction items here, because taskgroup descriptors must be
5202 // privatized earlier.
5203 OMPPrivateScope InRedScope(CGF);
5204 if (!InRedVars.empty()) {
5205 ReductionCodeGen RedCG(InRedVars, InRedVars, InRedPrivs, InRedOps);
5206 for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5207 RedCG.emitSharedOrigLValue(CGF, Cnt);
5208 RedCG.emitAggregateType(CGF, Cnt);
5209 // The taskgroup descriptor variable is always implicit firstprivate and
5210 // privatized already during processing of the firstprivates.
5211 // FIXME: This must removed once the runtime library is fixed.
5212 // Emit required threadprivate variables for
5213 // initializer/combiner/finalizer.
5214 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5215 RedCG, Cnt);
5216 llvm::Value *ReductionsPtr;
5217 if (const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5218 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5219 TRExpr->getExprLoc());
5220 } else {
5221 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5222 }
5223 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5224 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5225 Replacement = Address(
5226 CGF.EmitScalarConversion(
5227 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5228 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5229 InRedPrivs[Cnt]->getExprLoc()),
5230 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5231 Replacement.getAlignment());
5232 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5233 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5234 }
5235 }
5236 (void)InRedScope.Privatize();
5237
5239 UntiedLocalVars);
5240 Action.Enter(CGF);
5241 BodyGen(CGF);
5242 };
5244 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5245 S, *I, *PartId, *TaskT, EKind, CodeGen, Data.Tied, Data.NumberOfParts);
5246 OMPLexicalScope Scope(*this, S, std::nullopt,
5247 !isOpenMPParallelDirective(EKind) &&
5248 !isOpenMPSimdDirective(EKind));
5249 TaskGen(*this, OutlinedFn, Data);
5250}
5251
5252static ImplicitParamDecl *
5254 QualType Ty, CapturedDecl *CD,
5256 auto *OrigVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
5258 auto *OrigRef = DeclRefExpr::Create(
5260 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
5261 auto *PrivateVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
5263 auto *PrivateRef = DeclRefExpr::Create(
5264 C, NestedNameSpecifierLoc(), SourceLocation(), PrivateVD,
5265 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
5266 QualType ElemType = C.getBaseElementType(Ty);
5267 auto *InitVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, ElemType,
5269 auto *InitRef = DeclRefExpr::Create(
5271 /*RefersToEnclosingVariableOrCapture=*/false, Loc, ElemType, VK_LValue);
5272 PrivateVD->setInitStyle(VarDecl::CInit);
5273 PrivateVD->setInit(ImplicitCastExpr::Create(C, ElemType, CK_LValueToRValue,
5274 InitRef, /*BasePath=*/nullptr,
5276 Data.FirstprivateVars.emplace_back(OrigRef);
5277 Data.FirstprivateCopies.emplace_back(PrivateRef);
5278 Data.FirstprivateInits.emplace_back(InitRef);
5279 return OrigVD;
5280}
5281
5283 const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen,
5284 OMPTargetDataInfo &InputInfo) {
5285 // Emit outlined function for task construct.
5286 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
5287 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
5288 CanQualType SharedsTy =
5290 auto I = CS->getCapturedDecl()->param_begin();
5291 auto PartId = std::next(I);
5292 auto TaskT = std::next(I, 4);
5294 // The task is not final.
5295 Data.Final.setInt(/*IntVal=*/false);
5296 // Get list of firstprivate variables.
5297 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5298 auto IRef = C->varlist_begin();
5299 auto IElemInitRef = C->inits().begin();
5300 for (auto *IInit : C->private_copies()) {
5301 Data.FirstprivateVars.push_back(*IRef);
5302 Data.FirstprivateCopies.push_back(IInit);
5303 Data.FirstprivateInits.push_back(*IElemInitRef);
5304 ++IRef;
5305 ++IElemInitRef;
5306 }
5307 }
5310 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) {
5311 Data.ReductionVars.append(C->varlist_begin(), C->varlist_end());
5312 Data.ReductionOrigs.append(C->varlist_begin(), C->varlist_end());
5313 Data.ReductionCopies.append(C->privates().begin(), C->privates().end());
5314 Data.ReductionOps.append(C->reduction_ops().begin(),
5315 C->reduction_ops().end());
5316 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
5317 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
5318 }
5319 OMPPrivateScope TargetScope(*this);
5320 VarDecl *BPVD = nullptr;
5321 VarDecl *PVD = nullptr;
5322 VarDecl *SVD = nullptr;
5323 VarDecl *MVD = nullptr;
5324 if (InputInfo.NumberOfTargetItems > 0) {
5325 auto *CD = CapturedDecl::Create(
5326 getContext(), getContext().getTranslationUnitDecl(), /*NumParams=*/0);
5327 llvm::APInt ArrSize(/*numBits=*/32, InputInfo.NumberOfTargetItems);
5328 QualType BaseAndPointerAndMapperType = getContext().getConstantArrayType(
5329 getContext().VoidPtrTy, ArrSize, nullptr, ArraySizeModifier::Normal,
5330 /*IndexTypeQuals=*/0);
5332 getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5334 getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5336 getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1),
5337 ArrSize, nullptr, ArraySizeModifier::Normal,
5338 /*IndexTypeQuals=*/0);
5339 SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD,
5340 S.getBeginLoc());
5341 TargetScope.addPrivate(BPVD, InputInfo.BasePointersArray);
5342 TargetScope.addPrivate(PVD, InputInfo.PointersArray);
5343 TargetScope.addPrivate(SVD, InputInfo.SizesArray);
5344 // If there is no user-defined mapper, the mapper array will be nullptr. In
5345 // this case, we don't need to privatize it.
5346 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5347 InputInfo.MappersArray.emitRawPointer(*this))) {
5349 getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5350 TargetScope.addPrivate(MVD, InputInfo.MappersArray);
5351 }
5352 }
5353 (void)TargetScope.Privatize();
5356 auto &&CodeGen = [&Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5357 &InputInfo](CodeGenFunction &CGF, PrePostActionTy &Action) {
5358 // Set proper addresses for generated private copies.
5360 if (!Data.FirstprivateVars.empty()) {
5361 enum { PrivatesParam = 2, CopyFnParam = 3 };
5362 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5363 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
5364 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5365 CS->getCapturedDecl()->getParam(PrivatesParam)));
5366 // Map privates.
5370 CallArgs.push_back(PrivatesPtr);
5371 ParamTypes.push_back(PrivatesPtr->getType());
5372 for (const Expr *E : Data.FirstprivateVars) {
5373 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5374 RawAddress PrivatePtr =
5375 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
5376 ".firstpriv.ptr.addr");
5377 PrivatePtrs.emplace_back(VD, PrivatePtr);
5378 CallArgs.push_back(PrivatePtr.getPointer());
5379 ParamTypes.push_back(PrivatePtr.getType());
5380 }
5381 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5382 ParamTypes, /*isVarArg=*/false);
5383 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5384 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5385 for (const auto &Pair : PrivatePtrs) {
5386 Address Replacement(
5387 CGF.Builder.CreateLoad(Pair.second),
5388 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5389 CGF.getContext().getDeclAlign(Pair.first));
5390 Scope.addPrivate(Pair.first, Replacement);
5391 }
5392 }
5393 CGF.processInReduction(S, Data, CGF, CS, Scope);
5394 if (InputInfo.NumberOfTargetItems > 0) {
5395 InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP(
5396 CGF.GetAddrOfLocalVar(BPVD), /*Index=*/0);
5397 InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP(
5398 CGF.GetAddrOfLocalVar(PVD), /*Index=*/0);
5399 InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP(
5400 CGF.GetAddrOfLocalVar(SVD), /*Index=*/0);
5401 // If MVD is nullptr, the mapper array is not privatized
5402 if (MVD)
5403 InputInfo.MappersArray = CGF.Builder.CreateConstArrayGEP(
5404 CGF.GetAddrOfLocalVar(MVD), /*Index=*/0);
5405 }
5406
5407 Action.Enter(CGF);
5408 OMPLexicalScope LexScope(CGF, S, OMPD_task, /*EmitPreInitStmt=*/false);
5409 auto *TL = S.getSingleClause<OMPThreadLimitClause>();
5410 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5411 needsTaskBasedThreadLimit(EKind) && TL) {
5412 // Emit __kmpc_set_thread_limit() to set the thread_limit for the task
5413 // enclosing this target region. This will indirectly set the thread_limit
5414 // for every applicable construct within target region.
5415 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5416 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5417 }
5418 BodyGen(CGF);
5419 };
5420 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5421 S, *I, *PartId, *TaskT, EKind, CodeGen, /*Tied=*/true,
5422 Data.NumberOfParts);
5423 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5424 IntegerLiteral IfCond(getContext(), TrueOrFalse,
5425 getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
5426 SourceLocation());
5427 CGM.getOpenMPRuntime().emitTaskCall(*this, S.getBeginLoc(), S, OutlinedFn,
5428 SharedsTy, CapturedStruct, &IfCond, Data);
5429}
5430
5433 CodeGenFunction &CGF,
5434 const CapturedStmt *CS,
5437 if (Data.Reductions) {
5438 OpenMPDirectiveKind CapturedRegion = EKind;
5439 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5440 ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionVars,
5441 Data.ReductionCopies, Data.ReductionOps);
5442 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5444 for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5445 RedCG.emitSharedOrigLValue(CGF, Cnt);
5446 RedCG.emitAggregateType(CGF, Cnt);
5447 // FIXME: This must removed once the runtime library is fixed.
5448 // Emit required threadprivate variables for
5449 // initializer/combiner/finalizer.
5450 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5451 RedCG, Cnt);
5453 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5454 Replacement = Address(
5455 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5456 CGF.getContext().VoidPtrTy,
5458 Data.ReductionCopies[Cnt]->getType()),
5459 Data.ReductionCopies[Cnt]->getExprLoc()),
5460 CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()),
5461 Replacement.getAlignment());
5462 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5463 Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5464 }
5465 }
5466 (void)Scope.Privatize();
5470 SmallVector<const Expr *, 4> TaskgroupDescriptors;
5471 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) {
5472 auto IPriv = C->privates().begin();
5473 auto IRed = C->reduction_ops().begin();
5474 auto ITD = C->taskgroup_descriptors().begin();
5475 for (const Expr *Ref : C->varlist()) {
5476 InRedVars.emplace_back(Ref);
5477 InRedPrivs.emplace_back(*IPriv);
5478 InRedOps.emplace_back(*IRed);
5479 TaskgroupDescriptors.emplace_back(*ITD);
5480 std::advance(IPriv, 1);
5481 std::advance(IRed, 1);
5482 std::advance(ITD, 1);
5483 }
5484 }
5485 OMPPrivateScope InRedScope(CGF);
5486 if (!InRedVars.empty()) {
5487 ReductionCodeGen RedCG(InRedVars, InRedVars, InRedPrivs, InRedOps);
5488 for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5489 RedCG.emitSharedOrigLValue(CGF, Cnt);
5490 RedCG.emitAggregateType(CGF, Cnt);
5491 // FIXME: This must removed once the runtime library is fixed.
5492 // Emit required threadprivate variables for
5493 // initializer/combiner/finalizer.
5494 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5495 RedCG, Cnt);
5496 llvm::Value *ReductionsPtr;
5497 if (const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5498 ReductionsPtr =
5499 CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr), TRExpr->getExprLoc());
5500 } else {
5501 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5502 }
5504 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5505 Replacement = Address(
5507 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5508 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5509 InRedPrivs[Cnt]->getExprLoc()),
5510 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5511 Replacement.getAlignment());
5512 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5513 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5514 }
5515 }
5516 (void)InRedScope.Privatize();
5517}
5518
5520 // Emit outlined function for task construct.
5521 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
5522 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
5523 CanQualType SharedsTy =
5525 const Expr *IfCond = nullptr;
5526 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
5527 if (C->getNameModifier() == OMPD_unknown ||
5528 C->getNameModifier() == OMPD_task) {
5529 IfCond = C->getCondition();
5530 break;
5531 }
5532 }
5533
5535 // Check if we should emit tied or untied task.
5536 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5537 auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) {
5538 CGF.EmitStmt(CS->getCapturedStmt());
5539 };
5540 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5541 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5542 const OMPTaskDataTy &Data) {
5543 CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getBeginLoc(), S, OutlinedFn,
5544 SharedsTy, CapturedStruct, IfCond,
5545 Data);
5546 };
5547 auto LPCRegion =
5549 EmitOMPTaskBasedDirective(S, OMPD_task, BodyGen, TaskGen, Data);
5550}
5551
5553 const OMPTaskyieldDirective &S) {
5554 CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getBeginLoc());
5555}
5556
5558 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5559 Expr *ME = MC ? MC->getMessageString() : nullptr;
5560 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5561 bool IsFatal = false;
5562 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5563 IsFatal = true;
5564 CGM.getOpenMPRuntime().emitErrorCall(*this, S.getBeginLoc(), ME, IsFatal);
5565}
5566
5568 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_barrier);
5569}
5570
5573 // Build list of dependences
5575 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5576 CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data);
5577}
5578
5580 return T.clauses().empty();
5581}
5582
5584 const OMPTaskgroupDirective &S) {
5585 OMPLexicalScope Scope(*this, S, OMPD_unknown);
5586 if (CGM.getLangOpts().OpenMPIRBuilder && isSupportedByOpenMPIRBuilder(S)) {
5587 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
5588 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5589 InsertPointTy AllocaIP(AllocaInsertPt->getParent(),
5590 AllocaInsertPt->getIterator());
5591
5592 auto BodyGenCB = [&, this](InsertPointTy AllocaIP,
5593 InsertPointTy CodeGenIP) {
5594 Builder.restoreIP(CodeGenIP);
5595 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5596 return llvm::Error::success();
5597 };
5599 if (!CapturedStmtInfo)
5600 CapturedStmtInfo = &CapStmtInfo;
5601 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5602 cantFail(OMPBuilder.createTaskgroup(Builder, AllocaIP, BodyGenCB));
5603 Builder.restoreIP(AfterIP);
5604 return;
5605 }
5606 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5607 Action.Enter(CGF);
5608 if (const Expr *E = S.getReductionRef()) {
5612 for (const auto *C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5613 Data.ReductionVars.append(C->varlist_begin(), C->varlist_end());
5614 Data.ReductionOrigs.append(C->varlist_begin(), C->varlist_end());
5615 Data.ReductionCopies.append(C->privates().begin(), C->privates().end());
5616 Data.ReductionOps.append(C->reduction_ops().begin(),
5617 C->reduction_ops().end());
5618 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
5619 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
5620 }
5621 llvm::Value *ReductionDesc =
5622 CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getBeginLoc(),
5623 LHSs, RHSs, Data);
5624 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5625 CGF.EmitVarDecl(*VD);
5626 CGF.EmitStoreOfScalar(ReductionDesc, CGF.GetAddrOfLocalVar(VD),
5627 /*Volatile=*/false, E->getType());
5628 }
5629 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5630 };
5631 CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc());
5632}
5633
5635 llvm::AtomicOrdering AO = S.getSingleClause<OMPFlushClause>()
5636 ? llvm::AtomicOrdering::NotAtomic
5637 : llvm::AtomicOrdering::AcquireRelease;
5639 *this,
5640 [&S]() -> ArrayRef<const Expr *> {
5641 if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>())
5642 return llvm::ArrayRef(FlushClause->varlist_begin(),
5643 FlushClause->varlist_end());
5644 return {};
5645 }(),
5646 S.getBeginLoc(), AO);
5647}
5648
5650 const auto *DO = S.getSingleClause<OMPDepobjClause>();
5651 LValue DOLVal = EmitLValue(DO->getDepobj());
5652 if (const auto *DC = S.getSingleClause<OMPDependClause>()) {
5653 // Build list and emit dependences
5656 for (auto &Dep : Data.Dependences) {
5658 *this, Dep, DC->getBeginLoc());
5659 EmitStoreOfScalar(DepAddr.emitRawPointer(*this), DOLVal);
5660 }
5661 return;
5662 }
5663 if (const auto *DC = S.getSingleClause<OMPDestroyClause>()) {
5664 CGM.getOpenMPRuntime().emitDestroyClause(*this, DOLVal, DC->getBeginLoc());
5665 return;
5666 }
5667 if (const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
5669 *this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5670 return;
5671 }
5672}
5673
5676 return;
5678 bool IsInclusive = S.hasClausesOfKind<OMPInclusiveClause>();
5683 SmallVector<const Expr *, 4> ReductionOps;
5685 SmallVector<const Expr *, 4> CopyArrayTemps;
5686 SmallVector<const Expr *, 4> CopyArrayElems;
5687 for (const auto *C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
5688 if (C->getModifier() != OMPC_REDUCTION_inscan)
5689 continue;
5690 Shareds.append(C->varlist_begin(), C->varlist_end());
5691 Privates.append(C->privates().begin(), C->privates().end());
5692 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
5693 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
5694 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
5695 CopyOps.append(C->copy_ops().begin(), C->copy_ops().end());
5696 CopyArrayTemps.append(C->copy_array_temps().begin(),
5697 C->copy_array_temps().end());
5698 CopyArrayElems.append(C->copy_array_elems().begin(),
5699 C->copy_array_elems().end());
5700 }
5701 if (ParentDir.getDirectiveKind() == OMPD_simd ||
5702 (getLangOpts().OpenMPSimd &&
5704 // For simd directive and simd-based directives in simd only mode, use the
5705 // following codegen:
5706 // int x = 0;
5707 // #pragma omp simd reduction(inscan, +: x)
5708 // for (..) {
5709 // <first part>
5710 // #pragma omp scan inclusive(x)
5711 // <second part>
5712 // }
5713 // is transformed to:
5714 // int x = 0;
5715 // for (..) {
5716 // int x_priv = 0;
5717 // <first part>
5718 // x = x_priv + x;
5719 // x_priv = x;
5720 // <second part>
5721 // }
5722 // and
5723 // int x = 0;
5724 // #pragma omp simd reduction(inscan, +: x)
5725 // for (..) {
5726 // <first part>
5727 // #pragma omp scan exclusive(x)
5728 // <second part>
5729 // }
5730 // to
5731 // int x = 0;
5732 // for (..) {
5733 // int x_priv = 0;
5734 // <second part>
5735 // int temp = x;
5736 // x = x_priv + x;
5737 // x_priv = temp;
5738 // <first part>
5739 // }
5740 llvm::BasicBlock *OMPScanReduce = createBasicBlock("omp.inscan.reduce");
5741 EmitBranch(IsInclusive
5742 ? OMPScanReduce
5743 : BreakContinueStack.back().ContinueBlock.getBlock());
5745 {
5746 // New scope for correct construction/destruction of temp variables for
5747 // exclusive scan.
5748 LexicalScope Scope(*this, S.getSourceRange());
5750 EmitBlock(OMPScanReduce);
5751 if (!IsInclusive) {
5752 // Create temp var and copy LHS value to this temp value.
5753 // TMP = LHS;
5754 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5755 const Expr *PrivateExpr = Privates[I];
5756 const Expr *TempExpr = CopyArrayTemps[I];
5758 *cast<VarDecl>(cast<DeclRefExpr>(TempExpr)->getDecl()));
5759 LValue DestLVal = EmitLValue(TempExpr);
5760 LValue SrcLVal = EmitLValue(LHSs[I]);
5761 EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(),
5762 SrcLVal.getAddress(),
5763 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5764 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()),
5765 CopyOps[I]);
5766 }
5767 }
5769 *this, ParentDir.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
5770 {/*WithNowait=*/true, /*SimpleReduction=*/true,
5771 /*IsPrivateVarReduction*/ {}, OMPD_simd});
5772 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5773 const Expr *PrivateExpr = Privates[I];
5774 LValue DestLVal;
5775 LValue SrcLVal;
5776 if (IsInclusive) {
5777 DestLVal = EmitLValue(RHSs[I]);
5778 SrcLVal = EmitLValue(LHSs[I]);
5779 } else {
5780 const Expr *TempExpr = CopyArrayTemps[I];
5781 DestLVal = EmitLValue(RHSs[I]);
5782 SrcLVal = EmitLValue(TempExpr);
5783 }
5785 PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
5786 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5787 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
5788 }
5789 }
5791 OMPScanExitBlock = IsInclusive
5792 ? BreakContinueStack.back().ContinueBlock.getBlock()
5793 : OMPScanReduce;
5795 return;
5796 }
5797 if (!IsInclusive) {
5798 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5800 }
5801 if (OMPFirstScanLoop) {
5802 // Emit buffer[i] = red; at the end of the input phase.
5803 const auto *IVExpr = cast<OMPLoopDirective>(ParentDir)
5804 .getIterationVariable()
5806 LValue IdxLVal = EmitLValue(IVExpr);
5807 llvm::Value *IdxVal = EmitLoadOfScalar(IdxLVal, IVExpr->getExprLoc());
5808 IdxVal = Builder.CreateIntCast(IdxVal, SizeTy, /*isSigned=*/false);
5809 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5810 const Expr *PrivateExpr = Privates[I];
5811 const Expr *OrigExpr = Shareds[I];
5812 const Expr *CopyArrayElem = CopyArrayElems[I];
5813 OpaqueValueMapping IdxMapping(
5814 *this,
5815 cast<OpaqueValueExpr>(
5816 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
5817 RValue::get(IdxVal));
5818 LValue DestLVal = EmitLValue(CopyArrayElem);
5819 LValue SrcLVal = EmitLValue(OrigExpr);
5821 PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
5822 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5823 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
5824 }
5825 }
5826 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5827 if (IsInclusive) {
5829 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5830 }
5832 if (!OMPFirstScanLoop) {
5833 // Emit red = buffer[i]; at the entrance to the scan phase.
5834 const auto *IVExpr = cast<OMPLoopDirective>(ParentDir)
5835 .getIterationVariable()
5837 LValue IdxLVal = EmitLValue(IVExpr);
5838 llvm::Value *IdxVal = EmitLoadOfScalar(IdxLVal, IVExpr->getExprLoc());
5839 IdxVal = Builder.CreateIntCast(IdxVal, SizeTy, /*isSigned=*/false);
5840 llvm::BasicBlock *ExclusiveExitBB = nullptr;
5841 if (!IsInclusive) {
5842 llvm::BasicBlock *ContBB = createBasicBlock("omp.exclusive.dec");
5843 ExclusiveExitBB = createBasicBlock("omp.exclusive.copy.exit");
5844 llvm::Value *Cmp = Builder.CreateIsNull(IdxVal);
5845 Builder.CreateCondBr(Cmp, ExclusiveExitBB, ContBB);
5846 EmitBlock(ContBB);
5847 // Use idx - 1 iteration for exclusive scan.
5848 IdxVal = Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(SizeTy, 1));
5849 }
5850 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5851 const Expr *PrivateExpr = Privates[I];
5852 const Expr *OrigExpr = Shareds[I];
5853 const Expr *CopyArrayElem = CopyArrayElems[I];
5854 OpaqueValueMapping IdxMapping(
5855 *this,
5856 cast<OpaqueValueExpr>(
5857 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
5858 RValue::get(IdxVal));
5859 LValue SrcLVal = EmitLValue(CopyArrayElem);
5860 LValue DestLVal = EmitLValue(OrigExpr);
5862 PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
5863 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5864 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
5865 }
5866 if (!IsInclusive) {
5867 EmitBlock(ExclusiveExitBB);
5868 }
5869 }
5873}
5874
5876 const CodeGenLoopTy &CodeGenLoop,
5877 Expr *IncExpr) {
5878 // Emit the loop iteration variable.
5879 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
5880 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
5881 EmitVarDecl(*IVDecl);
5882
5883 // Emit the iterations count variable.
5884 // If it is not a variable, Sema decided to calculate iterations count on each
5885 // iteration (e.g., it is foldable into a constant).
5886 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
5887 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
5888 // Emit calculation of the iterations count.
5889 EmitIgnoredExpr(S.getCalcLastIteration());
5890 }
5891
5893
5894 bool HasLastprivateClause = false;
5895 // Check pre-condition.
5896 {
5897 OMPLoopScope PreInitScope(*this, S);
5898 // Skip the entire loop if we don't meet the precondition.
5899 // If the condition constant folds and can be elided, avoid emitting the
5900 // whole loop.
5901 bool CondConstant;
5902 llvm::BasicBlock *ContBlock = nullptr;
5903 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
5904 if (!CondConstant)
5905 return;
5906 } else {
5907 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
5908 ContBlock = createBasicBlock("omp.precond.end");
5909 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
5910 getProfileCount(&S));
5911 EmitBlock(ThenBlock);
5913 }
5914
5915 emitAlignedClause(*this, S);
5916 // Emit 'then' code.
5917 {
5918 // Emit helper vars inits.
5919
5921 *this, cast<DeclRefExpr>(
5922 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
5923 ? S.getCombinedLowerBoundVariable()
5924 : S.getLowerBoundVariable())));
5926 *this, cast<DeclRefExpr>(
5927 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
5928 ? S.getCombinedUpperBoundVariable()
5929 : S.getUpperBoundVariable())));
5930 LValue ST =
5931 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
5932 LValue IL =
5933 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
5934
5935 OMPPrivateScope LoopScope(*this);
5936 if (EmitOMPFirstprivateClause(S, LoopScope)) {
5937 // Emit implicit barrier to synchronize threads and avoid data races
5938 // on initialization of firstprivate variables and post-update of
5939 // lastprivate variables.
5941 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
5942 /*ForceSimpleCall=*/true);
5943 }
5944 EmitOMPPrivateClause(S, LoopScope);
5945 if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
5946 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
5947 !isOpenMPTeamsDirective(S.getDirectiveKind()))
5948 EmitOMPReductionClauseInit(S, LoopScope);
5949 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
5950 EmitOMPPrivateLoopCounters(S, LoopScope);
5951 (void)LoopScope.Privatize();
5952 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
5954
5955 // Detect the distribute schedule kind and chunk.
5956 llvm::Value *Chunk = nullptr;
5958 if (const auto *C = S.getSingleClause<OMPDistScheduleClause>()) {
5959 ScheduleKind = C->getDistScheduleKind();
5960 if (const Expr *Ch = C->getChunkSize()) {
5961 Chunk = EmitScalarExpr(Ch);
5962 Chunk = EmitScalarConversion(Chunk, Ch->getType(),
5963 S.getIterationVariable()->getType(),
5964 S.getBeginLoc());
5965 }
5966 } else {
5967 // Default behaviour for dist_schedule clause.
5969 *this, S, ScheduleKind, Chunk);
5970 }
5971 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
5972 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
5973
5974 // OpenMP [2.10.8, distribute Construct, Description]
5975 // If dist_schedule is specified, kind must be static. If specified,
5976 // iterations are divided into chunks of size chunk_size, chunks are
5977 // assigned to the teams of the league in a round-robin fashion in the
5978 // order of the team number. When no chunk_size is specified, the
5979 // iteration space is divided into chunks that are approximately equal
5980 // in size, and at most one chunk is distributed to each team of the
5981 // league. The size of the chunks is unspecified in this case.
5982 bool StaticChunked =
5983 RT.isStaticChunked(ScheduleKind, /* Chunked */ Chunk != nullptr) &&
5984 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
5985 if (RT.isStaticNonchunked(ScheduleKind,
5986 /* Chunked */ Chunk != nullptr) ||
5987 StaticChunked) {
5989 IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(),
5990 LB.getAddress(), UB.getAddress(), ST.getAddress(),
5991 StaticChunked ? Chunk : nullptr);
5992 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind,
5993 StaticInit);
5996 // UB = min(UB, GlobalUB);
5998 ? S.getCombinedEnsureUpperBound()
5999 : S.getEnsureUpperBound());
6000 // IV = LB;
6002 ? S.getCombinedInit()
6003 : S.getInit());
6004
6005 const Expr *Cond =
6006 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
6007 ? S.getCombinedCond()
6008 : S.getCond();
6009
6010 if (StaticChunked)
6011 Cond = S.getCombinedDistCond();
6012
6013 // For static unchunked schedules generate:
6014 //
6015 // 1. For distribute alone, codegen
6016 // while (idx <= UB) {
6017 // BODY;
6018 // ++idx;
6019 // }
6020 //
6021 // 2. When combined with 'for' (e.g. as in 'distribute parallel for')
6022 // while (idx <= UB) {
6023 // <CodeGen rest of pragma>(LB, UB);
6024 // idx += ST;
6025 // }
6026 //
6027 // For static chunk one schedule generate:
6028 //
6029 // while (IV <= GlobalUB) {
6030 // <CodeGen rest of pragma>(LB, UB);
6031 // LB += ST;
6032 // UB += ST;
6033 // UB = min(UB, GlobalUB);
6034 // IV = LB;
6035 // }
6036 //
6038 *this, S,
6039 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
6040 if (isOpenMPSimdDirective(S.getDirectiveKind()))
6041 CGF.EmitOMPSimdInit(S);
6042 },
6043 [&S, &LoopScope, Cond, IncExpr, LoopExit, &CodeGenLoop,
6044 StaticChunked](CodeGenFunction &CGF, PrePostActionTy &) {
6045 CGF.EmitOMPInnerLoop(
6046 S, LoopScope.requiresCleanups(), Cond, IncExpr,
6047 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6048 CodeGenLoop(CGF, S, LoopExit);
6049 },
6050 [&S, StaticChunked](CodeGenFunction &CGF) {
6051 if (StaticChunked) {
6052 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6053 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6054 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6055 CGF.EmitIgnoredExpr(S.getCombinedInit());
6056 }
6057 });
6058 });
6059 EmitBlock(LoopExit.getBlock());
6060 // Tell the runtime we are done.
6061 RT.emitForStaticFinish(*this, S.getEndLoc(), OMPD_distribute);
6062 } else {
6063 // Emit the outer loop, which requests its work chunk [LB..UB] from
6064 // runtime and runs the inner loop to process it.
6065 const OMPLoopArguments LoopArguments = {
6066 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(),
6067 Chunk};
6068 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6069 CodeGenLoop);
6070 }
6071 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
6072 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
6073 return CGF.Builder.CreateIsNotNull(
6074 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
6075 });
6076 }
6077 if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
6078 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
6079 !isOpenMPTeamsDirective(S.getDirectiveKind())) {
6080 EmitOMPReductionClauseFinal(S, OMPD_simd);
6081 // Emit post-update of the reduction variables if IsLastIter != 0.
6083 *this, S, [IL, &S](CodeGenFunction &CGF) {
6084 return CGF.Builder.CreateIsNotNull(
6085 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
6086 });
6087 }
6088 // Emit final copy of the lastprivate variables if IsLastIter != 0.
6089 if (HasLastprivateClause) {
6091 S, /*NoFinals=*/false,
6092 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
6093 }
6094 }
6095
6096 // We're now done with the loop, so jump to the continuation block.
6097 if (ContBlock) {
6098 EmitBranch(ContBlock);
6099 EmitBlock(ContBlock, true);
6100 }
6101 }
6102}
6103
6104// Pass OMPLoopDirective (instead of OMPDistributeDirective) to make this
6105// function available for "loop bind(teams)", which maps to "distribute".
6107 CodeGenFunction &CGF,
6108 CodeGenModule &CGM) {
6109 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
6111 };
6112 OMPLexicalScope Scope(CGF, S, OMPD_unknown);
6113 CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, CodeGen);
6114}
6115
6117 const OMPDistributeDirective &S) {
6119}
6120
6122 const CapturedStmt *S,
6124 CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
6126 CGF.CapturedStmtInfo = &CapStmtInfo;
6127 llvm::Function *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S, Loc);
6128 Fn->setDoesNotRecurse();
6129 return Fn;
6130}
6131
6132template <typename T>
6133static void emitRestoreIP(CodeGenFunction &CGF, const T *C,
6134 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6135 llvm::OpenMPIRBuilder &OMPBuilder) {
6136
6137 unsigned NumLoops = C->getNumLoops();
6139 /*DestWidth=*/64, /*Signed=*/1);
6141 for (unsigned I = 0; I < NumLoops; I++) {
6142 const Expr *CounterVal = C->getLoopData(I);
6143 assert(CounterVal);
6144 llvm::Value *StoreValue = CGF.EmitScalarConversion(
6145 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
6146 CounterVal->getExprLoc());
6147 StoreValues.emplace_back(StoreValue);
6148 }
6149 OMPDoacrossKind<T> ODK;
6150 bool IsDependSource = ODK.isSource(C);
6151 CGF.Builder.restoreIP(
6152 OMPBuilder.createOrderedDepend(CGF.Builder, AllocaIP, NumLoops,
6153 StoreValues, ".cnt.addr", IsDependSource));
6154}
6155
6157 if (CGM.getLangOpts().OpenMPIRBuilder) {
6158 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
6159 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6160
6161 if (S.hasClausesOfKind<OMPDependClause>() ||
6162 S.hasClausesOfKind<OMPDoacrossClause>()) {
6163 // The ordered directive with depend clause.
6164 assert(!S.hasAssociatedStmt() && "No associated statement must be in "
6165 "ordered depend|doacross construct.");
6166 InsertPointTy AllocaIP(AllocaInsertPt->getParent(),
6167 AllocaInsertPt->getIterator());
6168 for (const auto *DC : S.getClausesOfKind<OMPDependClause>())
6169 emitRestoreIP(*this, DC, AllocaIP, OMPBuilder);
6170 for (const auto *DC : S.getClausesOfKind<OMPDoacrossClause>())
6171 emitRestoreIP(*this, DC, AllocaIP, OMPBuilder);
6172 } else {
6173 // The ordered directive with threads or simd clause, or without clause.
6174 // Without clause, it behaves as if the threads clause is specified.
6175 const auto *C = S.getSingleClause<OMPSIMDClause>();
6176
6177 auto FiniCB = [this](InsertPointTy IP) {
6179 return llvm::Error::success();
6180 };
6181
6182 auto BodyGenCB = [&S, C, this](InsertPointTy AllocaIP,
6183 InsertPointTy CodeGenIP) {
6184 Builder.restoreIP(CodeGenIP);
6185
6186 const CapturedStmt *CS = S.getInnermostCapturedStmt();
6187 if (C) {
6188 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6189 Builder, /*CreateBranch=*/false, ".ordered.after");
6191 GenerateOpenMPCapturedVars(*CS, CapturedVars);
6192 llvm::Function *OutlinedFn =
6193 emitOutlinedOrderedFunction(CGM, CS, S.getBeginLoc());
6194 assert(S.getBeginLoc().isValid() &&
6195 "Outlined function call location must be valid.");
6196 ApplyDebugLocation::CreateDefaultArtificial(*this, S.getBeginLoc());
6197 OMPBuilderCBHelpers::EmitCaptureStmt(*this, CodeGenIP, *FiniBB,
6198 OutlinedFn, CapturedVars);
6199 } else {
6201 *this, CS->getCapturedStmt(), AllocaIP, CodeGenIP, "ordered");
6202 }
6203 return llvm::Error::success();
6204 };
6205
6206 OMPLexicalScope Scope(*this, S, OMPD_unknown);
6207 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6208 OMPBuilder.createOrderedThreadsSimd(Builder, BodyGenCB, FiniCB, !C));
6209 Builder.restoreIP(AfterIP);
6210 }
6211 return;
6212 }
6213
6214 if (S.hasClausesOfKind<OMPDependClause>()) {
6215 assert(!S.hasAssociatedStmt() &&
6216 "No associated statement must be in ordered depend construct.");
6217 for (const auto *DC : S.getClausesOfKind<OMPDependClause>())
6219 return;
6220 }
6221 if (S.hasClausesOfKind<OMPDoacrossClause>()) {
6222 assert(!S.hasAssociatedStmt() &&
6223 "No associated statement must be in ordered doacross construct.");
6224 for (const auto *DC : S.getClausesOfKind<OMPDoacrossClause>())
6226 return;
6227 }
6228 const auto *C = S.getSingleClause<OMPSIMDClause>();
6229 auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF,
6230 PrePostActionTy &Action) {
6231 const CapturedStmt *CS = S.getInnermostCapturedStmt();
6232 if (C) {
6234 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6235 llvm::Function *OutlinedFn =
6236 emitOutlinedOrderedFunction(CGM, CS, S.getBeginLoc());
6237 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6238 OutlinedFn, CapturedVars);
6239 } else {
6240 Action.Enter(CGF);
6241 CGF.EmitStmt(CS->getCapturedStmt());
6242 }
6243 };
6244 OMPLexicalScope Scope(*this, S, OMPD_unknown);
6245 CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getBeginLoc(), !C);
6246}
6247
6248static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val,
6249 QualType SrcType, QualType DestType,
6251 assert(CGF.hasScalarEvaluationKind(DestType) &&
6252 "DestType must have scalar evaluation kind.");
6253 assert(!Val.isAggregate() && "Must be a scalar or complex.");
6254 return Val.isScalar() ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType,
6255 DestType, Loc)
6257 Val.getComplexVal(), SrcType, DestType, Loc);
6258}
6259
6262 QualType DestType, SourceLocation Loc) {
6263 assert(CGF.getEvaluationKind(DestType) == TEK_Complex &&
6264 "DestType must have complex evaluation kind.");
6266 if (Val.isScalar()) {
6267 // Convert the input element to the element type of the complex.
6268 QualType DestElementType =
6269 DestType->castAs<ComplexType>()->getElementType();
6270 llvm::Value *ScalarVal = CGF.EmitScalarConversion(
6271 Val.getScalarVal(), SrcType, DestElementType, Loc);
6272 ComplexVal = CodeGenFunction::ComplexPairTy(
6273 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6274 } else {
6275 assert(Val.isComplex() && "Must be a scalar or complex.");
6276 QualType SrcElementType = SrcType->castAs<ComplexType>()->getElementType();
6277 QualType DestElementType =
6278 DestType->castAs<ComplexType>()->getElementType();
6279 ComplexVal.first = CGF.EmitScalarConversion(
6280 Val.getComplexVal().first, SrcElementType, DestElementType, Loc);
6281 ComplexVal.second = CGF.EmitScalarConversion(
6282 Val.getComplexVal().second, SrcElementType, DestElementType, Loc);
6283 }
6284 return ComplexVal;
6285}
6286
6287static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO,
6288 LValue LVal, RValue RVal) {
6289 if (LVal.isGlobalReg())
6290 CGF.EmitStoreThroughGlobalRegLValue(RVal, LVal);
6291 else
6292 CGF.EmitAtomicStore(RVal, LVal, AO, LVal.isVolatile(), /*isInit=*/false);
6293}
6294
6296 llvm::AtomicOrdering AO, LValue LVal,
6298 if (LVal.isGlobalReg())
6299 return CGF.EmitLoadOfLValue(LVal, Loc);
6300 return CGF.EmitAtomicLoad(
6301 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6302 LVal.isVolatile());
6303}
6304
6306 QualType RValTy, SourceLocation Loc) {
6307 switch (getEvaluationKind(LVal.getType())) {
6308 case TEK_Scalar:
6310 *this, RVal, RValTy, LVal.getType(), Loc)),
6311 LVal);
6312 break;
6313 case TEK_Complex:
6315 convertToComplexValue(*this, RVal, RValTy, LVal.getType(), Loc), LVal,
6316 /*isInit=*/false);
6317 break;
6318 case TEK_Aggregate:
6319 llvm_unreachable("Must be a scalar or complex.");
6320 }
6321}
6322
6323static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO,
6324 const Expr *X, const Expr *V,
6326 // v = x;
6327 assert(V->isLValue() && "V of 'omp atomic read' is not lvalue");
6328 assert(X->isLValue() && "X of 'omp atomic read' is not lvalue");
6329 LValue XLValue = CGF.EmitLValue(X);
6330 LValue VLValue = CGF.EmitLValue(V);
6331 RValue Res = emitSimpleAtomicLoad(CGF, AO, XLValue, Loc);
6332 // OpenMP, 2.17.7, atomic Construct
6333 // If the read or capture clause is specified and the acquire, acq_rel, or
6334 // seq_cst clause is specified then the strong flush on exit from the atomic
6335 // operation is also an acquire flush.
6336 switch (AO) {
6337 case llvm::AtomicOrdering::Acquire:
6338 case llvm::AtomicOrdering::AcquireRelease:
6339 case llvm::AtomicOrdering::SequentiallyConsistent:
6340 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, {}, Loc,
6341 llvm::AtomicOrdering::Acquire);
6342 break;
6343 case llvm::AtomicOrdering::Monotonic:
6344 case llvm::AtomicOrdering::Release:
6345 break;
6346 case llvm::AtomicOrdering::NotAtomic:
6347 case llvm::AtomicOrdering::Unordered:
6348 llvm_unreachable("Unexpected ordering.");
6349 }
6350 CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc);
6352}
6353
6355 llvm::AtomicOrdering AO, const Expr *X,
6356 const Expr *E, SourceLocation Loc) {
6357 // x = expr;
6358 assert(X->isLValue() && "X of 'omp atomic write' is not lvalue");
6359 emitSimpleAtomicStore(CGF, AO, CGF.EmitLValue(X), CGF.EmitAnyExpr(E));
6361 // OpenMP, 2.17.7, atomic Construct
6362 // If the write, update, or capture clause is specified and the release,
6363 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
6364 // the atomic operation is also a release flush.
6365 switch (AO) {
6366 case llvm::AtomicOrdering::Release:
6367 case llvm::AtomicOrdering::AcquireRelease:
6368 case llvm::AtomicOrdering::SequentiallyConsistent:
6369 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, {}, Loc,
6370 llvm::AtomicOrdering::Release);
6371 break;
6372 case llvm::AtomicOrdering::Acquire:
6373 case llvm::AtomicOrdering::Monotonic:
6374 break;
6375 case llvm::AtomicOrdering::NotAtomic:
6376 case llvm::AtomicOrdering::Unordered:
6377 llvm_unreachable("Unexpected ordering.");
6378 }
6379}
6380
6381static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
6382 RValue Update,
6384 llvm::AtomicOrdering AO,
6385 bool IsXLHSInRHSPart) {
6386 ASTContext &Context = CGF.getContext();
6387 // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x'
6388 // expression is simple and atomic is allowed for the given type for the
6389 // target platform.
6390 if (BO == BO_Comma || !Update.isScalar() || !X.isSimple() ||
6391 (!isa<llvm::ConstantInt>(Update.getScalarVal()) &&
6392 (Update.getScalarVal()->getType() != X.getAddress().getElementType())) ||
6394 Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment())))
6395 return std::make_pair(false, RValue::get(nullptr));
6396
6397 auto &&CheckAtomicSupport = [&CGF](llvm::Type *T, BinaryOperatorKind BO) {
6398 if (T->isIntegerTy())
6399 return true;
6400
6401 if (T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6402 return llvm::isPowerOf2_64(CGF.CGM.getDataLayout().getTypeStoreSize(T));
6403
6404 return false;
6405 };
6406
6407 if (!CheckAtomicSupport(Update.getScalarVal()->getType(), BO) ||
6408 !CheckAtomicSupport(X.getAddress().getElementType(), BO))
6409 return std::make_pair(false, RValue::get(nullptr));
6410
6411 bool IsInteger = X.getAddress().getElementType()->isIntegerTy();
6412 llvm::AtomicRMWInst::BinOp RMWOp;
6413 switch (BO) {
6414 case BO_Add:
6415 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6416 break;
6417 case BO_Sub:
6418 if (!IsXLHSInRHSPart)
6419 return std::make_pair(false, RValue::get(nullptr));
6420 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6421 break;
6422 case BO_And:
6423 RMWOp = llvm::AtomicRMWInst::And;
6424 break;
6425 case BO_Or:
6426 RMWOp = llvm::AtomicRMWInst::Or;
6427 break;
6428 case BO_Xor:
6429 RMWOp = llvm::AtomicRMWInst::Xor;
6430 break;
6431 case BO_LT:
6432 if (IsInteger)
6433 RMWOp = X.getType()->hasSignedIntegerRepresentation()
6434 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
6435 : llvm::AtomicRMWInst::Max)
6436 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
6437 : llvm::AtomicRMWInst::UMax);
6438 else
6439 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMin
6440 : llvm::AtomicRMWInst::FMax;
6441 break;
6442 case BO_GT:
6443 if (IsInteger)
6444 RMWOp = X.getType()->hasSignedIntegerRepresentation()
6445 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
6446 : llvm::AtomicRMWInst::Min)
6447 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
6448 : llvm::AtomicRMWInst::UMin);
6449 else
6450 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMax
6451 : llvm::AtomicRMWInst::FMin;
6452 break;
6453 case BO_Assign:
6454 RMWOp = llvm::AtomicRMWInst::Xchg;
6455 break;
6456 case BO_Mul:
6457 case BO_Div:
6458 case BO_Rem:
6459 case BO_Shl:
6460 case BO_Shr:
6461 case BO_LAnd:
6462 case BO_LOr:
6463 return std::make_pair(false, RValue::get(nullptr));
6464 case BO_PtrMemD:
6465 case BO_PtrMemI:
6466 case BO_LE:
6467 case BO_GE:
6468 case BO_EQ:
6469 case BO_NE:
6470 case BO_Cmp:
6471 case BO_AddAssign:
6472 case BO_SubAssign:
6473 case BO_AndAssign:
6474 case BO_OrAssign:
6475 case BO_XorAssign:
6476 case BO_MulAssign:
6477 case BO_DivAssign:
6478 case BO_RemAssign:
6479 case BO_ShlAssign:
6480 case BO_ShrAssign:
6481 case BO_Comma:
6482 llvm_unreachable("Unsupported atomic update operation");
6483 }
6484 llvm::Value *UpdateVal = Update.getScalarVal();
6485 if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6486 if (IsInteger)
6487 UpdateVal = CGF.Builder.CreateIntCast(
6488 IC, X.getAddress().getElementType(),
6489 X.getType()->hasSignedIntegerRepresentation());
6490 else
6491 UpdateVal = CGF.Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6492 X.getAddress().getElementType());
6493 }
6494 llvm::AtomicRMWInst *Res =
6495 CGF.emitAtomicRMWInst(RMWOp, X.getAddress(), UpdateVal, AO);
6496 return std::make_pair(true, RValue::get(Res));
6497}
6498
6500 LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
6501 llvm::AtomicOrdering AO, SourceLocation Loc,
6502 const llvm::function_ref<RValue(RValue)> CommonGen) {
6503 // Update expressions are allowed to have the following forms:
6504 // x binop= expr; -> xrval + expr;
6505 // x++, ++x -> xrval + 1;
6506 // x--, --x -> xrval - 1;
6507 // x = x binop expr; -> xrval binop expr
6508 // x = expr Op x; - > expr binop xrval;
6509 auto Res = emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart);
6510 if (!Res.first) {
6511 if (X.isGlobalReg()) {
6512 // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop
6513 // 'xrval'.
6515 } else {
6516 // Perform compare-and-swap procedure.
6517 EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified());
6518 }
6519 }
6520 return Res;
6521}
6522
6524 llvm::AtomicOrdering AO, const Expr *X,
6525 const Expr *E, const Expr *UE,
6526 bool IsXLHSInRHSPart, SourceLocation Loc) {
6527 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
6528 "Update expr in 'atomic update' must be a binary operator.");
6529 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
6530 // Update expressions are allowed to have the following forms:
6531 // x binop= expr; -> xrval + expr;
6532 // x++, ++x -> xrval + 1;
6533 // x--, --x -> xrval - 1;
6534 // x = x binop expr; -> xrval binop expr
6535 // x = expr Op x; - > expr binop xrval;
6536 assert(X->isLValue() && "X of 'omp atomic update' is not lvalue");
6537 LValue XLValue = CGF.EmitLValue(X);
6538 RValue ExprRValue = CGF.EmitAnyExpr(E);
6539 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
6540 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
6541 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
6542 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
6543 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) {
6544 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6545 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
6546 return CGF.EmitAnyExpr(UE);
6547 };
6549 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
6551 // OpenMP, 2.17.7, atomic Construct
6552 // If the write, update, or capture clause is specified and the release,
6553 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
6554 // the atomic operation is also a release flush.
6555 switch (AO) {
6556 case llvm::AtomicOrdering::Release:
6557 case llvm::AtomicOrdering::AcquireRelease:
6558 case llvm::AtomicOrdering::SequentiallyConsistent:
6559 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, {}, Loc,
6560 llvm::AtomicOrdering::Release);
6561 break;
6562 case llvm::AtomicOrdering::Acquire:
6563 case llvm::AtomicOrdering::Monotonic:
6564 break;
6565 case llvm::AtomicOrdering::NotAtomic:
6566 case llvm::AtomicOrdering::Unordered:
6567 llvm_unreachable("Unexpected ordering.");
6568 }
6569}
6570
6572 QualType SourceType, QualType ResType,
6574 switch (CGF.getEvaluationKind(ResType)) {
6575 case TEK_Scalar:
6576 return RValue::get(
6577 convertToScalarValue(CGF, Value, SourceType, ResType, Loc));
6578 case TEK_Complex: {
6579 auto Res = convertToComplexValue(CGF, Value, SourceType, ResType, Loc);
6580 return RValue::getComplex(Res.first, Res.second);
6581 }
6582 case TEK_Aggregate:
6583 break;
6584 }
6585 llvm_unreachable("Must be a scalar or complex.");
6586}
6587
6589 llvm::AtomicOrdering AO,
6590 bool IsPostfixUpdate, const Expr *V,
6591 const Expr *X, const Expr *E,
6592 const Expr *UE, bool IsXLHSInRHSPart,
6594 assert(X->isLValue() && "X of 'omp atomic capture' is not lvalue");
6595 assert(V->isLValue() && "V of 'omp atomic capture' is not lvalue");
6596 RValue NewVVal;
6597 LValue VLValue = CGF.EmitLValue(V);
6598 LValue XLValue = CGF.EmitLValue(X);
6599 RValue ExprRValue = CGF.EmitAnyExpr(E);
6600 QualType NewVValType;
6601 if (UE) {
6602 // 'x' is updated with some additional value.
6603 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
6604 "Update expr in 'atomic capture' must be a binary operator.");
6605 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
6606 // Update expressions are allowed to have the following forms:
6607 // x binop= expr; -> xrval + expr;
6608 // x++, ++x -> xrval + 1;
6609 // x--, --x -> xrval - 1;
6610 // x = x binop expr; -> xrval binop expr
6611 // x = expr Op x; - > expr binop xrval;
6612 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
6613 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
6614 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
6615 NewVValType = XRValExpr->getType();
6616 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
6617 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6618 IsPostfixUpdate](RValue XRValue) {
6619 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6620 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
6621 RValue Res = CGF.EmitAnyExpr(UE);
6622 NewVVal = IsPostfixUpdate ? XRValue : Res;
6623 return Res;
6624 };
6625 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
6626 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
6628 if (Res.first) {
6629 // 'atomicrmw' instruction was generated.
6630 if (IsPostfixUpdate) {
6631 // Use old value from 'atomicrmw'.
6632 NewVVal = Res.second;
6633 } else {
6634 // 'atomicrmw' does not provide new value, so evaluate it using old
6635 // value of 'x'.
6636 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6637 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second);
6638 NewVVal = CGF.EmitAnyExpr(UE);
6639 }
6640 }
6641 } else {
6642 // 'x' is simply rewritten with some 'expr'.
6643 NewVValType = X->getType().getNonReferenceType();
6644 ExprRValue = convertToType(CGF, ExprRValue, E->getType(),
6645 X->getType().getNonReferenceType(), Loc);
6646 auto &&Gen = [&NewVVal, ExprRValue](RValue XRValue) {
6647 NewVVal = XRValue;
6648 return ExprRValue;
6649 };
6650 // Try to perform atomicrmw xchg, otherwise simple exchange.
6651 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
6652 XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO,
6653 Loc, Gen);
6655 if (Res.first) {
6656 // 'atomicrmw' instruction was generated.
6657 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
6658 }
6659 }
6660 // Emit post-update store to 'v' of old/new 'x' value.
6661 CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc);
6663 // OpenMP 5.1 removes the required flush for capture clause.
6664 if (CGF.CGM.getLangOpts().OpenMP < 51) {
6665 // OpenMP, 2.17.7, atomic Construct
6666 // If the write, update, or capture clause is specified and the release,
6667 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
6668 // the atomic operation is also a release flush.
6669 // If the read or capture clause is specified and the acquire, acq_rel, or
6670 // seq_cst clause is specified then the strong flush on exit from the atomic
6671 // operation is also an acquire flush.
6672 switch (AO) {
6673 case llvm::AtomicOrdering::Release:
6674 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, {}, Loc,
6675 llvm::AtomicOrdering::Release);
6676 break;
6677 case llvm::AtomicOrdering::Acquire:
6678 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, {}, Loc,
6679 llvm::AtomicOrdering::Acquire);
6680 break;
6681 case llvm::AtomicOrdering::AcquireRelease:
6682 case llvm::AtomicOrdering::SequentiallyConsistent:
6684 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
6685 break;
6686 case llvm::AtomicOrdering::Monotonic:
6687 break;
6688 case llvm::AtomicOrdering::NotAtomic:
6689 case llvm::AtomicOrdering::Unordered:
6690 llvm_unreachable("Unexpected ordering.");
6691 }
6692 }
6693}
6694
6696 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6697 const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *D,
6698 const Expr *CE, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly,
6700 llvm::OpenMPIRBuilder &OMPBuilder =
6702
6703 OMPAtomicCompareOp Op;
6704 assert(isa<BinaryOperator>(CE) && "CE is not a BinaryOperator");
6705 switch (cast<BinaryOperator>(CE)->getOpcode()) {
6706 case BO_EQ:
6707 Op = OMPAtomicCompareOp::EQ;
6708 break;
6709 case BO_LT:
6710 Op = OMPAtomicCompareOp::MIN;
6711 break;
6712 case BO_GT:
6713 Op = OMPAtomicCompareOp::MAX;
6714 break;
6715 default:
6716 llvm_unreachable("unsupported atomic compare binary operator");
6717 }
6718
6719 LValue XLVal = CGF.EmitLValue(X);
6720 Address XAddr = XLVal.getAddress();
6721
6722 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](const Expr *X, const Expr *E) {
6723 if (X->getType() == E->getType())
6724 return CGF.EmitScalarExpr(E);
6725 const Expr *NewE = E->IgnoreImplicitAsWritten();
6726 llvm::Value *V = CGF.EmitScalarExpr(NewE);
6727 if (NewE->getType() == X->getType())
6728 return V;
6729 return CGF.EmitScalarConversion(V, NewE->getType(), X->getType(), Loc);
6730 };
6731
6732 llvm::Value *EVal = EmitRValueWithCastIfNeeded(X, E);
6733 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(X, D) : nullptr;
6734 if (auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
6735 EVal = CGF.Builder.CreateIntCast(
6736 CI, XLVal.getAddress().getElementType(),
6738 if (DVal)
6739 if (auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
6740 DVal = CGF.Builder.CreateIntCast(
6741 CI, XLVal.getAddress().getElementType(),
6742 D->getType()->hasSignedIntegerRepresentation());
6743
6744 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
6745 XAddr.emitRawPointer(CGF), XAddr.getElementType(),
6746 X->getType()->hasSignedIntegerRepresentation(),
6747 X->getType().isVolatileQualified()};
6748 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
6749 if (V) {
6750 LValue LV = CGF.EmitLValue(V);
6751 Address Addr = LV.getAddress();
6752 VOpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(),
6753 V->getType()->hasSignedIntegerRepresentation(),
6754 V->getType().isVolatileQualified()};
6755 }
6756 if (R) {
6757 LValue LV = CGF.EmitLValue(R);
6758 Address Addr = LV.getAddress();
6759 ROpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(),
6762 }
6763
6764 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
6765 // fail clause was not mentioned on the
6766 // "#pragma omp atomic compare" construct.
6767 CGF.Builder.restoreIP(OMPBuilder.createAtomicCompare(
6768 CGF.Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6769 IsPostfixUpdate, IsFailOnly));
6770 } else
6771 CGF.Builder.restoreIP(OMPBuilder.createAtomicCompare(
6772 CGF.Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6773 IsPostfixUpdate, IsFailOnly, FailAO));
6774}
6775
6777 llvm::AtomicOrdering AO,
6778 llvm::AtomicOrdering FailAO, bool IsPostfixUpdate,
6779 const Expr *X, const Expr *V, const Expr *R,
6780 const Expr *E, const Expr *UE, const Expr *D,
6781 const Expr *CE, bool IsXLHSInRHSPart,
6782 bool IsFailOnly, SourceLocation Loc) {
6783 switch (Kind) {
6784 case OMPC_read:
6785 emitOMPAtomicReadExpr(CGF, AO, X, V, Loc);
6786 break;
6787 case OMPC_write:
6788 emitOMPAtomicWriteExpr(CGF, AO, X, E, Loc);
6789 break;
6790 case OMPC_unknown:
6791 case OMPC_update:
6792 emitOMPAtomicUpdateExpr(CGF, AO, X, E, UE, IsXLHSInRHSPart, Loc);
6793 break;
6794 case OMPC_capture:
6795 emitOMPAtomicCaptureExpr(CGF, AO, IsPostfixUpdate, V, X, E, UE,
6796 IsXLHSInRHSPart, Loc);
6797 break;
6798 case OMPC_compare: {
6799 emitOMPAtomicCompareExpr(CGF, AO, FailAO, X, V, R, E, D, CE,
6800 IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly, Loc);
6801 break;
6802 }
6803 default:
6804 llvm_unreachable("Clause is not allowed in 'omp atomic'.");
6805 }
6806}
6807
6809 llvm::AtomicOrdering AO = CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6810 // Fail Memory Clause Ordering.
6811 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
6812 bool MemOrderingSpecified = false;
6813 if (S.getSingleClause<OMPSeqCstClause>()) {
6814 AO = llvm::AtomicOrdering::SequentiallyConsistent;
6815 MemOrderingSpecified = true;
6816 } else if (S.getSingleClause<OMPAcqRelClause>()) {
6817 AO = llvm::AtomicOrdering::AcquireRelease;
6818 MemOrderingSpecified = true;
6819 } else if (S.getSingleClause<OMPAcquireClause>()) {
6820 AO = llvm::AtomicOrdering::Acquire;
6821 MemOrderingSpecified = true;
6822 } else if (S.getSingleClause<OMPReleaseClause>()) {
6823 AO = llvm::AtomicOrdering::Release;
6824 MemOrderingSpecified = true;
6825 } else if (S.getSingleClause<OMPRelaxedClause>()) {
6826 AO = llvm::AtomicOrdering::Monotonic;
6827 MemOrderingSpecified = true;
6828 }
6829 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
6830 OpenMPClauseKind Kind = OMPC_unknown;
6831 for (const OMPClause *C : S.clauses()) {
6832 // Find first clause (skip seq_cst|acq_rel|aqcuire|release|relaxed clause,
6833 // if it is first).
6834 OpenMPClauseKind K = C->getClauseKind();
6835 // TBD
6836 if (K == OMPC_weak)
6837 return;
6838 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
6839 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
6840 continue;
6841 Kind = K;
6842 KindsEncountered.insert(K);
6843 }
6844 // We just need to correct Kind here. No need to set a bool saying it is
6845 // actually compare capture because we can tell from whether V and R are
6846 // nullptr.
6847 if (KindsEncountered.contains(OMPC_compare) &&
6848 KindsEncountered.contains(OMPC_capture))
6849 Kind = OMPC_compare;
6850 if (!MemOrderingSpecified) {
6851 llvm::AtomicOrdering DefaultOrder =
6853 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
6854 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
6855 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
6856 Kind == OMPC_capture)) {
6857 AO = DefaultOrder;
6858 } else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
6859 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
6860 AO = llvm::AtomicOrdering::Release;
6861 } else if (Kind == OMPC_read) {
6862 assert(Kind == OMPC_read && "Unexpected atomic kind.");
6863 AO = llvm::AtomicOrdering::Acquire;
6864 }
6865 }
6866 }
6867
6868 if (KindsEncountered.contains(OMPC_compare) &&
6869 KindsEncountered.contains(OMPC_fail)) {
6870 Kind = OMPC_compare;
6871 const auto *FailClause = S.getSingleClause<OMPFailClause>();
6872 if (FailClause) {
6873 OpenMPClauseKind FailParameter = FailClause->getFailParameter();
6874 if (FailParameter == llvm::omp::OMPC_relaxed)
6875 FailAO = llvm::AtomicOrdering::Monotonic;
6876 else if (FailParameter == llvm::omp::OMPC_acquire)
6877 FailAO = llvm::AtomicOrdering::Acquire;
6878 else if (FailParameter == llvm::omp::OMPC_seq_cst)
6879 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
6880 }
6881 }
6882
6883 LexicalScope Scope(*this, S.getSourceRange());
6884 EmitStopPoint(S.getAssociatedStmt());
6885 emitOMPAtomicExpr(*this, Kind, AO, FailAO, S.isPostfixUpdate(), S.getX(),
6886 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
6887 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
6888 S.isFailOnly(), S.getBeginLoc());
6889}
6890
6892 const OMPExecutableDirective &S,
6893 const RegionCodeGenTy &CodeGen) {
6894 assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind()));
6895 CodeGenModule &CGM = CGF.CGM;
6896
6897 // On device emit this construct as inlined code.
6898 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
6899 OMPLexicalScope Scope(CGF, S, OMPD_target);
6901 CGF, OMPD_target, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
6902 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6903 });
6904 return;
6905 }
6906
6908 llvm::Function *Fn = nullptr;
6909 llvm::Constant *FnID = nullptr;
6910
6911 const Expr *IfCond = nullptr;
6912 // Check for the at most one if clause associated with the target region.
6913 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
6914 if (C->getNameModifier() == OMPD_unknown ||
6915 C->getNameModifier() == OMPD_target) {
6916 IfCond = C->getCondition();
6917 break;
6918 }
6919 }
6920
6921 // Check if we have any device clause associated with the directive.
6922 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device(
6923 nullptr, OMPC_DEVICE_unknown);
6924 if (auto *C = S.getSingleClause<OMPDeviceClause>())
6925 Device.setPointerAndInt(C->getDevice(), C->getModifier());
6926
6927 // Check if we have an if clause whose conditional always evaluates to false
6928 // or if we do not have any targets specified. If so the target region is not
6929 // an offload entry point.
6930 bool IsOffloadEntry = true;
6931 if (IfCond) {
6932 bool Val;
6933 if (CGF.ConstantFoldsToSimpleInteger(IfCond, Val) && !Val)
6934 IsOffloadEntry = false;
6935 }
6936 if (CGM.getLangOpts().OMPTargetTriples.empty())
6937 IsOffloadEntry = false;
6938
6939 if (CGM.getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
6940 unsigned DiagID = CGM.getDiags().getCustomDiagID(
6942 "No offloading entry generated while offloading is mandatory.");
6943 CGM.getDiags().Report(DiagID);
6944 }
6945
6946 assert(CGF.CurFuncDecl && "No parent declaration for target region!");
6947 StringRef ParentName;
6948 // In case we have Ctors/Dtors we use the complete type variant to produce
6949 // the mangling of the device outlined kernel.
6950 if (const auto *D = dyn_cast<CXXConstructorDecl>(CGF.CurFuncDecl))
6952 else if (const auto *D = dyn_cast<CXXDestructorDecl>(CGF.CurFuncDecl))
6954 else
6955 ParentName =
6956 CGM.getMangledName(GlobalDecl(cast<FunctionDecl>(CGF.CurFuncDecl)));
6957
6958 // Emit target region as a standalone region.
6959 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID,
6960 IsOffloadEntry, CodeGen);
6961 OMPLexicalScope Scope(CGF, S, OMPD_task);
6962 auto &&SizeEmitter =
6963 [IsOffloadEntry](CodeGenFunction &CGF,
6964 const OMPLoopDirective &D) -> llvm::Value * {
6965 if (IsOffloadEntry) {
6966 OMPLoopScope(CGF, D);
6967 // Emit calculation of the iterations count.
6968 llvm::Value *NumIterations = CGF.EmitScalarExpr(D.getNumIterations());
6969 NumIterations = CGF.Builder.CreateIntCast(NumIterations, CGF.Int64Ty,
6970 /*isSigned=*/false);
6971 return NumIterations;
6972 }
6973 return nullptr;
6974 };
6975 CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device,
6976 SizeEmitter);
6977}
6978
6980 PrePostActionTy &Action) {
6981 Action.Enter(CGF);
6982 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
6983 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
6984 CGF.EmitOMPPrivateClause(S, PrivateScope);
6985 (void)PrivateScope.Privatize();
6986 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
6988
6989 CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
6990 CGF.EnsureInsertPoint();
6991}
6992
6994 StringRef ParentName,
6995 const OMPTargetDirective &S) {
6996 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
6997 emitTargetRegion(CGF, S, Action);
6998 };
6999 llvm::Function *Fn;
7000 llvm::Constant *Addr;
7001 // Emit target region as a standalone region.
7003 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7004 assert(Fn && Addr && "Target device function emission failed.");
7005}
7006
7008 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7009 emitTargetRegion(CGF, S, Action);
7010 };
7011 emitCommonOMPTargetDirective(*this, S, CodeGen);
7012}
7013
7015 const OMPExecutableDirective &S,
7016 OpenMPDirectiveKind InnermostKind,
7017 const RegionCodeGenTy &CodeGen) {
7018 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7019 llvm::Function *OutlinedFn =
7021 CGF, S, *CS->getCapturedDecl()->param_begin(), InnermostKind,
7022 CodeGen);
7023
7024 const auto *NT = S.getSingleClause<OMPNumTeamsClause>();
7025 const auto *TL = S.getSingleClause<OMPThreadLimitClause>();
7026 if (NT || TL) {
7027 const Expr *NumTeams = NT ? NT->getNumTeams().front() : nullptr;
7028 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() : nullptr;
7029
7030 CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit,
7031 S.getBeginLoc());
7032 }
7033
7034 OMPTeamsScope Scope(CGF, S);
7036 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
7037 CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getBeginLoc(), OutlinedFn,
7038 CapturedVars);
7039}
7040
7042 // Emit teams region as a standalone region.
7043 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7044 Action.Enter(CGF);
7045 OMPPrivateScope PrivateScope(CGF);
7046 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
7047 CGF.EmitOMPPrivateClause(S, PrivateScope);
7048 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7049 (void)PrivateScope.Privatize();
7050 CGF.EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7051 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7052 };
7053 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
7055 [](CodeGenFunction &) { return nullptr; });
7056}
7057
7059 const OMPTargetTeamsDirective &S) {
7060 auto *CS = S.getCapturedStmt(OMPD_teams);
7061 Action.Enter(CGF);
7062 // Emit teams region as a standalone region.
7063 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
7064 Action.Enter(CGF);
7065 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7066 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
7067 CGF.EmitOMPPrivateClause(S, PrivateScope);
7068 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7069 (void)PrivateScope.Privatize();
7070 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
7072 CGF.EmitStmt(CS->getCapturedStmt());
7073 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7074 };
7075 emitCommonOMPTeamsDirective(CGF, S, OMPD_teams, CodeGen);
7077 [](CodeGenFunction &) { return nullptr; });
7078}
7079
7081 CodeGenModule &CGM, StringRef ParentName,
7082 const OMPTargetTeamsDirective &S) {
7083 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7084 emitTargetTeamsRegion(CGF, Action, S);
7085 };
7086 llvm::Function *Fn;
7087 llvm::Constant *Addr;
7088 // Emit target region as a standalone region.
7090 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7091 assert(Fn && Addr && "Target device function emission failed.");
7092}
7093
7095 const OMPTargetTeamsDirective &S) {
7096 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7097 emitTargetTeamsRegion(CGF, Action, S);
7098 };
7099 emitCommonOMPTargetDirective(*this, S, CodeGen);
7100}
7101
7102static void
7105 Action.Enter(CGF);
7106 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7108 };
7109
7110 // Emit teams region as a standalone region.
7111 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7112 PrePostActionTy &Action) {
7113 Action.Enter(CGF);
7114 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7115 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7116 (void)PrivateScope.Privatize();
7117 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7118 CodeGenDistribute);
7119 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7120 };
7121 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute, CodeGen);
7123 [](CodeGenFunction &) { return nullptr; });
7124}
7125
7127 CodeGenModule &CGM, StringRef ParentName,
7129 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7130 emitTargetTeamsDistributeRegion(CGF, Action, S);
7131 };
7132 llvm::Function *Fn;
7133 llvm::Constant *Addr;
7134 // Emit target region as a standalone region.
7136 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7137 assert(Fn && Addr && "Target device function emission failed.");
7138}
7139
7142 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7143 emitTargetTeamsDistributeRegion(CGF, Action, S);
7144 };
7145 emitCommonOMPTargetDirective(*this, S, CodeGen);
7146}
7147
7149 CodeGenFunction &CGF, PrePostActionTy &Action,
7151 Action.Enter(CGF);
7152 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7154 };
7155
7156 // Emit teams region as a standalone region.
7157 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7158 PrePostActionTy &Action) {
7159 Action.Enter(CGF);
7160 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7161 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7162 (void)PrivateScope.Privatize();
7163 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7164 CodeGenDistribute);
7165 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7166 };
7167 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_simd, CodeGen);
7169 [](CodeGenFunction &) { return nullptr; });
7170}
7171
7173 CodeGenModule &CGM, StringRef ParentName,
7175 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7177 };
7178 llvm::Function *Fn;
7179 llvm::Constant *Addr;
7180 // Emit target region as a standalone region.
7182 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7183 assert(Fn && Addr && "Target device function emission failed.");
7184}
7185
7188 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7190 };
7191 emitCommonOMPTargetDirective(*this, S, CodeGen);
7192}
7193
7195 const OMPTeamsDistributeDirective &S) {
7196
7197 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7199 };
7200
7201 // Emit teams region as a standalone region.
7202 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7203 PrePostActionTy &Action) {
7204 Action.Enter(CGF);
7205 OMPPrivateScope PrivateScope(CGF);
7206 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7207 (void)PrivateScope.Privatize();
7208 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7209 CodeGenDistribute);
7210 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7211 };
7212 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
7214 [](CodeGenFunction &) { return nullptr; });
7215}
7216
7219 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7221 };
7222
7223 // Emit teams region as a standalone region.
7224 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7225 PrePostActionTy &Action) {
7226 Action.Enter(CGF);
7227 OMPPrivateScope PrivateScope(CGF);
7228 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7229 (void)PrivateScope.Privatize();
7230 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
7231 CodeGenDistribute);
7232 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7233 };
7234 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_simd, CodeGen);
7236 [](CodeGenFunction &) { return nullptr; });
7237}
7238
7241 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7243 S.getDistInc());
7244 };
7245
7246 // Emit teams region as a standalone region.
7247 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7248 PrePostActionTy &Action) {
7249 Action.Enter(CGF);
7250 OMPPrivateScope PrivateScope(CGF);
7251 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7252 (void)PrivateScope.Privatize();
7253 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7254 CodeGenDistribute);
7255 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7256 };
7257 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for, CodeGen);
7259 [](CodeGenFunction &) { return nullptr; });
7260}
7261
7264 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7266 S.getDistInc());
7267 };
7268
7269 // Emit teams region as a standalone region.
7270 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7271 PrePostActionTy &Action) {
7272 Action.Enter(CGF);
7273 OMPPrivateScope PrivateScope(CGF);
7274 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7275 (void)PrivateScope.Privatize();
7277 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
7278 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7279 };
7280 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for_simd,
7281 CodeGen);
7283 [](CodeGenFunction &) { return nullptr; });
7284}
7285
7287 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
7288 llvm::Value *Device = nullptr;
7289 llvm::Value *NumDependences = nullptr;
7290 llvm::Value *DependenceList = nullptr;
7291
7292 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
7293 Device = EmitScalarExpr(C->getDevice());
7294
7295 // Build list and emit dependences
7298 if (!Data.Dependences.empty()) {
7299 Address DependenciesArray = Address::invalid();
7300 std::tie(NumDependences, DependenciesArray) =
7301 CGM.getOpenMPRuntime().emitDependClause(*this, Data.Dependences,
7302 S.getBeginLoc());
7303 DependenceList = DependenciesArray.emitRawPointer(*this);
7304 }
7305 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7306
7307 assert(!(Data.HasNowaitClause && !(S.getSingleClause<OMPInitClause>() ||
7308 S.getSingleClause<OMPDestroyClause>() ||
7309 S.getSingleClause<OMPUseClause>())) &&
7310 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7311
7312 auto ItOMPInitClause = S.getClausesOfKind<OMPInitClause>();
7313 if (!ItOMPInitClause.empty()) {
7314 // Look at the multiple init clauses
7315 for (const OMPInitClause *C : ItOMPInitClause) {
7316 llvm::Value *InteropvarPtr =
7317 EmitLValue(C->getInteropVar()).getPointer(*this);
7318 llvm::omp::OMPInteropType InteropType =
7319 llvm::omp::OMPInteropType::Unknown;
7320 if (C->getIsTarget()) {
7321 InteropType = llvm::omp::OMPInteropType::Target;
7322 } else {
7323 assert(C->getIsTargetSync() &&
7324 "Expected interop-type target/targetsync");
7325 InteropType = llvm::omp::OMPInteropType::TargetSync;
7326 }
7327 OMPBuilder.createOMPInteropInit(Builder, InteropvarPtr, InteropType,
7328 Device, NumDependences, DependenceList,
7329 Data.HasNowaitClause);
7330 }
7331 }
7332 auto ItOMPDestroyClause = S.getClausesOfKind<OMPDestroyClause>();
7333 if (!ItOMPDestroyClause.empty()) {
7334 // Look at the multiple destroy clauses
7335 for (const OMPDestroyClause *C : ItOMPDestroyClause) {
7336 llvm::Value *InteropvarPtr =
7337 EmitLValue(C->getInteropVar()).getPointer(*this);
7338 OMPBuilder.createOMPInteropDestroy(Builder, InteropvarPtr, Device,
7339 NumDependences, DependenceList,
7340 Data.HasNowaitClause);
7341 }
7342 }
7343 auto ItOMPUseClause = S.getClausesOfKind<OMPUseClause>();
7344 if (!ItOMPUseClause.empty()) {
7345 // Look at the multiple use clauses
7346 for (const OMPUseClause *C : ItOMPUseClause) {
7347 llvm::Value *InteropvarPtr =
7348 EmitLValue(C->getInteropVar()).getPointer(*this);
7349 OMPBuilder.createOMPInteropUse(Builder, InteropvarPtr, Device,
7350 NumDependences, DependenceList,
7351 Data.HasNowaitClause);
7352 }
7353 }
7354}
7355
7358 PrePostActionTy &Action) {
7359 Action.Enter(CGF);
7360 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7362 S.getDistInc());
7363 };
7364
7365 // Emit teams region as a standalone region.
7366 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7367 PrePostActionTy &Action) {
7368 Action.Enter(CGF);
7369 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7370 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7371 (void)PrivateScope.Privatize();
7373 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
7374 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7375 };
7376
7377 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for,
7378 CodeGenTeams);
7380 [](CodeGenFunction &) { return nullptr; });
7381}
7382
7384 CodeGenModule &CGM, StringRef ParentName,
7386 // Emit SPMD target teams distribute parallel for region as a standalone
7387 // region.
7388 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7390 };
7391 llvm::Function *Fn;
7392 llvm::Constant *Addr;
7393 // Emit target region as a standalone region.
7395 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7396 assert(Fn && Addr && "Target device function emission failed.");
7397}
7398
7401 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7403 };
7404 emitCommonOMPTargetDirective(*this, S, CodeGen);
7405}
7406
7408 CodeGenFunction &CGF,
7410 PrePostActionTy &Action) {
7411 Action.Enter(CGF);
7412 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7414 S.getDistInc());
7415 };
7416
7417 // Emit teams region as a standalone region.
7418 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7419 PrePostActionTy &Action) {
7420 Action.Enter(CGF);
7421 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7422 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7423 (void)PrivateScope.Privatize();
7425 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
7426 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7427 };
7428
7429 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for_simd,
7430 CodeGenTeams);
7432 [](CodeGenFunction &) { return nullptr; });
7433}
7434
7436 CodeGenModule &CGM, StringRef ParentName,
7438 // Emit SPMD target teams distribute parallel for simd region as a standalone
7439 // region.
7440 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7442 };
7443 llvm::Function *Fn;
7444 llvm::Constant *Addr;
7445 // Emit target region as a standalone region.
7447 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7448 assert(Fn && Addr && "Target device function emission failed.");
7449}
7450
7453 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7455 };
7456 emitCommonOMPTargetDirective(*this, S, CodeGen);
7457}
7458
7461 CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getBeginLoc(),
7462 S.getCancelRegion());
7463}
7464
7466 const Expr *IfCond = nullptr;
7467 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
7468 if (C->getNameModifier() == OMPD_unknown ||
7469 C->getNameModifier() == OMPD_cancel) {
7470 IfCond = C->getCondition();
7471 break;
7472 }
7473 }
7474 if (CGM.getLangOpts().OpenMPIRBuilder) {
7475 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
7476 // TODO: This check is necessary as we only generate `omp parallel` through
7477 // the OpenMPIRBuilder for now.
7478 if (S.getCancelRegion() == OMPD_parallel ||
7479 S.getCancelRegion() == OMPD_sections ||
7480 S.getCancelRegion() == OMPD_section) {
7481 llvm::Value *IfCondition = nullptr;
7482 if (IfCond)
7483 IfCondition = EmitScalarExpr(IfCond,
7484 /*IgnoreResultAssign=*/true);
7485 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7486 OMPBuilder.createCancel(Builder, IfCondition, S.getCancelRegion()));
7487 return Builder.restoreIP(AfterIP);
7488 }
7489 }
7490
7491 CGM.getOpenMPRuntime().emitCancelCall(*this, S.getBeginLoc(), IfCond,
7492 S.getCancelRegion());
7493}
7494
7497 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7498 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7499 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7500 return ReturnBlock;
7501 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7502 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7503 Kind == OMPD_distribute_parallel_for ||
7504 Kind == OMPD_target_parallel_for ||
7505 Kind == OMPD_teams_distribute_parallel_for ||
7506 Kind == OMPD_target_teams_distribute_parallel_for);
7507 return OMPCancelStack.getExitBlock();
7508}
7509
7511 const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope,
7512 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7513 CaptureDeviceAddrMap) {
7514 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7515 for (const Expr *OrigVarIt : C.varlist()) {
7516 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(OrigVarIt)->getDecl());
7517 if (!Processed.insert(OrigVD).second)
7518 continue;
7519
7520 // In order to identify the right initializer we need to match the
7521 // declaration used by the mapping logic. In some cases we may get
7522 // OMPCapturedExprDecl that refers to the original declaration.
7523 const ValueDecl *MatchingVD = OrigVD;
7524 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7525 // OMPCapturedExprDecl are used to privative fields of the current
7526 // structure.
7527 const auto *ME = cast<MemberExpr>(OED->getInit());
7528 assert(isa<CXXThisExpr>(ME->getBase()->IgnoreImpCasts()) &&
7529 "Base should be the current struct!");
7530 MatchingVD = ME->getMemberDecl();
7531 }
7532
7533 // If we don't have information about the current list item, move on to
7534 // the next one.
7535 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7536 if (InitAddrIt == CaptureDeviceAddrMap.end())
7537 continue;
7538
7539 llvm::Type *Ty = ConvertTypeForMem(OrigVD->getType().getNonReferenceType());
7540
7541 // Return the address of the private variable.
7542 bool IsRegistered = PrivateScope.addPrivate(
7543 OrigVD,
7544 Address(InitAddrIt->second, Ty,
7545 getContext().getTypeAlignInChars(getContext().VoidPtrTy)));
7546 assert(IsRegistered && "firstprivate var already registered as private");
7547 // Silence the warning about unused variable.
7548 (void)IsRegistered;
7549 }
7550}
7551
7552static const VarDecl *getBaseDecl(const Expr *Ref) {
7553 const Expr *Base = Ref->IgnoreParenImpCasts();
7554 while (const auto *OASE = dyn_cast<ArraySectionExpr>(Base))
7555 Base = OASE->getBase()->IgnoreParenImpCasts();
7556 while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Base))
7557 Base = ASE->getBase()->IgnoreParenImpCasts();
7558 return cast<VarDecl>(cast<DeclRefExpr>(Base)->getDecl());
7559}
7560
7562 const OMPUseDeviceAddrClause &C, OMPPrivateScope &PrivateScope,
7563 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7564 CaptureDeviceAddrMap) {
7565 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7566 for (const Expr *Ref : C.varlist()) {
7567 const VarDecl *OrigVD = getBaseDecl(Ref);
7568 if (!Processed.insert(OrigVD).second)
7569 continue;
7570 // In order to identify the right initializer we need to match the
7571 // declaration used by the mapping logic. In some cases we may get
7572 // OMPCapturedExprDecl that refers to the original declaration.
7573 const ValueDecl *MatchingVD = OrigVD;
7574 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7575 // OMPCapturedExprDecl are used to privative fields of the current
7576 // structure.
7577 const auto *ME = cast<MemberExpr>(OED->getInit());
7578 assert(isa<CXXThisExpr>(ME->getBase()) &&
7579 "Base should be the current struct!");
7580 MatchingVD = ME->getMemberDecl();
7581 }
7582
7583 // If we don't have information about the current list item, move on to
7584 // the next one.
7585 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7586 if (InitAddrIt == CaptureDeviceAddrMap.end())
7587 continue;
7588
7589 llvm::Type *Ty = ConvertTypeForMem(OrigVD->getType().getNonReferenceType());
7590
7591 Address PrivAddr =
7592 Address(InitAddrIt->second, Ty,
7593 getContext().getTypeAlignInChars(getContext().VoidPtrTy));
7594 // For declrefs and variable length array need to load the pointer for
7595 // correct mapping, since the pointer to the data was passed to the runtime.
7596 if (isa<DeclRefExpr>(Ref->IgnoreParenImpCasts()) ||
7597 MatchingVD->getType()->isArrayType()) {
7599 OrigVD->getType().getNonReferenceType());
7600 PrivAddr =
7602 PtrTy->castAs<PointerType>());
7603 }
7604
7605 (void)PrivateScope.addPrivate(OrigVD, PrivAddr);
7606 }
7607}
7608
7609// Generate the instructions for '#pragma omp target data' directive.
7611 const OMPTargetDataDirective &S) {
7612 CGOpenMPRuntime::TargetDataInfo Info(/*RequiresDevicePointerInfo=*/true,
7613 /*SeparateBeginEndCalls=*/true);
7614
7615 // Create a pre/post action to signal the privatization of the device pointer.
7616 // This action can be replaced by the OpenMP runtime code generation to
7617 // deactivate privatization.
7618 bool PrivatizeDevicePointers = false;
7619 class DevicePointerPrivActionTy : public PrePostActionTy {
7620 bool &PrivatizeDevicePointers;
7621
7622 public:
7623 explicit DevicePointerPrivActionTy(bool &PrivatizeDevicePointers)
7624 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7625 void Enter(CodeGenFunction &CGF) override {
7626 PrivatizeDevicePointers = true;
7627 }
7628 };
7629 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7630
7631 auto &&CodeGen = [&](CodeGenFunction &CGF, PrePostActionTy &Action) {
7632 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7633 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7634 };
7635
7636 // Codegen that selects whether to generate the privatization code or not.
7637 auto &&PrivCodeGen = [&](CodeGenFunction &CGF, PrePostActionTy &Action) {
7638 RegionCodeGenTy RCG(InnermostCodeGen);
7639 PrivatizeDevicePointers = false;
7640
7641 // Call the pre-action to change the status of PrivatizeDevicePointers if
7642 // needed.
7643 Action.Enter(CGF);
7644
7645 if (PrivatizeDevicePointers) {
7646 OMPPrivateScope PrivateScope(CGF);
7647 // Emit all instances of the use_device_ptr clause.
7648 for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>())
7649 CGF.EmitOMPUseDevicePtrClause(*C, PrivateScope,
7651 for (const auto *C : S.getClausesOfKind<OMPUseDeviceAddrClause>())
7652 CGF.EmitOMPUseDeviceAddrClause(*C, PrivateScope,
7654 (void)PrivateScope.Privatize();
7655 RCG(CGF);
7656 } else {
7657 // If we don't have target devices, don't bother emitting the data
7658 // mapping code.
7659 std::optional<OpenMPDirectiveKind> CaptureRegion;
7660 if (CGM.getLangOpts().OMPTargetTriples.empty()) {
7661 // Emit helper decls of the use_device_ptr/use_device_addr clauses.
7662 for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>())
7663 for (const Expr *E : C->varlist()) {
7664 const Decl *D = cast<DeclRefExpr>(E)->getDecl();
7665 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7666 CGF.EmitVarDecl(*OED);
7667 }
7668 for (const auto *C : S.getClausesOfKind<OMPUseDeviceAddrClause>())
7669 for (const Expr *E : C->varlist()) {
7670 const Decl *D = getBaseDecl(E);
7671 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7672 CGF.EmitVarDecl(*OED);
7673 }
7674 } else {
7675 CaptureRegion = OMPD_unknown;
7676 }
7677
7678 OMPLexicalScope Scope(CGF, S, CaptureRegion);
7679 RCG(CGF);
7680 }
7681 };
7682
7683 // Forward the provided action to the privatization codegen.
7684 RegionCodeGenTy PrivRCG(PrivCodeGen);
7685 PrivRCG.setAction(Action);
7686
7687 // Notwithstanding the body of the region is emitted as inlined directive,
7688 // we don't use an inline scope as changes in the references inside the
7689 // region are expected to be visible outside, so we do not privative them.
7690 OMPLexicalScope Scope(CGF, S);
7691 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data,
7692 PrivRCG);
7693 };
7694
7695 RegionCodeGenTy RCG(CodeGen);
7696
7697 // If we don't have target devices, don't bother emitting the data mapping
7698 // code.
7699 if (CGM.getLangOpts().OMPTargetTriples.empty()) {
7700 RCG(*this);
7701 return;
7702 }
7703
7704 // Check if we have any if clause associated with the directive.
7705 const Expr *IfCond = nullptr;
7706 if (const auto *C = S.getSingleClause<OMPIfClause>())
7707 IfCond = C->getCondition();
7708
7709 // Check if we have any device clause associated with the directive.
7710 const Expr *Device = nullptr;
7711 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
7712 Device = C->getDevice();
7713
7714 // Set the action to signal privatization of device pointers.
7715 RCG.setAction(PrivAction);
7716
7717 // Emit region code.
7718 CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, RCG,
7719 Info);
7720}
7721
7723 const OMPTargetEnterDataDirective &S) {
7724 // If we don't have target devices, don't bother emitting the data mapping
7725 // code.
7726 if (CGM.getLangOpts().OMPTargetTriples.empty())
7727 return;
7728
7729 // Check if we have any if clause associated with the directive.
7730 const Expr *IfCond = nullptr;
7731 if (const auto *C = S.getSingleClause<OMPIfClause>())
7732 IfCond = C->getCondition();
7733
7734 // Check if we have any device clause associated with the directive.
7735 const Expr *Device = nullptr;
7736 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
7737 Device = C->getDevice();
7738
7739 OMPLexicalScope Scope(*this, S, OMPD_task);
7741}
7742
7744 const OMPTargetExitDataDirective &S) {
7745 // If we don't have target devices, don't bother emitting the data mapping
7746 // code.
7747 if (CGM.getLangOpts().OMPTargetTriples.empty())
7748 return;
7749
7750 // Check if we have any if clause associated with the directive.
7751 const Expr *IfCond = nullptr;
7752 if (const auto *C = S.getSingleClause<OMPIfClause>())
7753 IfCond = C->getCondition();
7754
7755 // Check if we have any device clause associated with the directive.
7756 const Expr *Device = nullptr;
7757 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
7758 Device = C->getDevice();
7759
7760 OMPLexicalScope Scope(*this, S, OMPD_task);
7762}
7763
7766 PrePostActionTy &Action) {
7767 // Get the captured statement associated with the 'parallel' region.
7768 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
7769 Action.Enter(CGF);
7770 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
7771 Action.Enter(CGF);
7772 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7773 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
7774 CGF.EmitOMPPrivateClause(S, PrivateScope);
7775 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7776 (void)PrivateScope.Privatize();
7777 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
7779 // TODO: Add support for clauses.
7780 CGF.EmitStmt(CS->getCapturedStmt());
7781 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
7782 };
7783 emitCommonOMPParallelDirective(CGF, S, OMPD_parallel, CodeGen,
7786 [](CodeGenFunction &) { return nullptr; });
7787}
7788
7790 CodeGenModule &CGM, StringRef ParentName,
7791 const OMPTargetParallelDirective &S) {
7792 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7793 emitTargetParallelRegion(CGF, S, Action);
7794 };
7795 llvm::Function *Fn;
7796 llvm::Constant *Addr;
7797 // Emit target region as a standalone region.
7799 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7800 assert(Fn && Addr && "Target device function emission failed.");
7801}
7802
7804 const OMPTargetParallelDirective &S) {
7805 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7806 emitTargetParallelRegion(CGF, S, Action);
7807 };
7808 emitCommonOMPTargetDirective(*this, S, CodeGen);
7809}
7810
7813 PrePostActionTy &Action) {
7814 Action.Enter(CGF);
7815 // Emit directive as a combined directive that consists of two implicit
7816 // directives: 'parallel' with 'for' directive.
7817 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7818 Action.Enter(CGF);
7820 CGF, OMPD_target_parallel_for, S.hasCancel());
7821 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
7823 };
7824 emitCommonOMPParallelDirective(CGF, S, OMPD_for, CodeGen,
7826}
7827
7829 CodeGenModule &CGM, StringRef ParentName,
7831 // Emit SPMD target parallel for region as a standalone region.
7832 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7833 emitTargetParallelForRegion(CGF, S, Action);
7834 };
7835 llvm::Function *Fn;
7836 llvm::Constant *Addr;
7837 // Emit target region as a standalone region.
7839 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7840 assert(Fn && Addr && "Target device function emission failed.");
7841}
7842
7845 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7846 emitTargetParallelForRegion(CGF, S, Action);
7847 };
7848 emitCommonOMPTargetDirective(*this, S, CodeGen);
7849}
7850
7851static void
7854 PrePostActionTy &Action) {
7855 Action.Enter(CGF);
7856 // Emit directive as a combined directive that consists of two implicit
7857 // directives: 'parallel' with 'for' directive.
7858 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7859 Action.Enter(CGF);
7860 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
7862 };
7863 emitCommonOMPParallelDirective(CGF, S, OMPD_simd, CodeGen,
7865}
7866
7868 CodeGenModule &CGM, StringRef ParentName,
7870 // Emit SPMD target parallel for region as a standalone region.
7871 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7872 emitTargetParallelForSimdRegion(CGF, S, Action);
7873 };
7874 llvm::Function *Fn;
7875 llvm::Constant *Addr;
7876 // Emit target region as a standalone region.
7878 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7879 assert(Fn && Addr && "Target device function emission failed.");
7880}
7881
7884 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7885 emitTargetParallelForSimdRegion(CGF, S, Action);
7886 };
7887 emitCommonOMPTargetDirective(*this, S, CodeGen);
7888}
7889
7890/// Emit a helper variable and return corresponding lvalue.
7891static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper,
7892 const ImplicitParamDecl *PVD,
7894 const auto *VDecl = cast<VarDecl>(Helper->getDecl());
7895 Privates.addPrivate(VDecl, CGF.GetAddrOfLocalVar(PVD));
7896}
7897
7899 assert(isOpenMPTaskLoopDirective(S.getDirectiveKind()));
7900 // Emit outlined function for task construct.
7901 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
7902 Address CapturedStruct = Address::invalid();
7903 {
7904 OMPLexicalScope Scope(*this, S, OMPD_taskloop, /*EmitPreInitStmt=*/false);
7905 CapturedStruct = GenerateCapturedStmtArgument(*CS);
7906 }
7907 CanQualType SharedsTy =
7909 const Expr *IfCond = nullptr;
7910 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
7911 if (C->getNameModifier() == OMPD_unknown ||
7912 C->getNameModifier() == OMPD_taskloop) {
7913 IfCond = C->getCondition();
7914 break;
7915 }
7916 }
7917
7919 // Check if taskloop must be emitted without taskgroup.
7920 Data.Nogroup = S.getSingleClause<OMPNogroupClause>();
7921 // TODO: Check if we should emit tied or untied task.
7922 Data.Tied = true;
7923 // Set scheduling for taskloop
7924 if (const auto *Clause = S.getSingleClause<OMPGrainsizeClause>()) {
7925 // grainsize clause
7926 Data.Schedule.setInt(/*IntVal=*/false);
7927 Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize()));
7928 Data.HasModifier =
7929 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ? true : false;
7930 } else if (const auto *Clause = S.getSingleClause<OMPNumTasksClause>()) {
7931 // num_tasks clause
7932 Data.Schedule.setInt(/*IntVal=*/true);
7933 Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks()));
7934 Data.HasModifier =
7935 (Clause->getModifier() == OMPC_NUMTASKS_strict) ? true : false;
7936 }
7937
7938 auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) {
7939 // if (PreCond) {
7940 // for (IV in 0..LastIteration) BODY;
7941 // <Final counter/linear vars updates>;
7942 // }
7943 //
7944
7945 // Emit: if (PreCond) - begin.
7946 // If the condition constant folds and can be elided, avoid emitting the
7947 // whole loop.
7948 bool CondConstant;
7949 llvm::BasicBlock *ContBlock = nullptr;
7950 OMPLoopScope PreInitScope(CGF, S);
7951 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
7952 if (!CondConstant)
7953 return;
7954 } else {
7955 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("taskloop.if.then");
7956 ContBlock = CGF.createBasicBlock("taskloop.if.end");
7957 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
7958 CGF.getProfileCount(&S));
7959 CGF.EmitBlock(ThenBlock);
7960 CGF.incrementProfileCounter(&S);
7961 }
7962
7963 (void)CGF.EmitOMPLinearClauseInit(S);
7964
7965 OMPPrivateScope LoopScope(CGF);
7966 // Emit helper vars inits.
7967 enum { LowerBound = 5, UpperBound, Stride, LastIter };
7968 auto *I = CS->getCapturedDecl()->param_begin();
7969 auto *LBP = std::next(I, LowerBound);
7970 auto *UBP = std::next(I, UpperBound);
7971 auto *STP = std::next(I, Stride);
7972 auto *LIP = std::next(I, LastIter);
7973 mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP,
7974 LoopScope);
7975 mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP,
7976 LoopScope);
7977 mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope);
7978 mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP,
7979 LoopScope);
7980 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
7981 CGF.EmitOMPLinearClause(S, LoopScope);
7982 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
7983 (void)LoopScope.Privatize();
7984 // Emit the loop iteration variable.
7985 const Expr *IVExpr = S.getIterationVariable();
7986 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
7987 CGF.EmitVarDecl(*IVDecl);
7988 CGF.EmitIgnoredExpr(S.getInit());
7989
7990 // Emit the iterations count variable.
7991 // If it is not a variable, Sema decided to calculate iterations count on
7992 // each iteration (e.g., it is foldable into a constant).
7993 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
7994 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
7995 // Emit calculation of the iterations count.
7996 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
7997 }
7998
7999 {
8000 OMPLexicalScope Scope(CGF, S, OMPD_taskloop, /*EmitPreInitStmt=*/false);
8002 CGF, S,
8003 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
8004 if (isOpenMPSimdDirective(S.getDirectiveKind()))
8005 CGF.EmitOMPSimdInit(S);
8006 },
8007 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
8008 CGF.EmitOMPInnerLoop(
8009 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
8010 [&S](CodeGenFunction &CGF) {
8011 emitOMPLoopBodyWithStopPoint(CGF, S,
8012 CodeGenFunction::JumpDest());
8013 },
8014 [](CodeGenFunction &) {});
8015 });
8016 }
8017 // Emit: if (PreCond) - end.
8018 if (ContBlock) {
8019 CGF.EmitBranch(ContBlock);
8020 CGF.EmitBlock(ContBlock, true);
8021 }
8022 // Emit final copy of the lastprivate variables if IsLastIter != 0.
8023 if (HasLastprivateClause) {
8024 CGF.EmitOMPLastprivateClauseFinal(
8025 S, isOpenMPSimdDirective(S.getDirectiveKind()),
8026 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8027 CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
8028 (*LIP)->getType(), S.getBeginLoc())));
8029 }
8030 LoopScope.restoreMap();
8031 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8032 return CGF.Builder.CreateIsNotNull(
8033 CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
8034 (*LIP)->getType(), S.getBeginLoc()));
8035 });
8036 };
8037 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8038 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8039 const OMPTaskDataTy &Data) {
8040 auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8042 OMPLoopScope PreInitScope(CGF, S);
8043 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8044 OutlinedFn, SharedsTy,
8045 CapturedStruct, IfCond, Data);
8046 };
8047 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8048 CodeGen);
8049 };
8050 if (Data.Nogroup) {
8051 EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, Data);
8052 } else {
8054 *this,
8055 [&S, &BodyGen, &TaskGen, &Data](CodeGenFunction &CGF,
8056 PrePostActionTy &Action) {
8057 Action.Enter(CGF);
8058 CGF.EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen,
8059 Data);
8060 },
8061 S.getBeginLoc());
8062 }
8063}
8064
8066 auto LPCRegion =
8069}
8070
8072 const OMPTaskLoopSimdDirective &S) {
8073 auto LPCRegion =
8075 OMPLexicalScope Scope(*this, S);
8077}
8078
8080 const OMPMasterTaskLoopDirective &S) {
8081 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8082 Action.Enter(CGF);
8084 };
8085 auto LPCRegion =
8087 OMPLexicalScope Scope(*this, S, std::nullopt, /*EmitPreInitStmt=*/false);
8088 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
8089}
8090
8092 const OMPMaskedTaskLoopDirective &S) {
8093 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8094 Action.Enter(CGF);
8096 };
8097 auto LPCRegion =
8099 OMPLexicalScope Scope(*this, S, std::nullopt, /*EmitPreInitStmt=*/false);
8100 CGM.getOpenMPRuntime().emitMaskedRegion(*this, CodeGen, S.getBeginLoc());
8101}
8102
8105 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8106 Action.Enter(CGF);
8108 };
8109 auto LPCRegion =
8111 OMPLexicalScope Scope(*this, S);
8112 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
8113}
8114
8117 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8118 Action.Enter(CGF);
8120 };
8121 auto LPCRegion =
8123 OMPLexicalScope Scope(*this, S);
8124 CGM.getOpenMPRuntime().emitMaskedRegion(*this, CodeGen, S.getBeginLoc());
8125}
8126
8129 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8130 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8131 PrePostActionTy &Action) {
8132 Action.Enter(CGF);
8134 };
8135 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
8136 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8137 S.getBeginLoc());
8138 };
8139 auto LPCRegion =
8141 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop, CodeGen,
8143}
8144
8147 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8148 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8149 PrePostActionTy &Action) {
8150 Action.Enter(CGF);
8152 };
8153 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
8154 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8155 S.getBeginLoc());
8156 };
8157 auto LPCRegion =
8159 emitCommonOMPParallelDirective(*this, S, OMPD_masked_taskloop, CodeGen,
8161}
8162
8165 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8166 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8167 PrePostActionTy &Action) {
8168 Action.Enter(CGF);
8170 };
8171 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
8172 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8173 S.getBeginLoc());
8174 };
8175 auto LPCRegion =
8177 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop_simd, CodeGen,
8179}
8180
8183 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8184 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8185 PrePostActionTy &Action) {
8186 Action.Enter(CGF);
8188 };
8189 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
8190 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8191 S.getBeginLoc());
8192 };
8193 auto LPCRegion =
8195 emitCommonOMPParallelDirective(*this, S, OMPD_masked_taskloop_simd, CodeGen,
8197}
8198
8199// Generate the instructions for '#pragma omp target update' directive.
8201 const OMPTargetUpdateDirective &S) {
8202 // If we don't have target devices, don't bother emitting the data mapping
8203 // code.
8204 if (CGM.getLangOpts().OMPTargetTriples.empty())
8205 return;
8206
8207 // Check if we have any if clause associated with the directive.
8208 const Expr *IfCond = nullptr;
8209 if (const auto *C = S.getSingleClause<OMPIfClause>())
8210 IfCond = C->getCondition();
8211
8212 // Check if we have any device clause associated with the directive.
8213 const Expr *Device = nullptr;
8214 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
8215 Device = C->getDevice();
8216
8217 OMPLexicalScope Scope(*this, S, OMPD_task);
8219}
8220
8222 const OMPGenericLoopDirective &S) {
8223 // Always expect a bind clause on the loop directive. It it wasn't
8224 // in the source, it should have been added in sema.
8225
8227 if (const auto *C = S.getSingleClause<OMPBindClause>())
8228 BindKind = C->getBindKind();
8229
8230 switch (BindKind) {
8231 case OMPC_BIND_parallel: // for
8232 return emitOMPForDirective(S, *this, CGM, /*HasCancel=*/false);
8233 case OMPC_BIND_teams: // distribute
8234 return emitOMPDistributeDirective(S, *this, CGM);
8235 case OMPC_BIND_thread: // simd
8236 return emitOMPSimdDirective(S, *this, CGM);
8237 case OMPC_BIND_unknown:
8238 break;
8239 }
8240
8241 // Unimplemented, just inline the underlying statement for now.
8242 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8243 // Emit the loop iteration variable.
8244 const Stmt *CS =
8245 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
8246 const auto *ForS = dyn_cast<ForStmt>(CS);
8247 if (ForS && !isa<DeclStmt>(ForS->getInit())) {
8248 OMPPrivateScope LoopScope(CGF);
8249 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8250 (void)LoopScope.Privatize();
8251 CGF.EmitStmt(CS);
8252 LoopScope.restoreMap();
8253 } else {
8254 CGF.EmitStmt(CS);
8255 }
8256 };
8257 OMPLexicalScope Scope(*this, S, OMPD_unknown);
8258 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_loop, CodeGen);
8259}
8260
8262 const OMPLoopDirective &S) {
8263 // Emit combined directive as if its constituent constructs are 'parallel'
8264 // and 'for'.
8265 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8266 Action.Enter(CGF);
8267 emitOMPCopyinClause(CGF, S);
8268 (void)emitWorksharingDirective(CGF, S, /*HasCancel=*/false);
8269 };
8270 {
8271 auto LPCRegion =
8273 emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen,
8275 }
8276 // Check for outer lastprivate conditional update.
8278}
8279
8282 // To be consistent with current behavior of 'target teams loop', emit
8283 // 'teams loop' as if its constituent constructs are 'teams' and 'distribute'.
8284 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
8286 };
8287
8288 // Emit teams region as a standalone region.
8289 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8290 PrePostActionTy &Action) {
8291 Action.Enter(CGF);
8292 OMPPrivateScope PrivateScope(CGF);
8293 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
8294 (void)PrivateScope.Privatize();
8295 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
8296 CodeGenDistribute);
8297 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
8298 };
8299 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
8301 [](CodeGenFunction &) { return nullptr; });
8302}
8303
8304#ifndef NDEBUG
8306 std::string StatusMsg,
8307 const OMPExecutableDirective &D) {
8308 bool IsDevice = CGF.CGM.getLangOpts().OpenMPIsTargetDevice;
8309 if (IsDevice)
8310 StatusMsg += ": DEVICE";
8311 else
8312 StatusMsg += ": HOST";
8314 auto &SM = CGF.getContext().getSourceManager();
8315 PresumedLoc PLoc = SM.getPresumedLoc(L);
8316 const char *FileName = PLoc.isValid() ? PLoc.getFilename() : nullptr;
8317 unsigned LineNo =
8318 PLoc.isValid() ? PLoc.getLine() : SM.getExpansionLineNumber(L);
8319 llvm::dbgs() << StatusMsg << ": " << FileName << ": " << LineNo << "\n";
8320}
8321#endif
8322
8324 CodeGenFunction &CGF, PrePostActionTy &Action,
8326 Action.Enter(CGF);
8327 // Emit 'teams loop' as if its constituent constructs are 'distribute,
8328 // 'parallel, and 'for'.
8329 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
8331 S.getDistInc());
8332 };
8333
8334 // Emit teams region as a standalone region.
8335 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8336 PrePostActionTy &Action) {
8337 Action.Enter(CGF);
8338 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
8339 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
8340 (void)PrivateScope.Privatize();
8342 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
8343 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
8344 };
8345 DEBUG_WITH_TYPE(TTL_CODEGEN_TYPE,
8347 CGF, TTL_CODEGEN_TYPE " as parallel for", S));
8348 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for,
8349 CodeGenTeams);
8351 [](CodeGenFunction &) { return nullptr; });
8352}
8353
8355 CodeGenFunction &CGF, PrePostActionTy &Action,
8357 Action.Enter(CGF);
8358 // Emit 'teams loop' as if its constituent construct is 'distribute'.
8359 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
8361 };
8362
8363 // Emit teams region as a standalone region.
8364 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8365 PrePostActionTy &Action) {
8366 Action.Enter(CGF);
8367 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
8368 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
8369 (void)PrivateScope.Privatize();
8371 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
8372 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
8373 };
8374 DEBUG_WITH_TYPE(TTL_CODEGEN_TYPE,
8376 CGF, TTL_CODEGEN_TYPE " as distribute", S));
8377 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute, CodeGen);
8379 [](CodeGenFunction &) { return nullptr; });
8380}
8381
8384 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8385 if (S.canBeParallelFor())
8387 else
8389 };
8390 emitCommonOMPTargetDirective(*this, S, CodeGen);
8391}
8392
8394 CodeGenModule &CGM, StringRef ParentName,
8396 // Emit SPMD target parallel loop region as a standalone region.
8397 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8398 if (S.canBeParallelFor())
8400 else
8402 };
8403 llvm::Function *Fn;
8404 llvm::Constant *Addr;
8405 // Emit target region as a standalone region.
8407 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
8408 assert(Fn && Addr &&
8409 "Target device function emission failed for 'target teams loop'.");
8410}
8411
8414 PrePostActionTy &Action) {
8415 Action.Enter(CGF);
8416 // Emit as 'parallel for'.
8417 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8418 Action.Enter(CGF);
8420 CGF, OMPD_target_parallel_loop, /*hasCancel=*/false);
8421 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
8423 };
8424 emitCommonOMPParallelDirective(CGF, S, OMPD_for, CodeGen,
8426}
8427
8429 CodeGenModule &CGM, StringRef ParentName,
8431 // Emit target parallel loop region as a standalone region.
8432 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8434 };
8435 llvm::Function *Fn;
8436 llvm::Constant *Addr;
8437 // Emit target region as a standalone region.
8439 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
8440 assert(Fn && Addr && "Target device function emission failed.");
8441}
8442
8443/// Emit combined directive 'target parallel loop' as if its constituent
8444/// constructs are 'target', 'parallel', and 'for'.
8447 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8449 };
8450 emitCommonOMPTargetDirective(*this, S, CodeGen);
8451}
8452
8454 const OMPExecutableDirective &D) {
8455 if (const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8457 return;
8458 }
8459 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8460 return;
8461 auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) {
8462 OMPPrivateScope GlobalsScope(CGF);
8463 if (isOpenMPTaskingDirective(D.getDirectiveKind())) {
8464 // Capture global firstprivates to avoid crash.
8465 for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8466 for (const Expr *Ref : C->varlist()) {
8467 const auto *DRE = cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
8468 if (!DRE)
8469 continue;
8470 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8471 if (!VD || VD->hasLocalStorage())
8472 continue;
8473 if (!CGF.LocalDeclMap.count(VD)) {
8474 LValue GlobLVal = CGF.EmitLValue(Ref);
8475 GlobalsScope.addPrivate(VD, GlobLVal.getAddress());
8476 }
8477 }
8478 }
8479 }
8480 if (isOpenMPSimdDirective(D.getDirectiveKind())) {
8481 (void)GlobalsScope.Privatize();
8482 ParentLoopDirectiveForScanRegion ScanRegion(CGF, D);
8483 emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action);
8484 } else {
8485 if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8486 for (const Expr *E : LD->counters()) {
8487 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
8488 if (!VD->hasLocalStorage() && !CGF.LocalDeclMap.count(VD)) {
8489 LValue GlobLVal = CGF.EmitLValue(E);
8490 GlobalsScope.addPrivate(VD, GlobLVal.getAddress());
8491 }
8492 if (isa<OMPCapturedExprDecl>(VD)) {
8493 // Emit only those that were not explicitly referenced in clauses.
8494 if (!CGF.LocalDeclMap.count(VD))
8495 CGF.EmitVarDecl(*VD);
8496 }
8497 }
8498 for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) {
8499 if (!C->getNumForLoops())
8500 continue;
8501 for (unsigned I = LD->getLoopsNumber(),
8502 E = C->getLoopNumIterations().size();
8503 I < E; ++I) {
8504 if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8505 cast<DeclRefExpr>(C->getLoopCounter(I))->getDecl())) {
8506 // Emit only those that were not explicitly referenced in clauses.
8507 if (!CGF.LocalDeclMap.count(VD))
8508 CGF.EmitVarDecl(*VD);
8509 }
8510 }
8511 }
8512 }
8513 (void)GlobalsScope.Privatize();
8514 CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8515 }
8516 };
8517 if (D.getDirectiveKind() == OMPD_atomic ||
8518 D.getDirectiveKind() == OMPD_critical ||
8519 D.getDirectiveKind() == OMPD_section ||
8520 D.getDirectiveKind() == OMPD_master ||
8521 D.getDirectiveKind() == OMPD_masked ||
8522 D.getDirectiveKind() == OMPD_unroll ||
8523 D.getDirectiveKind() == OMPD_assume) {
8524 EmitStmt(D.getAssociatedStmt());
8525 } else {
8526 auto LPCRegion =
8528 OMPSimdLexicalScope Scope(*this, D);
8530 *this,
8531 isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd
8532 : D.getDirectiveKind(),
8533 CodeGen);
8534 }
8535 // Check for outer lastprivate conditional update.
8537}
8538
8540 EmitStmt(S.getAssociatedStmt());
8541}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3597
static bool isAllocatableDecl(const VarDecl *VD)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, PrePostActionTy &Action)
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action)
static llvm::Function * emitOutlinedOrderedFunction(CodeGenModule &CGM, const CapturedStmt *S, SourceLocation Loc)
static const VarDecl * getBaseDecl(const Expr *Ref)
static void emitTargetTeamsGenericLoopRegionAsParallel(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *V, SourceLocation Loc)
static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, bool IsPostfixUpdate, const Expr *V, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static void emitScanBasedDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen, llvm::function_ref< void(CodeGenFunction &)> FirstGen, llvm::function_ref< void(CodeGenFunction &)> SecondGen)
Emits the code for the directive with inscan reductions.
static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, RValue RVal)
static bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T)
static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, QualType DstType, StringRef Name, LValue AddrLV)
static void emitDistributeParallelForDistributeInnerBoundParams(CodeGenFunction &CGF, const OMPExecutableDirective &S, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars)
static void emitScanBasedDirectiveFinals(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Copies final inscan reductions values to the original variables.
static void checkForLastprivateConditionalUpdate(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static std::pair< LValue, LValue > emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
The following two functions generate expressions for the loop lower and upper bounds in case of stati...
static void emitTargetParallelForRegion(CodeGenFunction &CGF, const OMPTargetParallelForDirective &S, PrePostActionTy &Action)
static LValue EmitOMPHelperVar(CodeGenFunction &CGF, const DeclRefExpr *Helper)
Emit a helper variable and return corresponding lvalue.
static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static llvm::Value * convertToScalarValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount)
static std::pair< bool, RValue > emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, RValue Update, BinaryOperatorKind BO, llvm::AtomicOrdering AO, bool IsXLHSInRHSPart)
static std::pair< LValue, LValue > emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsGenericLoopRegionAsDistribute(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitTargetParallelRegion(CodeGenFunction &CGF, const OMPTargetParallelDirective &S, PrePostActionTy &Action)
static std::pair< llvm::Value *, llvm::Value * > emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
When dealing with dispatch schedules (e.g.
static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitRestoreIP(CodeGenFunction &CGF, const T *C, llvm::OpenMPIRBuilder::InsertPointTy AllocaIP, llvm::OpenMPIRBuilder &OMPBuilder)
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, const RegionCodeGenTy &CodeGen)
static void emitSimdlenSafelenClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static void emitAlignedClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static bool isSimdSupportedByOpenMPIRBuilder(const OMPLoopDirective &S)
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, const CodeGenBoundParametersTy &CodeGenBoundParameters)
static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt, LoopInfoStack &LoopStack)
static bool emitWorksharingDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, bool HasCancel)
static void emitPostUpdateForReductionClause(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, const unsigned IVSize, const bool IVSigned)
static void emitTargetTeamsLoopCodegenStatus(CodeGenFunction &CGF, std::string StatusMsg, const OMPExecutableDirective &D)
static bool isForSupportedByOpenMPIRBuilder(const OMPLoopDirective &S, bool HasCancel)
static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, SourceLocation Loc)
static std::pair< llvm::Value *, llvm::Value * > emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
if the 'for' loop has a dispatch schedule (e.g.
static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, bool IsPostfixUpdate, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *UE, const Expr *D, const Expr *CE, bool IsXLHSInRHSPart, bool IsFailOnly, SourceLocation Loc)
#define TTL_CODEGEN_TYPE
static CodeGenFunction::ComplexPairTy convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static ImplicitParamDecl * createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, QualType Ty, CapturedDecl *CD, SourceLocation Loc)
static EmittedClosureTy emitCapturedStmtFunc(CodeGenFunction &ParentCGF, const CapturedStmt *S)
Emit a captured statement and return the function as well as its captured closure context.
static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitOMPDistributeDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPCopyinClause(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsDistributeParallelForRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S, PrePostActionTy &Action)
static bool hasOrderedDirective(const Stmt *S)
static llvm::CallInst * emitCapturedStmtCall(CodeGenFunction &ParentCGF, EmittedClosureTy Cap, llvm::ArrayRef< llvm::Value * > Args)
Emit a call to a previously captured closure.
static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop, int MaxLevel, int Level=0)
static void emitOMPForDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM, bool HasCancel)
static void emitEmptyBoundParameters(CodeGenFunction &, const OMPExecutableDirective &, llvm::SmallVectorImpl< llvm::Value * > &)
static void emitTargetParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitOMPSimdDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *D, const Expr *CE, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly, SourceLocation Loc)
std::pair< llvm::Function *, llvm::Value * > EmittedClosureTy
static OpenMPDirectiveKind getEffectiveDirectiveKind(const OMPExecutableDirective &S)
static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDirective &S)
static void buildDependences(const OMPExecutableDirective &S, OMPTaskDataTy &Data)
static RValue convertToType(CodeGenFunction &CGF, RValue Value, QualType SourceType, QualType ResType, SourceLocation Loc)
static void emitScanBasedDirectiveDecls(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Emits internal temp array declarations for the directive with inscan reductions.
static void emitTargetTeamsDistributeParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitTargetTeamsDistributeSimdRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeSimdDirective &S)
static llvm::MapVector< llvm::Value *, llvm::Value * > GetAlignedMapping(const OMPLoopDirective &S, CodeGenFunction &CGF)
static llvm::omp::ScheduleKind convertClauseKindToSchedKind(OpenMPScheduleClauseKind ScheduleClauseKind)
static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, const ImplicitParamDecl *PVD, CodeGenFunction::OMPPrivateScope &Privates)
Emit a helper variable and return corresponding lvalue.
static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
static void emitTargetParallelGenericLoopRegion(CodeGenFunction &CGF, const OMPTargetParallelGenericLoopDirective &S, PrePostActionTy &Action)
static QualType getCanonicalParamType(ASTContext &C, QualType T)
static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S, const RegionCodeGenTy &SimdInitGen, const RegionCodeGenTy &BodyCodeGen)
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, const Twine &Name, llvm::Value *Init=nullptr)
static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, SourceLocation Loc)
static llvm::Function * emitOutlinedFunctionPrologue(CodeGenFunction &CGF, FunctionArgList &Args, llvm::MapVector< const Decl *, std::pair< const VarDecl *, Address > > &LocalAddrs, llvm::DenseMap< const Decl *, std::pair< const Expr *, llvm::Value * > > &VLASizes, llvm::Value *&CXXThisValue, const FunctionOptions &FO)
static void emitInnerParallelForWhenCombined(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeDirective &S)
const Decl * D
enum clang::sema::@1840::IndirectLocalPathEntry::EntryKind Kind
Expr * E
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
#define X(type, name)
Definition: Value.h:145
#define SM(sm)
Definition: OffloadArch.cpp:16
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
SourceLocation Loc
Definition: SemaObjC.cpp:754
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
SourceManager & getSourceManager()
Definition: ASTContext.h:801
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1201
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
Definition: ASTContext.h:1249
IdentifierTable & Idents
Definition: ASTContext.h:740
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element 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,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2625
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
Definition: ASTContext.h:1222
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Definition: ASTContext.h:1750
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:859
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
Definition: RecordLayout.h:38
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Definition: RecordLayout.h:201
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: TypeBase.h:3738
Represents an attribute applied to a statement.
Definition: Stmt.h:2203
ArrayRef< const Attr * > getAttrs() const
Definition: Stmt.h:2235
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3974
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Definition: Expr.cpp:4938
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition: Expr.h:6560
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition: Decl.h:4906
unsigned getContextParamPosition() const
Definition: Decl.h:4973
bool isNothrow() const
Definition: Decl.cpp:5569
static CapturedDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
Definition: Decl.cpp:5554
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
Definition: Decl.h:4981
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Definition: Decl.h:4979
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: Decl.cpp:5566
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4946
This captures a statement into a function.
Definition: Stmt.h:3886
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition: Stmt.cpp:1451
child_range children()
Definition: Stmt.cpp:1442
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Definition: Stmt.h:4007
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition: Stmt.h:3990
capture_range captures()
Definition: Stmt.h:4024
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
Definition: Stmt.h:4050
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition: CharUnits.h:185
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Definition: CharUnits.h:214
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition: CharUnits.h:63
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Definition: CharUnits.h:201
bool hasReducedDebugInfo() const
Check if type and variable info should be emitted.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition: Address.h:128
static Address invalid()
Definition: Address.h:176
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition: Address.h:253
CharUnits getAlignment() const
Definition: Address.h:194
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Definition: Address.h:209
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Definition: Address.h:276
Address withAlignment(CharUnits NewAlignment) const
Return address with different alignment, but same pointer and element type.
Definition: Address.h:269
llvm::PointerType * getType() const
Return the type of the pointer value.
Definition: Address.h:204
static AggValueSlot ignored()
ignored - Returns an aggregate value slot indicating that the aggregate value is being ignored.
Definition: CGValue.h:572
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
Definition: CGDebugInfo.h:953
llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")
Definition: CGBuilder.h:360
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
Definition: CGBuilder.h:207
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
Definition: CGBuilder.h:112
Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")
Definition: CGBuilder.h:350
CGFunctionInfo - Class to encapsulate the information about a function definition.
Manages list of lastprivate conditional decls for the specified directive.
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
Manages list of nontemporal decls for the specified directive.
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
Manages list of nontemporal decls for the specified directive.
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
virtual 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)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
virtual const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const
Translates the native parameter of outlined function if this is required for target.
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.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
virtual void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
virtual void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_teams,...
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, int proc_bind) to generat...
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
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 emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_threads)...
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
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::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
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 checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
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.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getAllocatedAddress() const
Returns the raw, allocated address, which is not necessarily the address of the object itself.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual StringRef getHelperName() const
Get the name of the capture helper.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
LValue getReferenceLValue(CodeGenFunction &CGF, const Expr *RefExpr) const
void ForceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
RAII for preserving necessary info during inlined region body codegen.
RAII for preserving necessary info during Outlined region body codegen.
Controls insertion of cancellation exit blocks in worksharing constructs.
Save/restore original map of previously emitted local vars in case when we need to duplicate emission...
The class used to assign some variables some temporarily addresses.
bool apply(CodeGenFunction &CGF)
Applies new addresses to the list of the variables.
void restore(CodeGenFunction &CGF)
Restores original addresses of the variables.
bool setVarAddr(CodeGenFunction &CGF, const VarDecl *LocalVD, Address TempAddr)
Sets the address of the variable LocalVD to be TempAddr in function CGF.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
void restoreMap()
Restore all mapped variables w/o clean up.
bool Privatize()
Privatizes local variables previously registered as private.
bool isGlobalVarCaptured(const VarDecl *VD) const
Checks if the global variable is captured in current function.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
bool requiresCleanups() const
Determine whether this scope requires any cleanups.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, SourceLocation Loc)
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void EmitOMPLastprivateClauseFinal(const OMPExecutableDirective &D, bool NoFinals, llvm::Value *IsLastIterCond=nullptr)
Emit final copying of lastprivate values to original variables at the end of the worksharing or simd ...
void processInReduction(const OMPExecutableDirective &S, OMPTaskDataTy &Data, CodeGenFunction &CGF, const CapturedStmt *CS, OMPPrivateScope &Scope)
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S)
void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy, SourceLocation Loc)
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
static bool hasScalarEvaluationKind(QualType T)
llvm::function_ref< std::pair< llvm::Value *, llvm::Value * >(CodeGenFunction &, const OMPExecutableDirective &S, Address LB, Address UB)> CodeGenDispatchBoundsTy
LValue InitCapturedStruct(const CapturedStmt &S)
Definition: CGStmt.cpp:3294
CGCapturedStmtInfo * CapturedStmtInfo
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOMPSimdInit(const OMPLoopDirective &D)
Helpers for the OpenMP loop directives.
const OMPExecutableDirective * OMPParentLoopDirectiveForScan
Parent loop-based directive for scan directive.
void EmitOMPFlushDirective(const OMPFlushDirective &S)
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
void EmitOMPReductionClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope, bool ForInscan=false)
Emit initial code for reduction variables.
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
Definition: CGDecl.cpp:1349
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
const LangOptions & getLangOpts() const
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
Definition: CGDecl.cpp:1483
void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO, const llvm::function_ref< RValue(RValue)> &UpdateOp, bool IsVolatile)
Definition: CGAtomic.cpp:2092
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
Definition: CGExpr.cpp:3039
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
Definition: CGCleanup.cpp:1112
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind)
Emit final update of reduction values to original variables at the end of the directive.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit)
Helper for the OpenMP loop directives.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
const llvm::function_ref< void(CodeGenFunction &, llvm::Function *, const OMPTaskDataTy &)> TaskGenTy
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
bool EmitOMPCopyinClause(const OMPExecutableDirective &D)
Emit code for copyin clause in D directive.
void EmitOMPLinearClause(const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope)
Emit initial code for linear clauses.
llvm::BasicBlock * OMPBeforeScanBlock
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, OMPPrivateScope &LoopScope)
Emit initial code for loop counters of loop-based directives.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
Definition: CGExpr.cpp:242
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
Definition: CGExpr.cpp:2336
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type,...
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB, const CodeGenLoopBoundsTy &CodeGenLoopBounds, const CodeGenDispatchBoundsTy &CGDispatchBounds)
Emit code for the worksharing loop-based directive.
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
llvm::CanonicalLoopInfo * EmitOMPCollapsedCanonicalLoopNest(const Stmt *S, int Depth)
Emit the Stmt S and return its topmost canonical loop, if any.
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
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.
void EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
Definition: CGExpr.cpp:223
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
void EmitOMPUseDeviceAddrClause(const OMPUseDeviceAddrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
Definition: CGAtomic.cpp:1549
void EmitOMPDistributeLoop(const OMPLoopDirective &S, const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr)
Emit code for the distribute loop-based directive.
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
llvm::BasicBlock * OMPScanDispatch
llvm::function_ref< std::pair< LValue, LValue >(CodeGenFunction &, const OMPExecutableDirective &S)> CodeGenLoopBoundsTy
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
std::pair< bool, RValue > EmitOMPAtomicSimpleUpdateExpr(LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, llvm::AtomicOrdering AO, SourceLocation Loc, const llvm::function_ref< RValue(RValue)> CommonGen)
Emit atomic update code for constructs: X = X BO E or X = E BO E.
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
int ExpectedOMPLoopDepth
Number of nested loop to be consumed by the last surrounding loop-associated directive.
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
Definition: CGStmt.cpp:51
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
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...
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
Definition: CGDecl.cpp:2203
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
Definition: CGExpr.cpp:2533
SmallVector< llvm::CanonicalLoopInfo *, 4 > OMPLoopNestStack
List of recently emitted OMPCanonicalLoops.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
llvm::AtomicRMWInst * emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Order=llvm::AtomicOrdering::SequentiallyConsistent, llvm::SyncScope::ID SSID=llvm::SyncScope::System, const AtomicExpr *AE=nullptr)
Emit an atomicrmw instruction, and applying relevant metadata when applicable.
Definition: CGAtomic.cpp:2082
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitOMPUseDevicePtrClause(const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
Definition: CGExpr.cpp:264
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
Definition: CGStmt.cpp:61
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPInnerLoop(const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond, const Expr *IncExpr, const llvm::function_ref< void(CodeGenFunction &)> BodyGen, const llvm::function_ref< void(CodeGenFunction &)> PostIncGen)
Emit inner loop of the worksharing/simd construct.
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
llvm::BasicBlock * OMPScanExitBlock
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
Definition: CGStmt.cpp:3335
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for lastprivate variables.
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
Definition: CGStmt.cpp:672
void EmitOMPSimdDirective(const OMPSimdDirective &S)
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...
Definition: CGExpr.cpp:186
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
Definition: CGExpr.cpp:2997
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
Definition: CGDecl.cpp:202
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
Definition: CGAtomic.cpp:1973
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
Definition: CGExpr.cpp:2183
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
Definition: CGStmt.cpp:3342
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
Definition: CGDecl.cpp:52
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
llvm::BasicBlock * OMPAfterScanBlock
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
Definition: CGExpr.cpp:1864
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
Definition: CGExpr.cpp:1631
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
Store of global named registers are always calls to intrinsics.
Definition: CGExpr.cpp:2839
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
void emitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, SourceLocation Loc, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue=nullptr)
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::function_ref< void(CodeGenFunction &, const OMPLoopDirective &, JumpDest)> CodeGenLoopTy
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...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
Definition: CGDecl.cpp:1808
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
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 EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
Definition: CGStmt.cpp:652
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
Definition: CGDecl.cpp:2093
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
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
CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const
Return the store size, in character units, of the given LLVM type.
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
llvm::Constant * GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition=NotForDefinition)
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
llvm::Constant * getStaticLocalDeclAddress(const VarDecl *D)
llvm::ConstantInt * getSize(CharUnits numChars)
Emit the given number of characters as a value of type size_t.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
Definition: CGCall.cpp:1702
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
Definition: CGCall.cpp:739
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
Definition: CGCall.h:375
LValue - This represents an lvalue references.
Definition: CGValue.h:182
llvm::Value * getPointer(CodeGenFunction &CGF) const
bool isVolatile() const
Definition: CGValue.h:328
bool isGlobalReg() const
Definition: CGValue.h:282
Address getAddress() const
Definition: CGValue.h:361
QualType getType() const
Definition: CGValue.h:291
void setAddress(Address address)
Definition: CGValue.h:363
A stack of loop information corresponding to loop nesting levels.
Definition: CGLoopInfo.h:207
void setUnrollCount(unsigned C)
Set the unroll count for the next loop pushed.
Definition: CGLoopInfo.h:282
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
Definition: CGLoopInfo.h:272
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
Definition: CGLoopInfo.h:242
void setUnrollState(const LoopAttributes::LVEnableState &State)
Set the next pushed loop unroll state.
Definition: CGLoopInfo.h:257
void pop()
End the current loop.
Definition: CGLoopInfo.cpp:828
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
void setVectorizeEnable(bool Enable=true)
Set the next pushed loop 'vectorize.enable'.
Definition: CGLoopInfo.h:245
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
Definition: CGValue.h:42
bool isScalar() const
Definition: CGValue.h:64
static RValue get(llvm::Value *V)
Definition: CGValue.h:98
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
Definition: CGValue.h:108
bool isAggregate() const
Definition: CGValue.h:66
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
Definition: CGValue.h:71
llvm::Value * second
Definition: CGValue.h:51
bool isComplex() const
Definition: CGValue.h:65
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
Definition: CGValue.h:78
An abstract representation of an aligned address.
Definition: Address.h:42
llvm::PointerType * getType() const
Return the type of the pointer value.
Definition: Address.h:72
llvm::Value * getPointer() const
Definition: Address.h:66
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void setAction(PrePostActionTy &Action) const
Complex values, per C99 6.2.5p11.
Definition: TypeBase.h:3293
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1720
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:196
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2109
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1272
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition: Expr.cpp:484
ValueDecl * getDecl()
Definition: Expr.h:1340
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1611
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
SourceLocation getEndLoc() const LLVM_READONLY
Definition: DeclBase.h:435
T * getAttr() const
Definition: DeclBase.h:573
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:1087
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
Definition: DeclBase.cpp:1076
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
Definition: DeclBase.h:1093
SourceLocation getLocation() const
Definition: DeclBase.h:439
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:431
bool hasAttr() const
Definition: DeclBase.h:577
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:978
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:830
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1529
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition: Diagnostic.h:904
This represents one expression.
Definition: Expr.h:112
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3073
Expr * IgnoreImplicitAsWritten() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3065
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3053
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:273
QualType getType() const
Definition: Expr.h:144
Represents difference between two FPOptions values.
Definition: LangOptions.h:919
Represents a member of a struct/union/class.
Definition: Decl.h:3157
Represents a function declaration or definition.
Definition: Decl.h:1999
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
Definition: Decl.h:2188
GlobalDecl - represents a global declaration.
Definition: GlobalDecl.h:57
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition: Expr.cpp:2068
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Definition: Decl.cpp:5470
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
Definition: ExprCXX.h:1970
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
Definition: LangOptions.h:508
Represents a point when we exit a loop.
Definition: ProgramPoint.h:721
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:294
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:300
A C++ nested-name-specifier augmented with source location information.
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
This represents clause 'aligned' in the '#pragma omp ...' directives.
This represents '#pragma omp atomic' directive.
Definition: StmtOpenMP.h:2947
This represents '#pragma omp barrier' directive.
Definition: StmtOpenMP.h:2625
This represents 'bind' clause in the '#pragma omp ...' directives.
This represents '#pragma omp cancel' directive.
Definition: StmtOpenMP.h:3655
This represents '#pragma omp cancellation point' directive.
Definition: StmtOpenMP.h:3597
Representation of an OpenMP canonical loop.
Definition: StmtOpenMP.h:142
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:55
This represents clause 'copyin' in the '#pragma omp ...' directives.
This represents clause 'copyprivate' in the '#pragma omp ...' directives.
This represents '#pragma omp critical' directive.
Definition: StmtOpenMP.h:2076
This represents implicit clause 'depend' for the '#pragma omp task' directive.
This represents implicit clause 'depobj' for the '#pragma omp depobj' directive.
This represents '#pragma omp depobj' directive.
Definition: StmtOpenMP.h:2841
This represents 'destroy' clause in the '#pragma omp depobj' directive or the '#pragma omp interop' d...
This represents 'device' clause in the '#pragma omp ...' directive.
This represents 'dist_schedule' clause in the '#pragma omp ...' directive.
This represents '#pragma omp distribute' directive.
Definition: StmtOpenMP.h:4425
This represents '#pragma omp distribute parallel for' composite directive.
Definition: StmtOpenMP.h:4547
This represents '#pragma omp distribute parallel for simd' composite directive.
Definition: StmtOpenMP.h:4643
This represents '#pragma omp distribute simd' composite directive.
Definition: StmtOpenMP.h:4708
This represents the 'doacross' clause for the '#pragma omp ordered' directive.
This represents '#pragma omp error' directive.
Definition: StmtOpenMP.h:6514
This is a basic class for representing single OpenMP executable directive.
Definition: StmtOpenMP.h:266
OpenMPDirectiveKind getDirectiveKind() const
Definition: StmtOpenMP.h:555
SourceLocation getEndLoc() const
Returns ending location of directive.
Definition: StmtOpenMP.h:490
static llvm::iterator_range< specific_clause_iterator< SpecificClause > > getClausesOfKind(ArrayRef< OMPClause * > Clauses)
Definition: StmtOpenMP.h:445
This represents 'fail' clause in the '#pragma omp atomic' directive.
OpenMPClauseKind getFailParameter() const
Gets the parameter (type memory-order-clause) in Fail clause.
This represents 'filter' clause in the '#pragma omp ...' directive.
This represents 'final' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:779
This represents clause 'firstprivate' in the '#pragma omp ...' directives.
This represents implicit clause 'flush' for the '#pragma omp flush' directive.
This represents '#pragma omp flush' directive.
Definition: StmtOpenMP.h:2789
This represents '#pragma omp for' directive.
Definition: StmtOpenMP.h:1634
This represents '#pragma omp for simd' directive.
Definition: StmtOpenMP.h:1724
Representation of the 'full' clause of the '#pragma omp unroll' directive.
This represents '#pragma omp loop' directive.
Definition: StmtOpenMP.h:6185
This represents 'grainsize' clause in the '#pragma omp ...' directive.
This represents 'hint' clause in the '#pragma omp ...' directive.
This represents 'if' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:676
This represents clause 'in_reduction' in the '#pragma omp task' directives.
This represents clause 'inclusive' in the '#pragma omp scan' directive.
This represents the 'init' clause in '#pragma omp ...' directives.
Represents the '#pragma omp interchange' loop transformation directive.
Definition: StmtOpenMP.h:5851
This represents '#pragma omp interop' directive.
Definition: StmtOpenMP.h:5977
This represents clause 'lastprivate' in the '#pragma omp ...' directives.
This represents clause 'linear' in the '#pragma omp ...' directives.
The base class for all loop-based directives, including loop transformation directives.
Definition: StmtOpenMP.h:682
static Stmt * tryToFindNextInnerLoop(Stmt *CurStmt, bool TryImperfectlyNestedLoops)
Try to find the next loop sub-statement in the specified statement CurStmt.
Definition: StmtOpenMP.cpp:78
static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref< bool(unsigned, Stmt *)> Callback, llvm::function_ref< void(OMPLoopTransformationDirective *)> OnTransformationCallback)
Calls the specified callback function for all the loops in CurStmt, from the outermost to the innermo...
Definition: StmtOpenMP.cpp:125
This is a common base class for loop directives ('omp simd', 'omp for', 'omp for simd' etc....
Definition: StmtOpenMP.h:1004
Expr * getPrevUpperBoundVariable() const
Definition: StmtOpenMP.h:1407
Expr * getPrevLowerBoundVariable() const
Definition: StmtOpenMP.h:1402
Expr * getIterationVariable() const
Definition: StmtOpenMP.h:1319
Expr * getUpperBoundVariable() const
Definition: StmtOpenMP.h:1354
Expr * getLowerBoundVariable() const
Definition: StmtOpenMP.h:1346
This represents '#pragma omp masked' directive.
Definition: StmtOpenMP.h:6095
This represents '#pragma omp masked taskloop' directive.
Definition: StmtOpenMP.h:3930
This represents '#pragma omp masked taskloop simd' directive.
Definition: StmtOpenMP.h:4071
This represents '#pragma omp master' directive.
Definition: StmtOpenMP.h:2028
This represents '#pragma omp master taskloop' directive.
Definition: StmtOpenMP.h:3854
This represents '#pragma omp master taskloop simd' directive.
Definition: StmtOpenMP.h:4006
This represents the 'message' clause in the '#pragma omp error' and the '#pragma omp parallel' direct...
Expr * getMessageString() const
Returns message string of the clause.
This represents '#pragma omp metadirective' directive.
Definition: StmtOpenMP.h:6146
This represents 'nogroup' clause in the '#pragma omp ...' directive.
This represents 'nowait' clause in the '#pragma omp ...' directive.
This represents 'num_tasks' clause in the '#pragma omp ...' directive.
This represents 'num_teams' clause in the '#pragma omp ...' directive.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:825
This represents 'order' clause in the '#pragma omp ...' directive.
This represents 'ordered' clause in the '#pragma omp ...' directive.
This represents '#pragma omp ordered' directive.
Definition: StmtOpenMP.h:2893
This represents '#pragma omp parallel' directive.
Definition: StmtOpenMP.h:611
This represents '#pragma omp parallel for' directive.
Definition: StmtOpenMP.h:2147
This represents '#pragma omp parallel for simd' directive.
Definition: StmtOpenMP.h:2244
This represents '#pragma omp parallel masked' directive.
Definition: StmtOpenMP.h:2372
This represents '#pragma omp parallel masked taskloop' directive.
Definition: StmtOpenMP.h:4215
This represents '#pragma omp parallel masked taskloop simd' directive.
Definition: StmtOpenMP.h:4360
This represents '#pragma omp parallel master' directive.
Definition: StmtOpenMP.h:2309
This represents '#pragma omp parallel master taskloop' directive.
Definition: StmtOpenMP.h:4137
This represents '#pragma omp parallel master taskloop simd' directive.
Definition: StmtOpenMP.h:4293
This represents '#pragma omp parallel sections' directive.
Definition: StmtOpenMP.h:2436
Representation of the 'partial' clause of the '#pragma omp unroll' directive.
This represents 'priority' clause in the '#pragma omp ...' directive.
This represents clause 'private' in the '#pragma omp ...' directives.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
This represents clause 'reduction' in the '#pragma omp ...' directives.
This represents 'relaxed' clause in the '#pragma omp atomic' directives.
This represents 'release' clause in the '#pragma omp atomic|flush' directives.
Represents the '#pragma omp reverse' loop transformation directive.
Definition: StmtOpenMP.h:5779
This represents 'simd' clause in the '#pragma omp ...' directive.
This represents 'safelen' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:891
This represents '#pragma omp scan' directive.
Definition: StmtOpenMP.h:5924
This represents 'schedule' clause in the '#pragma omp ...' directive.
This represents '#pragma omp scope' directive.
Definition: StmtOpenMP.h:1925
This represents '#pragma omp section' directive.
Definition: StmtOpenMP.h:1864
This represents '#pragma omp sections' directive.
Definition: StmtOpenMP.h:1787
This represents 'seq_cst' clause in the '#pragma omp atomic|flush' directives.
This represents the 'severity' clause in the '#pragma omp error' and the '#pragma omp parallel' direc...
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
This represents '#pragma omp simd' directive.
Definition: StmtOpenMP.h:1571
This represents 'simdlen' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:926
This represents '#pragma omp single' directive.
Definition: StmtOpenMP.h:1977
This represents the '#pragma omp stripe' loop transformation directive.
Definition: StmtOpenMP.h:5625
This represents '#pragma omp target data' directive.
Definition: StmtOpenMP.h:3206
This represents '#pragma omp target' directive.
Definition: StmtOpenMP.h:3152
This represents '#pragma omp target enter data' directive.
Definition: StmtOpenMP.h:3260
This represents '#pragma omp target exit data' directive.
Definition: StmtOpenMP.h:3315
This represents '#pragma omp target parallel' directive.
Definition: StmtOpenMP.h:3369
This represents '#pragma omp target parallel for' directive.
Definition: StmtOpenMP.h:3449
This represents '#pragma omp target parallel for simd' directive.
Definition: StmtOpenMP.h:4774
This represents '#pragma omp target parallel loop' directive.
Definition: StmtOpenMP.h:6452
This represents '#pragma omp target simd' directive.
Definition: StmtOpenMP.h:4841
This represents '#pragma omp target teams' directive.
Definition: StmtOpenMP.h:5199
This represents '#pragma omp target teams distribute' combined directive.
Definition: StmtOpenMP.h:5255
This represents '#pragma omp target teams distribute parallel for' combined directive.
Definition: StmtOpenMP.h:5322
This represents '#pragma omp target teams distribute parallel for simd' combined directive.
Definition: StmtOpenMP.h:5420
This represents '#pragma omp target teams distribute simd' combined directive.
Definition: StmtOpenMP.h:5490
This represents '#pragma omp target teams loop' directive.
Definition: StmtOpenMP.h:6312
This represents '#pragma omp target update' directive.
Definition: StmtOpenMP.h:4491
This represents '#pragma omp task' directive.
Definition: StmtOpenMP.h:2517
This represents '#pragma omp taskloop' directive.
Definition: StmtOpenMP.h:3715
This represents '#pragma omp taskloop simd' directive.
Definition: StmtOpenMP.h:3788
This represents clause 'task_reduction' in the '#pragma omp taskgroup' directives.
This represents '#pragma omp taskgroup' directive.
Definition: StmtOpenMP.h:2722
This represents '#pragma omp taskwait' directive.
Definition: StmtOpenMP.h:2671
This represents '#pragma omp taskyield' directive.
Definition: StmtOpenMP.h:2579
This represents '#pragma omp teams' directive.
Definition: StmtOpenMP.h:3544
This represents '#pragma omp teams distribute' directive.
Definition: StmtOpenMP.h:4906
This represents '#pragma omp teams distribute parallel for' composite directive.
Definition: StmtOpenMP.h:5106
This represents '#pragma omp teams distribute parallel for simd' composite directive.
Definition: StmtOpenMP.h:5040
This represents '#pragma omp teams distribute simd' combined directive.
Definition: StmtOpenMP.h:4972
This represents '#pragma omp teams loop' directive.
Definition: StmtOpenMP.h:6247
This represents 'thread_limit' clause in the '#pragma omp ...' directive.
This represents the '#pragma omp tile' loop transformation directive.
Definition: StmtOpenMP.h:5548
This represents the '#pragma omp unroll' loop transformation directive.
Definition: StmtOpenMP.h:5705
This represents 'untied' clause in the '#pragma omp ...' directive.
This represents 'update' clause in the '#pragma omp atomic' directive.
This represents the 'use' clause in '#pragma omp ...' directives.
This represents clause 'use_device_addr' in the '#pragma omp ...' directives.
This represents clause 'use_device_ptr' in the '#pragma omp ...' directives.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1180
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition: Decl.cpp:2946
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: TypeBase.h:3346
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
bool isValid() const
unsigned getLine() const
Return the presumed line number of this location.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition: TypeBase.h:8427
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: TypeBase.h:8528
Represents a struct/union/class.
Definition: Decl.h:4309
field_range fields() const
Definition: Decl.h:4512
field_iterator field_begin() const
Definition: Decl.cpp:5154
Base for LValueReferenceType and RValueReferenceType.
Definition: TypeBase.h:3589
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
Definition: Stmt.h:85
child_range children()
Definition: Stmt.cpp:295
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:346
SwitchStmt - This represents a 'switch' stmt.
Definition: Stmt.h:2509
virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits, uint64_t AlignmentInBits) const
Returns true if the given target supports lock-free atomic operations at the specified width and alig...
Definition: TargetInfo.h:859
bool isTLSSupported() const
Whether the target supports thread-local storage.
Definition: TargetInfo.h:1616
The base class of the type hierarchy.
Definition: TypeBase.h:1833
bool isArrayType() const
Definition: TypeBase.h:8679
bool isPointerType() const
Definition: TypeBase.h:8580
const T * castAs() const
Member-template castAs<specific type>.
Definition: TypeBase.h:9226
bool isReferenceType() const
Definition: TypeBase.h:8604
bool isScalarType() const
Definition: TypeBase.h:9038
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
bool isLValueReferenceType() const
Definition: TypeBase.h:8608
bool isAnyComplexType() const
Definition: TypeBase.h:8715
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2247
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition: TypeBase.h:2818
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: TypeBase.h:9212
bool isAnyPointerType() const
Definition: TypeBase.h:8588
bool isRecordType() const
Definition: TypeBase.h:8707
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2246
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Definition: Expr.cpp:4995
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:711
QualType getType() const
Definition: Decl.h:722
Represents a variable declaration or definition.
Definition: Decl.h:925
TLSKind getTLSKind() const
Definition: Decl.cpp:2168
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:2257
@ CInit
C-style initialization with assignment.
Definition: Decl.h:930
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1225
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition: Decl.h:1207
const Expr * getInit() const
Definition: Decl.h:1367
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1183
@ TLS_None
Not a TLS variable.
Definition: Decl.h:945
Represents a C array with a specified size that is not an integer-constant-expression.
Definition: TypeBase.h:3982
Expr * getSizeExpr() const
Definition: TypeBase.h:3996
Definition: SPIR.cpp:35
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
Definition: Interp.h:865
CharSourceRange getSourceRange(const SourceRange &Range)
Returns the token CharSourceRange corresponding to Range.
Definition: FixIt.h:32
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
Definition: ABI.h:25
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:25
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:151
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
BinaryOperatorKind
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition: OpenMPKinds.h:39
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition: OpenMPKinds.h:40
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:28
@ CR_OpenMP
Definition: CapturedStmt.h:19
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
@ SC_Static
Definition: Specifiers.h:252
@ SC_None
Definition: Specifiers.h:250
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
Definition: OpenMPKinds.h:104
@ OMPC_DIST_SCHEDULE_unknown
Definition: OpenMPKinds.h:107
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
Definition: OpenMPKinds.h:208
@ OMPC_BIND_unknown
Definition: OpenMPKinds.h:211
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition: OpenMPKinds.h:55
@ Dtor_Complete
Complete object dtor.
Definition: ABI.h:35
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
Definition: OpenMPKinds.h:143
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
Definition: OpenMPKinds.h:226
@ OMPC_NUMTHREADS_unknown
Definition: OpenMPKinds.h:229
@ OMPC_DEVICE_unknown
Definition: OpenMPKinds.h:51
@ ThreadPrivateVar
Parameter for Thread private variable.
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Definition: OpenMPKinds.h:31
@ OMPC_SCHEDULE_unknown
Definition: OpenMPKinds.h:35
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
struct with the values to be passed to the dispatch runtime function
llvm::Value * Chunk
Chunk size specified using 'schedule' clause (nullptr if chunk was not specified)
Struct with the values to be passed to the static runtime function.
QualType getType() const
Definition: CGCall.h:248
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
static Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
llvm::OpenMPIRBuilder::InsertPointTy InsertPointTy
static void EmitOMPOutlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region that will be outlined in OpenMPIRBuilder::finalize().
static Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable /p VD.
static void EmitCaptureStmt(CodeGenFunction &CGF, InsertPointTy CodeGenIP, llvm::BasicBlock &FiniBB, llvm::Function *Fn, ArrayRef< llvm::Value * > Args)
static std::string getNameWithSeparators(ArrayRef< StringRef > Parts, StringRef FirstSeparator=".", StringRef Separator=".")
Get the platform-specific name separator.
static void FinalizeOMPRegion(CodeGenFunction &CGF, InsertPointTy IP)
Emit the Finalization for an OMP region.
static void EmitOMPInlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region.
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:645
Extra information about a function prototype.
Definition: TypeBase.h:5367
Scheduling data for loop-based OpenMP directives.
Definition: OpenMPKinds.h:180
OpenMPScheduleClauseModifier M2
Definition: OpenMPKinds.h:183
OpenMPScheduleClauseModifier M1
Definition: OpenMPKinds.h:182
OpenMPScheduleClauseKind Schedule
Definition: OpenMPKinds.h:181