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