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