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