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 AllocaIP,
2126 InsertPointTy CodeGenIP) {
2128 *this, ParallelRegionBodyStmt, AllocaIP, 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 = cantFail(
2137 OMPBuilder.createParallel(Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
2138 IfCond, NumThreads, ProcBind, S.hasCancel()));
2139 Builder.restoreIP(AfterIP);
2140 return;
2141 }
2142
2143 // Emit parallel region as a standalone region.
2144 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2145 Action.Enter(CGF);
2146 OMPPrivateScope PrivateScope(CGF);
2147 emitOMPCopyinClause(CGF, S);
2148 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
2149 CGF.EmitOMPPrivateClause(S, PrivateScope);
2150 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
2151 (void)PrivateScope.Privatize();
2152 CGF.EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2153 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
2154 };
2155 {
2156 auto LPCRegion =
2158 emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen,
2161 [](CodeGenFunction &) { return nullptr; });
2162 }
2163 // Check for outer lastprivate conditional update.
2165}
2166
2170
2171namespace {
2172/// RAII to handle scopes for loop transformation directives.
2173class OMPTransformDirectiveScopeRAII {
2174 OMPLoopScope *Scope = nullptr;
2176 CodeGenFunction::CGCapturedStmtRAII *CapInfoRAII = nullptr;
2177
2178 OMPTransformDirectiveScopeRAII(const OMPTransformDirectiveScopeRAII &) =
2179 delete;
2180 OMPTransformDirectiveScopeRAII &
2181 operator=(const OMPTransformDirectiveScopeRAII &) = delete;
2182
2183public:
2184 OMPTransformDirectiveScopeRAII(CodeGenFunction &CGF, const Stmt *S) {
2185 if (const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2186 Scope = new OMPLoopScope(CGF, *Dir);
2188 CapInfoRAII = new CodeGenFunction::CGCapturedStmtRAII(CGF, CGSI);
2189 } else if (const auto *Dir =
2190 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2191 S)) {
2192 // For simplicity we reuse the loop scope similarly to what we do with
2193 // OMPCanonicalLoopNestTransformationDirective do by being a subclass
2194 // of OMPLoopBasedDirective.
2195 Scope = new OMPLoopScope(CGF, *Dir);
2197 CapInfoRAII = new CodeGenFunction::CGCapturedStmtRAII(CGF, CGSI);
2198 }
2199 }
2200 ~OMPTransformDirectiveScopeRAII() {
2201 if (!Scope)
2202 return;
2203 delete CapInfoRAII;
2204 delete CGSI;
2205 delete Scope;
2206 }
2207};
2208} // namespace
2209
2210static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop,
2211 int MaxLevel, int Level = 0) {
2212 assert(Level < MaxLevel && "Too deep lookup during loop body codegen.");
2213 const Stmt *SimplifiedS = S->IgnoreContainers();
2214 if (const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2215 PrettyStackTraceLoc CrashInfo(
2216 CGF.getContext().getSourceManager(), CS->getLBracLoc(),
2217 "LLVM IR generation of compound statement ('{}')");
2218
2219 // Keep track of the current cleanup stack depth, including debug scopes.
2221 for (const Stmt *CurStmt : CS->body())
2222 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2223 return;
2224 }
2225 if (SimplifiedS == NextLoop) {
2226 if (auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2227 SimplifiedS = Dir->getTransformedStmt();
2228 if (const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2229 SimplifiedS = CanonLoop->getLoopStmt();
2230 if (const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2231 S = For->getBody();
2232 } else {
2233 assert(isa<CXXForRangeStmt>(SimplifiedS) &&
2234 "Expected canonical for loop or range-based for loop.");
2235 const auto *CXXFor = cast<CXXForRangeStmt>(SimplifiedS);
2236 CGF.EmitStmt(CXXFor->getLoopVarStmt());
2237 S = CXXFor->getBody();
2238 }
2239 if (Level + 1 < MaxLevel) {
2240 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2241 S, /*TryImperfectlyNestedLoops=*/true);
2242 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2243 return;
2244 }
2245 }
2246 CGF.EmitStmt(S);
2247}
2248
2251 RunCleanupsScope BodyScope(*this);
2252 // Update counters values on current iteration.
2253 for (const Expr *UE : D.updates())
2254 EmitIgnoredExpr(UE);
2255 // Update the linear variables.
2256 // In distribute directives only loop counters may be marked as linear, no
2257 // need to generate the code for them.
2259 if (!isOpenMPDistributeDirective(EKind)) {
2260 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
2261 for (const Expr *UE : C->updates())
2262 EmitIgnoredExpr(UE);
2263 }
2264 }
2265
2266 // On a continue in the body, jump to the end.
2267 JumpDest Continue = getJumpDestInCurrentScope("omp.body.continue");
2268 BreakContinueStack.push_back(BreakContinue(D, LoopExit, Continue));
2269 for (const Expr *E : D.finals_conditions()) {
2270 if (!E)
2271 continue;
2272 // Check that loop counter in non-rectangular nest fits into the iteration
2273 // space.
2274 llvm::BasicBlock *NextBB = createBasicBlock("omp.body.next");
2275 EmitBranchOnBoolExpr(E, NextBB, Continue.getBlock(),
2276 getProfileCount(D.getBody()));
2277 EmitBlock(NextBB);
2278 }
2279
2280 OMPPrivateScope InscanScope(*this);
2281 EmitOMPReductionClauseInit(D, InscanScope, /*ForInscan=*/true);
2282 bool IsInscanRegion = InscanScope.Privatize();
2283 if (IsInscanRegion) {
2284 // Need to remember the block before and after scan directive
2285 // to dispatch them correctly depending on the clause used in
2286 // this directive, inclusive or exclusive. For inclusive scan the natural
2287 // order of the blocks is used, for exclusive clause the blocks must be
2288 // executed in reverse order.
2289 OMPBeforeScanBlock = createBasicBlock("omp.before.scan.bb");
2290 OMPAfterScanBlock = createBasicBlock("omp.after.scan.bb");
2291 // No need to allocate inscan exit block, in simd mode it is selected in the
2292 // codegen for the scan directive.
2293 if (EKind != OMPD_simd && !getLangOpts().OpenMPSimd)
2294 OMPScanExitBlock = createBasicBlock("omp.exit.inscan.bb");
2295 OMPScanDispatch = createBasicBlock("omp.inscan.dispatch");
2298 }
2299
2300 // Emit loop variables for C++ range loops.
2301 const Stmt *Body =
2302 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2303 // Emit loop body.
2304 emitBody(*this, Body,
2305 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2306 Body, /*TryImperfectlyNestedLoops=*/true),
2307 D.getLoopsNumber());
2308
2309 // Jump to the dispatcher at the end of the loop body.
2310 if (IsInscanRegion)
2312
2313 // The end (updates/cleanups).
2314 EmitBlock(Continue.getBlock());
2315 BreakContinueStack.pop_back();
2316}
2317
2318using EmittedClosureTy = std::pair<llvm::Function *, llvm::Value *>;
2319
2320/// Emit a captured statement and return the function as well as its captured
2321/// closure context.
2323 const CapturedStmt *S) {
2324 LValue CapStruct = ParentCGF.InitCapturedStruct(*S);
2325 CodeGenFunction CGF(ParentCGF.CGM, /*suppressNewContext=*/true);
2326 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2327 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2328 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, CSI.get());
2329 llvm::Function *F = CGF.GenerateCapturedStmtFunction(*S);
2330
2331 return {F, CapStruct.getPointer(ParentCGF)};
2332}
2333
2334/// Emit a call to a previously captured closure.
2335static llvm::CallInst *
2338 // Append the closure context to the argument.
2339 SmallVector<llvm::Value *> EffectiveArgs;
2340 EffectiveArgs.reserve(Args.size() + 1);
2341 llvm::append_range(EffectiveArgs, Args);
2342 EffectiveArgs.push_back(Cap.second);
2343
2344 return ParentCGF.Builder.CreateCall(Cap.first, EffectiveArgs);
2345}
2346
2347llvm::CanonicalLoopInfo *
2349 assert(Depth == 1 && "Nested loops with OpenMPIRBuilder not yet implemented");
2350
2351 // The caller is processing the loop-associated directive processing the \p
2352 // Depth loops nested in \p S. Put the previous pending loop-associated
2353 // directive to the stack. If the current loop-associated directive is a loop
2354 // transformation directive, it will push its generated loops onto the stack
2355 // such that together with the loops left here they form the combined loop
2356 // nest for the parent loop-associated directive.
2357 int ParentExpectedOMPLoopDepth = ExpectedOMPLoopDepth;
2358 ExpectedOMPLoopDepth = Depth;
2359
2360 EmitStmt(S);
2361 assert(OMPLoopNestStack.size() >= (size_t)Depth && "Found too few loops");
2362
2363 // The last added loop is the outermost one.
2364 llvm::CanonicalLoopInfo *Result = OMPLoopNestStack.back();
2365
2366 // Pop the \p Depth loops requested by the call from that stack and restore
2367 // the previous context.
2368 OMPLoopNestStack.pop_back_n(Depth);
2369 ExpectedOMPLoopDepth = ParentExpectedOMPLoopDepth;
2370
2371 return Result;
2372}
2373
2374void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) {
2375 const Stmt *SyntacticalLoop = S->getLoopStmt();
2376 if (!getLangOpts().OpenMPIRBuilder) {
2377 // Ignore if OpenMPIRBuilder is not enabled.
2378 EmitStmt(SyntacticalLoop);
2379 return;
2380 }
2381
2382 LexicalScope ForScope(*this, S->getSourceRange());
2383
2384 // Emit init statements. The Distance/LoopVar funcs may reference variable
2385 // declarations they contain.
2386 const Stmt *BodyStmt;
2387 if (const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2388 if (const Stmt *InitStmt = For->getInit())
2389 EmitStmt(InitStmt);
2390 BodyStmt = For->getBody();
2391 } else if (const auto *RangeFor =
2392 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2393 if (const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2394 EmitStmt(RangeStmt);
2395 if (const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2396 EmitStmt(BeginStmt);
2397 if (const DeclStmt *EndStmt = RangeFor->getEndStmt())
2398 EmitStmt(EndStmt);
2399 if (const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2400 EmitStmt(LoopVarStmt);
2401 BodyStmt = RangeFor->getBody();
2402 } else
2403 llvm_unreachable("Expected for-stmt or range-based for-stmt");
2404
2405 // Emit closure for later use. By-value captures will be captured here.
2406 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2407 EmittedClosureTy DistanceClosure = emitCapturedStmtFunc(*this, DistanceFunc);
2408 const CapturedStmt *LoopVarFunc = S->getLoopVarFunc();
2409 EmittedClosureTy LoopVarClosure = emitCapturedStmtFunc(*this, LoopVarFunc);
2410
2411 // Call the distance function to get the number of iterations of the loop to
2412 // come.
2413 QualType LogicalTy = DistanceFunc->getCapturedDecl()
2414 ->getParam(0)
2415 ->getType()
2417 RawAddress CountAddr = CreateMemTemp(LogicalTy, ".count.addr");
2418 emitCapturedStmtCall(*this, DistanceClosure, {CountAddr.getPointer()});
2419 llvm::Value *DistVal = Builder.CreateLoad(CountAddr, ".count");
2420
2421 // Emit the loop structure.
2422 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
2423 auto BodyGen = [&, this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2424 llvm::Value *IndVar) {
2425 Builder.restoreIP(CodeGenIP);
2426
2427 // Emit the loop body: Convert the logical iteration number to the loop
2428 // variable and emit the body.
2429 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2430 LValue LCVal = EmitLValue(LoopVarRef);
2431 Address LoopVarAddress = LCVal.getAddress();
2432 emitCapturedStmtCall(*this, LoopVarClosure,
2433 {LoopVarAddress.emitRawPointer(*this), IndVar});
2434
2435 RunCleanupsScope BodyScope(*this);
2436 EmitStmt(BodyStmt);
2437 return llvm::Error::success();
2438 };
2439
2440 llvm::CanonicalLoopInfo *CL =
2441 cantFail(OMPBuilder.createCanonicalLoop(Builder, BodyGen, DistVal));
2442
2443 // Finish up the loop.
2444 Builder.restoreIP(CL->getAfterIP());
2445 ForScope.ForceCleanup();
2446
2447 // Remember the CanonicalLoopInfo for parent AST nodes consuming it.
2448 OMPLoopNestStack.push_back(CL);
2449}
2450
2452 const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond,
2453 const Expr *IncExpr,
2454 const llvm::function_ref<void(CodeGenFunction &)> BodyGen,
2455 const llvm::function_ref<void(CodeGenFunction &)> PostIncGen) {
2456 auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
2457
2458 // Start the loop with a block that tests the condition.
2459 auto CondBlock = createBasicBlock("omp.inner.for.cond");
2460 EmitBlock(CondBlock);
2461 const SourceRange R = S.getSourceRange();
2462
2463 // If attributes are attached, push to the basic block with them.
2464 const auto &OMPED = cast<OMPExecutableDirective>(S);
2465 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2466 const Stmt *SS = ICS->getCapturedStmt();
2467 const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(SS);
2468 OMPLoopNestStack.clear();
2469 if (AS)
2470 LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(),
2471 AS->getAttrs(), SourceLocToDebugLoc(R.getBegin()),
2472 SourceLocToDebugLoc(R.getEnd()));
2473 else
2474 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
2475 SourceLocToDebugLoc(R.getEnd()));
2476
2477 // If there are any cleanups between here and the loop-exit scope,
2478 // create a block to stage a loop exit along.
2479 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
2480 if (RequiresCleanup)
2481 ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
2482
2483 llvm::BasicBlock *LoopBody = createBasicBlock("omp.inner.for.body");
2484
2485 // Emit condition.
2486 EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S));
2487 if (ExitBlock != LoopExit.getBlock()) {
2488 EmitBlock(ExitBlock);
2490 }
2491
2492 EmitBlock(LoopBody);
2494
2495 // Create a block for the increment.
2496 JumpDest Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
2497 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
2498
2499 BodyGen(*this);
2500
2501 // Emit "IV = IV + 1" and a back-edge to the condition block.
2502 EmitBlock(Continue.getBlock());
2503 EmitIgnoredExpr(IncExpr);
2504 PostIncGen(*this);
2505 BreakContinueStack.pop_back();
2506 EmitBranch(CondBlock);
2507 LoopStack.pop();
2508 // Emit the fall-through block.
2509 EmitBlock(LoopExit.getBlock());
2510}
2511
2513 if (!HaveInsertPoint())
2514 return false;
2515 // Emit inits for the linear variables.
2516 bool HasLinears = false;
2517 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
2518 for (const Expr *Init : C->inits()) {
2519 HasLinears = true;
2520 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
2521 if (const auto *Ref =
2522 dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) {
2523 AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
2524 const auto *OrigVD = cast<VarDecl>(Ref->getDecl());
2525 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
2526 CapturedStmtInfo->lookup(OrigVD) != nullptr,
2527 VD->getInit()->getType(), VK_LValue,
2528 VD->getInit()->getExprLoc());
2530 &DRE, VD,
2531 MakeAddrLValue(Emission.getAllocatedAddress(), VD->getType()),
2532 /*capturedByInit=*/false);
2533 EmitAutoVarCleanups(Emission);
2534 } else {
2535 EmitVarDecl(*VD);
2536 }
2537 }
2538 // Emit the linear steps for the linear clauses.
2539 // If a step is not constant, it is pre-calculated before the loop.
2540 if (const auto *CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
2541 if (const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
2542 EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
2543 // Emit calculation of the linear step.
2544 EmitIgnoredExpr(CS);
2545 }
2546 }
2547 return HasLinears;
2548}
2549
2551 const OMPLoopDirective &D,
2552 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2553 if (!HaveInsertPoint())
2554 return;
2555 llvm::BasicBlock *DoneBB = nullptr;
2556 // Emit the final values of the linear variables.
2557 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
2558 auto IC = C->varlist_begin();
2559 for (const Expr *F : C->finals()) {
2560 if (!DoneBB) {
2561 if (llvm::Value *Cond = CondGen(*this)) {
2562 // If the first post-update expression is found, emit conditional
2563 // block if it was requested.
2564 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.linear.pu");
2565 DoneBB = createBasicBlock(".omp.linear.pu.done");
2566 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2567 EmitBlock(ThenBB);
2568 }
2569 }
2570 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
2571 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
2572 CapturedStmtInfo->lookup(OrigVD) != nullptr,
2573 (*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
2574 Address OrigAddr = EmitLValue(&DRE).getAddress();
2575 CodeGenFunction::OMPPrivateScope VarScope(*this);
2576 VarScope.addPrivate(OrigVD, OrigAddr);
2577 (void)VarScope.Privatize();
2578 EmitIgnoredExpr(F);
2579 ++IC;
2580 }
2581 if (const Expr *PostUpdate = C->getPostUpdateExpr())
2582 EmitIgnoredExpr(PostUpdate);
2583 }
2584 if (DoneBB)
2585 EmitBlock(DoneBB, /*IsFinished=*/true);
2586}
2587
2589 const OMPExecutableDirective &D) {
2590 if (!CGF.HaveInsertPoint())
2591 return;
2592 for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) {
2593 llvm::APInt ClauseAlignment(64, 0);
2594 if (const Expr *AlignmentExpr = Clause->getAlignment()) {
2595 auto *AlignmentCI =
2596 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
2597 ClauseAlignment = AlignmentCI->getValue();
2598 }
2599 for (const Expr *E : Clause->varlist()) {
2600 llvm::APInt Alignment(ClauseAlignment);
2601 if (Alignment == 0) {
2602 // OpenMP [2.8.1, Description]
2603 // If no optional parameter is specified, implementation-defined default
2604 // alignments for SIMD instructions on the target platforms are assumed.
2605 Alignment =
2606 CGF.getContext()
2608 E->getType()->getPointeeType()))
2609 .getQuantity();
2610 }
2611 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2612 "alignment is not power of 2");
2613 if (Alignment != 0) {
2614 llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
2616 PtrValue, E, /*No second loc needed*/ SourceLocation(),
2617 llvm::ConstantInt::get(CGF.getLLVMContext(), Alignment));
2618 }
2619 }
2620 }
2621}
2622
2625 if (!HaveInsertPoint())
2626 return;
2627 auto I = S.private_counters().begin();
2628 for (const Expr *E : S.counters()) {
2629 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2630 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
2631 // Emit var without initialization.
2632 AutoVarEmission VarEmission = EmitAutoVarAlloca(*PrivateVD);
2633 EmitAutoVarCleanups(VarEmission);
2634 LocalDeclMap.erase(PrivateVD);
2635 (void)LoopScope.addPrivate(VD, VarEmission.getAllocatedAddress());
2636 if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) ||
2637 VD->hasGlobalStorage()) {
2638 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD),
2639 LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD),
2640 E->getType(), VK_LValue, E->getExprLoc());
2641 (void)LoopScope.addPrivate(PrivateVD, EmitLValue(&DRE).getAddress());
2642 } else {
2643 (void)LoopScope.addPrivate(PrivateVD, VarEmission.getAllocatedAddress());
2644 }
2645 ++I;
2646 }
2647 // Privatize extra loop counters used in loops for ordered(n) clauses.
2648 for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) {
2649 if (!C->getNumForLoops())
2650 continue;
2651 for (unsigned I = S.getLoopsNumber(), E = C->getLoopNumIterations().size();
2652 I < E; ++I) {
2653 const auto *DRE = cast<DeclRefExpr>(C->getLoopCounter(I));
2654 const auto *VD = cast<VarDecl>(DRE->getDecl());
2655 // Override only those variables that can be captured to avoid re-emission
2656 // of the variables declared within the loops.
2657 if (DRE->refersToEnclosingVariableOrCapture()) {
2658 (void)LoopScope.addPrivate(
2659 VD, CreateMemTemp(DRE->getType(), VD->getName()));
2660 }
2661 }
2662 }
2663}
2664
2666 const Expr *Cond, llvm::BasicBlock *TrueBlock,
2667 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2668 if (!CGF.HaveInsertPoint())
2669 return;
2670 {
2671 CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
2672 CGF.EmitOMPPrivateLoopCounters(S, PreCondScope);
2673 (void)PreCondScope.Privatize();
2674 // Get initial values of real counters.
2675 for (const Expr *I : S.inits()) {
2676 CGF.EmitIgnoredExpr(I);
2677 }
2678 }
2679 // Create temp loop control variables with their init values to support
2680 // non-rectangular loops.
2681 CodeGenFunction::OMPMapVars PreCondVars;
2682 for (const Expr *E : S.dependent_counters()) {
2683 if (!E)
2684 continue;
2685 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2686 "dependent counter must not be an iterator.");
2687 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2688 Address CounterAddr =
2690 (void)PreCondVars.setVarAddr(CGF, VD, CounterAddr);
2691 }
2692 (void)PreCondVars.apply(CGF);
2693 for (const Expr *E : S.dependent_inits()) {
2694 if (!E)
2695 continue;
2696 CGF.EmitIgnoredExpr(E);
2697 }
2698 // Check that loop is executed at least one time.
2699 CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount);
2700 PreCondVars.restore(CGF);
2701}
2702
2704 const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope) {
2705 if (!HaveInsertPoint())
2706 return;
2707 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2709 if (isOpenMPSimdDirective(EKind)) {
2710 const auto *LoopDirective = cast<OMPLoopDirective>(&D);
2711 for (const Expr *C : LoopDirective->counters()) {
2712 SIMDLCVs.insert(
2714 }
2715 }
2716 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
2717 auto CurPrivate = C->privates().begin();
2718 for (const Expr *E : C->varlist()) {
2719 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2720 const auto *PrivateVD =
2721 cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
2722 if (!SIMDLCVs.count(VD->getCanonicalDecl())) {
2723 // Emit private VarDecl with copy init.
2724 EmitVarDecl(*PrivateVD);
2725 bool IsRegistered =
2726 PrivateScope.addPrivate(VD, GetAddrOfLocalVar(PrivateVD));
2727 assert(IsRegistered && "linear var already registered as private");
2728 // Silence the warning about unused variable.
2729 (void)IsRegistered;
2730 } else {
2731 EmitVarDecl(*PrivateVD);
2732 }
2733 ++CurPrivate;
2734 }
2735 }
2736}
2737
2739 const OMPExecutableDirective &D) {
2740 if (!CGF.HaveInsertPoint())
2741 return;
2742 if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) {
2743 RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
2744 /*ignoreResult=*/true);
2745 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
2746 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
2747 // In presence of finite 'safelen', it may be unsafe to mark all
2748 // the memory instructions parallel, because loop-carried
2749 // dependences of 'safelen' iterations are possible.
2750 CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>());
2751 } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) {
2752 RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
2753 /*ignoreResult=*/true);
2754 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
2755 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
2756 // In presence of finite 'safelen', it may be unsafe to mark all
2757 // the memory instructions parallel, because loop-carried
2758 // dependences of 'safelen' iterations are possible.
2759 CGF.LoopStack.setParallel(/*Enable=*/false);
2760 }
2761}
2762
2763// Check for the presence of an `OMPOrderedDirective`,
2764// i.e., `ordered` in `#pragma omp ordered simd`.
2765//
2766// Consider the following source code:
2767// ```
2768// __attribute__((noinline)) void omp_simd_loop(float X[ARRAY_SIZE][ARRAY_SIZE])
2769// {
2770// for (int r = 1; r < ARRAY_SIZE; ++r) {
2771// for (int c = 1; c < ARRAY_SIZE; ++c) {
2772// #pragma omp simd
2773// for (int k = 2; k < ARRAY_SIZE; ++k) {
2774// #pragma omp ordered simd
2775// X[r][k] = X[r][k - 2] + sinf((float)(r / c));
2776// }
2777// }
2778// }
2779// }
2780// ```
2781//
2782// Suppose we are in `CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective
2783// &D)`. By examining `D.dump()` we have the following AST containing
2784// `OMPOrderedDirective`:
2785//
2786// ```
2787// OMPSimdDirective 0x1c32950
2788// `-CapturedStmt 0x1c32028
2789// |-CapturedDecl 0x1c310e8
2790// | |-ForStmt 0x1c31e30
2791// | | |-DeclStmt 0x1c31298
2792// | | | `-VarDecl 0x1c31208 used k 'int' cinit
2793// | | | `-IntegerLiteral 0x1c31278 'int' 2
2794// | | |-<<<NULL>>>
2795// | | |-BinaryOperator 0x1c31308 'int' '<'
2796// | | | |-ImplicitCastExpr 0x1c312f0 'int' <LValueToRValue>
2797// | | | | `-DeclRefExpr 0x1c312b0 'int' lvalue Var 0x1c31208 'k' 'int'
2798// | | | `-IntegerLiteral 0x1c312d0 'int' 256
2799// | | |-UnaryOperator 0x1c31348 'int' prefix '++'
2800// | | | `-DeclRefExpr 0x1c31328 'int' lvalue Var 0x1c31208 'k' 'int'
2801// | | `-CompoundStmt 0x1c31e18
2802// | | `-OMPOrderedDirective 0x1c31dd8
2803// | | |-OMPSimdClause 0x1c31380
2804// | | `-CapturedStmt 0x1c31cd0
2805// ```
2806//
2807// Note the presence of `OMPOrderedDirective` above:
2808// It's (transitively) nested in a `CapturedStmt` representing the pragma
2809// annotated compound statement. Thus, we need to consider this nesting and
2810// include checking the `getCapturedStmt` in this case.
2811static bool hasOrderedDirective(const Stmt *S) {
2813 return true;
2814
2815 if (const auto *CS = dyn_cast<CapturedStmt>(S))
2817
2818 for (const Stmt *Child : S->children()) {
2819 if (Child && hasOrderedDirective(Child))
2820 return true;
2821 }
2822
2823 return false;
2824}
2825
2826static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt,
2828 // Check for the presence of an `OMPOrderedDirective`
2829 // i.e., `ordered` in `#pragma omp ordered simd`
2830 bool HasOrderedDirective = hasOrderedDirective(&AssociatedStmt);
2831 // If present then conservatively disable loop vectorization
2832 // analogously to how `emitSimdlenSafelenClause` does.
2833 if (HasOrderedDirective)
2834 LoopStack.setParallel(/*Enable=*/false);
2835}
2836
2838 // Walk clauses and process safelen/lastprivate.
2839 LoopStack.setParallel(/*Enable=*/true);
2840 LoopStack.setVectorizeEnable();
2841 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2843 emitSimdlenSafelenClause(*this, D);
2844 if (const auto *C = D.getSingleClause<OMPOrderClause>())
2845 if (C->getKind() == OMPC_ORDER_concurrent)
2846 LoopStack.setParallel(/*Enable=*/true);
2848 if ((EKind == OMPD_simd ||
2849 (getLangOpts().OpenMPSimd && isOpenMPSimdDirective(EKind))) &&
2850 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2851 [](const OMPReductionClause *C) {
2852 return C->getModifier() == OMPC_REDUCTION_inscan;
2853 }))
2854 // Disable parallel access in case of prefix sum.
2855 LoopStack.setParallel(/*Enable=*/false);
2856}
2857
2859 const OMPLoopDirective &D,
2860 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2861 if (!HaveInsertPoint())
2862 return;
2863 llvm::BasicBlock *DoneBB = nullptr;
2864 auto IC = D.counters().begin();
2865 auto IPC = D.private_counters().begin();
2866 for (const Expr *F : D.finals()) {
2867 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
2868 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
2869 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2870 if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) ||
2871 OrigVD->hasGlobalStorage() || CED) {
2872 if (!DoneBB) {
2873 if (llvm::Value *Cond = CondGen(*this)) {
2874 // If the first post-update expression is found, emit conditional
2875 // block if it was requested.
2876 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.final.then");
2877 DoneBB = createBasicBlock(".omp.final.done");
2878 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2879 EmitBlock(ThenBB);
2880 }
2881 }
2882 Address OrigAddr = Address::invalid();
2883 if (CED) {
2884 OrigAddr = EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress();
2885 } else {
2886 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(PrivateVD),
2887 /*RefersToEnclosingVariableOrCapture=*/false,
2888 (*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc());
2889 OrigAddr = EmitLValue(&DRE).getAddress();
2890 }
2891 OMPPrivateScope VarScope(*this);
2892 VarScope.addPrivate(OrigVD, OrigAddr);
2893 (void)VarScope.Privatize();
2894 EmitIgnoredExpr(F);
2895 }
2896 ++IC;
2897 ++IPC;
2898 }
2899 if (DoneBB)
2900 EmitBlock(DoneBB, /*IsFinished=*/true);
2901}
2902
2909
2910/// Emit a helper variable and return corresponding lvalue.
2912 const DeclRefExpr *Helper) {
2913 auto VDecl = cast<VarDecl>(Helper->getDecl());
2914 CGF.EmitVarDecl(*VDecl);
2915 return CGF.EmitLValue(Helper);
2916}
2917
2919 const RegionCodeGenTy &SimdInitGen,
2920 const RegionCodeGenTy &BodyCodeGen) {
2921 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](CodeGenFunction &CGF,
2922 PrePostActionTy &) {
2923 CGOpenMPRuntime::NontemporalDeclsRAII NontemporalsRegion(CGF.CGM, S);
2925 SimdInitGen(CGF);
2926
2927 BodyCodeGen(CGF);
2928 };
2929 auto &&ElseGen = [&BodyCodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
2931 CGF.LoopStack.setVectorizeEnable(/*Enable=*/false);
2932
2933 BodyCodeGen(CGF);
2934 };
2935 const Expr *IfCond = nullptr;
2937 if (isOpenMPSimdDirective(EKind)) {
2938 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
2939 if (CGF.getLangOpts().OpenMP >= 50 &&
2940 (C->getNameModifier() == OMPD_unknown ||
2941 C->getNameModifier() == OMPD_simd)) {
2942 IfCond = C->getCondition();
2943 break;
2944 }
2945 }
2946 }
2947 if (IfCond) {
2948 CGF.CGM.getOpenMPRuntime().emitIfClause(CGF, IfCond, ThenGen, ElseGen);
2949 } else {
2950 RegionCodeGenTy ThenRCG(ThenGen);
2951 ThenRCG(CGF);
2952 }
2953}
2954
2956 PrePostActionTy &Action) {
2957 Action.Enter(CGF);
2958 OMPLoopScope PreInitScope(CGF, S);
2959 // if (PreCond) {
2960 // for (IV in 0..LastIteration) BODY;
2961 // <Final counter/linear vars updates>;
2962 // }
2963
2964 // The presence of lower/upper bound variable depends on the actual directive
2965 // kind in the AST node. The variables must be emitted because some of the
2966 // expressions associated with the loop will use them.
2967 OpenMPDirectiveKind DKind = S.getDirectiveKind();
2968 if (isOpenMPDistributeDirective(DKind) ||
2971 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()));
2972 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()));
2973 }
2974
2976 // Emit: if (PreCond) - begin.
2977 // If the condition constant folds and can be elided, avoid emitting the
2978 // whole loop.
2979 bool CondConstant;
2980 llvm::BasicBlock *ContBlock = nullptr;
2981 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
2982 if (!CondConstant)
2983 return;
2984 } else {
2985 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("simd.if.then");
2986 ContBlock = CGF.createBasicBlock("simd.if.end");
2987 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2988 CGF.getProfileCount(&S));
2989 CGF.EmitBlock(ThenBlock);
2991 }
2992
2993 // Emit the loop iteration variable.
2994 const Expr *IVExpr = S.getIterationVariable();
2995 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
2996 CGF.EmitVarDecl(*IVDecl);
2997 CGF.EmitIgnoredExpr(S.getInit());
2998
2999 // Emit the iterations count variable.
3000 // If it is not a variable, Sema decided to calculate iterations count on
3001 // each iteration (e.g., it is foldable into a constant).
3002 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3003 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
3004 // Emit calculation of the iterations count.
3005 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
3006 }
3007
3008 emitAlignedClause(CGF, S);
3009 (void)CGF.EmitOMPLinearClauseInit(S);
3010 {
3011 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
3012 CGF.EmitOMPPrivateClause(S, LoopScope);
3013 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
3014 CGF.EmitOMPLinearClause(S, LoopScope);
3015 CGF.EmitOMPReductionClauseInit(S, LoopScope);
3017 CGF, S, CGF.EmitLValue(S.getIterationVariable()));
3018 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
3019 (void)LoopScope.Privatize();
3022
3024 CGF, S,
3025 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
3026 CGF.EmitOMPSimdInit(S);
3027 },
3028 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3029 CGF.EmitOMPInnerLoop(
3030 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
3031 [&S](CodeGenFunction &CGF) {
3032 emitOMPLoopBodyWithStopPoint(CGF, S,
3033 CodeGenFunction::JumpDest());
3034 },
3035 [](CodeGenFunction &) {});
3036 });
3037 CGF.EmitOMPSimdFinal(S, [](CodeGenFunction &) { return nullptr; });
3038 // Emit final copy of the lastprivate variables at the end of loops.
3039 if (HasLastprivateClause)
3040 CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true);
3041 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd);
3043 [](CodeGenFunction &) { return nullptr; });
3044 LoopScope.restoreMap();
3045 CGF.EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; });
3046 }
3047 // Emit: if (PreCond) - end.
3048 if (ContBlock) {
3049 CGF.EmitBranch(ContBlock);
3050 CGF.EmitBlock(ContBlock, true);
3051 }
3052}
3053
3054// Pass OMPLoopDirective (instead of OMPSimdDirective) to make this function
3055// available for "loop bind(thread)", which maps to "simd".
3057 // Check for unsupported clauses
3058 for (OMPClause *C : S.clauses()) {
3059 // Currently only order, simdlen and safelen clauses are supported
3062 return false;
3063 }
3064
3065 // Check if we have a statement with the ordered directive.
3066 // Visit the statement hierarchy to find a compound statement
3067 // with a ordered directive in it.
3068 if (const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3069 if (const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3070 for (const Stmt *SubStmt : SyntacticalLoop->children()) {
3071 if (!SubStmt)
3072 continue;
3073 if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3074 for (const Stmt *CSSubStmt : CS->children()) {
3075 if (!CSSubStmt)
3076 continue;
3077 if (isa<OMPOrderedDirective>(CSSubStmt)) {
3078 return false;
3079 }
3080 }
3081 }
3082 }
3083 }
3084 }
3085 return true;
3086}
3087
3088static llvm::MapVector<llvm::Value *, llvm::Value *>
3090 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3091 for (const auto *Clause : S.getClausesOfKind<OMPAlignedClause>()) {
3092 llvm::APInt ClauseAlignment(64, 0);
3093 if (const Expr *AlignmentExpr = Clause->getAlignment()) {
3094 auto *AlignmentCI =
3095 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
3096 ClauseAlignment = AlignmentCI->getValue();
3097 }
3098 for (const Expr *E : Clause->varlist()) {
3099 llvm::APInt Alignment(ClauseAlignment);
3100 if (Alignment == 0) {
3101 // OpenMP [2.8.1, Description]
3102 // If no optional parameter is specified, implementation-defined default
3103 // alignments for SIMD instructions on the target platforms are assumed.
3104 Alignment =
3105 CGF.getContext()
3107 E->getType()->getPointeeType()))
3108 .getQuantity();
3109 }
3110 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3111 "alignment is not power of 2");
3112 llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
3113 AlignedVars[PtrValue] = CGF.Builder.getInt64(Alignment.getSExtValue());
3114 }
3115 }
3116 return AlignedVars;
3117}
3118
3119// Pass OMPLoopDirective (instead of OMPSimdDirective) to make this function
3120// available for "loop bind(thread)", which maps to "simd".
3123 bool UseOMPIRBuilder =
3124 CGM.getLangOpts().OpenMPIRBuilder && isSimdSupportedByOpenMPIRBuilder(S);
3125 if (UseOMPIRBuilder) {
3126 auto &&CodeGenIRBuilder = [&S, &CGM, UseOMPIRBuilder](CodeGenFunction &CGF,
3127 PrePostActionTy &) {
3128 // Use the OpenMPIRBuilder if enabled.
3129 if (UseOMPIRBuilder) {
3130 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3131 GetAlignedMapping(S, CGF);
3132 // Emit the associated statement and get its loop representation.
3133 const Stmt *Inner = S.getRawStmt();
3134 llvm::CanonicalLoopInfo *CLI =
3135 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3136
3137 llvm::OpenMPIRBuilder &OMPBuilder =
3139 // Add SIMD specific metadata
3140 llvm::ConstantInt *Simdlen = nullptr;
3141 if (const auto *C = S.getSingleClause<OMPSimdlenClause>()) {
3142 RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
3143 /*ignoreResult=*/true);
3144 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
3145 Simdlen = Val;
3146 }
3147 llvm::ConstantInt *Safelen = nullptr;
3148 if (const auto *C = S.getSingleClause<OMPSafelenClause>()) {
3149 RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
3150 /*ignoreResult=*/true);
3151 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
3152 Safelen = Val;
3153 }
3154 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3155 if (const auto *C = S.getSingleClause<OMPOrderClause>()) {
3156 if (C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3157 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3158 }
3159 }
3160 // Add simd metadata to the collapsed loop. Do not generate
3161 // another loop for if clause. Support for if clause is done earlier.
3162 OMPBuilder.applySimd(CLI, AlignedVars,
3163 /*IfCond*/ nullptr, Order, Simdlen, Safelen);
3164 return;
3165 }
3166 };
3167 {
3168 auto LPCRegion =
3170 OMPLexicalScope Scope(CGF, S, OMPD_unknown);
3171 CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
3172 CodeGenIRBuilder);
3173 }
3174 return;
3175 }
3176
3178 CGF.OMPFirstScanLoop = true;
3179 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3180 emitOMPSimdRegion(CGF, S, Action);
3181 };
3182 {
3183 auto LPCRegion =
3185 OMPLexicalScope Scope(CGF, S, OMPD_unknown);
3187 }
3188 // Check for outer lastprivate conditional update.
3190}
3191
3192void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
3193 emitOMPSimdDirective(S, *this, CGM);
3194}
3195
3197 // Emit the de-sugared statement.
3198 OMPTransformDirectiveScopeRAII TileScope(*this, &S);
3200}
3201
3203 // Emit the de-sugared statement.
3204 OMPTransformDirectiveScopeRAII StripeScope(*this, &S);
3206}
3207
3209 // Emit the de-sugared statement.
3210 OMPTransformDirectiveScopeRAII ReverseScope(*this, &S);
3212}
3213
3215 // Emit the de-sugared statement (the split loops).
3216 OMPTransformDirectiveScopeRAII SplitScope(*this, &S);
3218}
3219
3221 const OMPInterchangeDirective &S) {
3222 // Emit the de-sugared statement.
3223 OMPTransformDirectiveScopeRAII InterchangeScope(*this, &S);
3225}
3226
3228 // Emit the de-sugared statement
3229 OMPTransformDirectiveScopeRAII FuseScope(*this, &S);
3231}
3232
3234 bool UseOMPIRBuilder = CGM.getLangOpts().OpenMPIRBuilder;
3235
3236 if (UseOMPIRBuilder) {
3237 auto DL = SourceLocToDebugLoc(S.getBeginLoc());
3238 const Stmt *Inner = S.getRawStmt();
3239
3240 // Consume nested loop. Clear the entire remaining loop stack because a
3241 // fully unrolled loop is non-transformable. For partial unrolling the
3242 // generated outer loop is pushed back to the stack.
3243 llvm::CanonicalLoopInfo *CLI = EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3244 OMPLoopNestStack.clear();
3245
3246 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
3247
3248 bool NeedsUnrolledCLI = ExpectedOMPLoopDepth >= 1;
3249 llvm::CanonicalLoopInfo *UnrolledCLI = nullptr;
3250
3251 if (S.hasClausesOfKind<OMPFullClause>()) {
3252 assert(ExpectedOMPLoopDepth == 0);
3253 OMPBuilder.unrollLoopFull(DL, CLI);
3254 } else if (auto *PartialClause = S.getSingleClause<OMPPartialClause>()) {
3255 uint64_t Factor = 0;
3256 if (Expr *FactorExpr = PartialClause->getFactor()) {
3257 Factor = FactorExpr->EvaluateKnownConstInt(getContext()).getZExtValue();
3258 assert(Factor >= 1 && "Only positive factors are valid");
3259 }
3260 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3261 NeedsUnrolledCLI ? &UnrolledCLI : nullptr);
3262 } else {
3263 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3264 }
3265
3266 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3267 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3268 if (UnrolledCLI)
3269 OMPLoopNestStack.push_back(UnrolledCLI);
3270
3271 return;
3272 }
3273
3274 // This function is only called if the unrolled loop is not consumed by any
3275 // other loop-associated construct. Such a loop-associated construct will have
3276 // used the transformed AST.
3277
3278 // Set the unroll metadata for the next emitted loop.
3279 LoopStack.setUnrollState(LoopAttributes::Enable);
3280
3281 if (S.hasClausesOfKind<OMPFullClause>()) {
3282 LoopStack.setUnrollState(LoopAttributes::Full);
3283 } else if (auto *PartialClause = S.getSingleClause<OMPPartialClause>()) {
3284 if (Expr *FactorExpr = PartialClause->getFactor()) {
3285 uint64_t Factor =
3286 FactorExpr->EvaluateKnownConstInt(getContext()).getZExtValue();
3287 assert(Factor >= 1 && "Only positive factors are valid");
3288 LoopStack.setUnrollCount(Factor);
3289 }
3290 }
3291
3292 EmitStmt(S.getAssociatedStmt());
3293}
3294
3295void CodeGenFunction::EmitOMPOuterLoop(
3296 bool DynamicOrOrdered, bool IsMonotonic, const OMPLoopDirective &S,
3298 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3299 const CodeGenFunction::CodeGenLoopTy &CodeGenLoop,
3300 const CodeGenFunction::CodeGenOrderedTy &CodeGenOrdered) {
3302
3303 const Expr *IVExpr = S.getIterationVariable();
3304 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3305 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3306
3307 JumpDest LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
3308
3309 // Start the loop with a block that tests the condition.
3310 llvm::BasicBlock *CondBlock = createBasicBlock("omp.dispatch.cond");
3311 EmitBlock(CondBlock);
3312 const SourceRange R = S.getSourceRange();
3313 OMPLoopNestStack.clear();
3314 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
3315 SourceLocToDebugLoc(R.getEnd()));
3316
3317 llvm::Value *BoolCondVal = nullptr;
3318 if (!DynamicOrOrdered) {
3319 // UB = min(UB, GlobalUB) or
3320 // UB = min(UB, PrevUB) for combined loop sharing constructs (e.g.
3321 // 'distribute parallel for')
3322 EmitIgnoredExpr(LoopArgs.EUB);
3323 // IV = LB
3324 EmitIgnoredExpr(LoopArgs.Init);
3325 // IV < UB
3326 BoolCondVal = EvaluateExprAsBool(LoopArgs.Cond);
3327 } else {
3328 BoolCondVal =
3329 RT.emitForNext(*this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3330 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3331 }
3332
3333 // If there are any cleanups between here and the loop-exit scope,
3334 // create a block to stage a loop exit along.
3335 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
3336 if (LoopScope.requiresCleanups())
3337 ExitBlock = createBasicBlock("omp.dispatch.cleanup");
3338
3339 llvm::BasicBlock *LoopBody = createBasicBlock("omp.dispatch.body");
3340 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3341 if (ExitBlock != LoopExit.getBlock()) {
3342 EmitBlock(ExitBlock);
3344 }
3345 EmitBlock(LoopBody);
3346
3347 // Emit "IV = LB" (in case of static schedule, we have already calculated new
3348 // LB for loop condition and emitted it above).
3349 if (DynamicOrOrdered)
3350 EmitIgnoredExpr(LoopArgs.Init);
3351
3352 // Create a block for the increment.
3353 JumpDest Continue = getJumpDestInCurrentScope("omp.dispatch.inc");
3354 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3355
3358 *this, S,
3359 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3360 // Generate !llvm.loop.parallel metadata for loads and stores for loops
3361 // with dynamic/guided scheduling and without ordered clause.
3362 if (!isOpenMPSimdDirective(EKind)) {
3363 CGF.LoopStack.setParallel(!IsMonotonic);
3364 if (const auto *C = S.getSingleClause<OMPOrderClause>())
3365 if (C->getKind() == OMPC_ORDER_concurrent)
3366 CGF.LoopStack.setParallel(/*Enable=*/true);
3367 } else {
3368 CGF.EmitOMPSimdInit(S);
3369 }
3370 },
3371 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3372 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3373 SourceLocation Loc = S.getBeginLoc();
3374 // when 'distribute' is not combined with a 'for':
3375 // while (idx <= UB) { BODY; ++idx; }
3376 // when 'distribute' is combined with a 'for'
3377 // (e.g. 'distribute parallel for')
3378 // while (idx <= UB) { <CodeGen rest of pragma>; idx += ST; }
3379 CGF.EmitOMPInnerLoop(
3380 S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr,
3381 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3382 CodeGenLoop(CGF, S, LoopExit);
3383 },
3384 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3385 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3386 });
3387 });
3388
3389 EmitBlock(Continue.getBlock());
3390 BreakContinueStack.pop_back();
3391 if (!DynamicOrOrdered) {
3392 // Emit "LB = LB + Stride", "UB = UB + Stride".
3393 EmitIgnoredExpr(LoopArgs.NextLB);
3394 EmitIgnoredExpr(LoopArgs.NextUB);
3395 }
3396
3397 EmitBranch(CondBlock);
3398 OMPLoopNestStack.clear();
3399 LoopStack.pop();
3400 // Emit the fall-through block.
3401 EmitBlock(LoopExit.getBlock());
3402
3403 // Tell the runtime we are done.
3404 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3405 if (!DynamicOrOrdered)
3406 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3407 LoopArgs.DKind);
3408 };
3409 OMPCancelStack.emitExit(*this, EKind, CodeGen);
3410}
3411
3412void CodeGenFunction::EmitOMPForOuterLoop(
3413 const OpenMPScheduleTy &ScheduleKind, bool IsMonotonic,
3414 const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered,
3415 const OMPLoopArguments &LoopArgs,
3416 const CodeGenDispatchBoundsTy &CGDispatchBounds) {
3417 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
3418
3419 // Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime).
3420 const bool DynamicOrOrdered = Ordered || RT.isDynamic(ScheduleKind.Schedule);
3421
3422 assert((Ordered || !RT.isStaticNonchunked(ScheduleKind.Schedule,
3423 LoopArgs.Chunk != nullptr)) &&
3424 "static non-chunked schedule does not need outer loop");
3425
3426 // Emit outer loop.
3427 //
3428 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
3429 // When schedule(dynamic,chunk_size) is specified, the iterations are
3430 // distributed to threads in the team in chunks as the threads request them.
3431 // Each thread executes a chunk of iterations, then requests another chunk,
3432 // until no chunks remain to be distributed. Each chunk contains chunk_size
3433 // iterations, except for the last chunk to be distributed, which may have
3434 // fewer iterations. When no chunk_size is specified, it defaults to 1.
3435 //
3436 // When schedule(guided,chunk_size) is specified, the iterations are assigned
3437 // to threads in the team in chunks as the executing threads request them.
3438 // Each thread executes a chunk of iterations, then requests another chunk,
3439 // until no chunks remain to be assigned. For a chunk_size of 1, the size of
3440 // each chunk is proportional to the number of unassigned iterations divided
3441 // by the number of threads in the team, decreasing to 1. For a chunk_size
3442 // with value k (greater than 1), the size of each chunk is determined in the
3443 // same way, with the restriction that the chunks do not contain fewer than k
3444 // iterations (except for the last chunk to be assigned, which may have fewer
3445 // than k iterations).
3446 //
3447 // When schedule(auto) is specified, the decision regarding scheduling is
3448 // delegated to the compiler and/or runtime system. The programmer gives the
3449 // implementation the freedom to choose any possible mapping of iterations to
3450 // threads in the team.
3451 //
3452 // When schedule(runtime) is specified, the decision regarding scheduling is
3453 // deferred until run time, and the schedule and chunk size are taken from the
3454 // run-sched-var ICV. If the ICV is set to auto, the schedule is
3455 // implementation defined
3456 //
3457 // __kmpc_dispatch_init();
3458 // while(__kmpc_dispatch_next(&LB, &UB)) {
3459 // idx = LB;
3460 // while (idx <= UB) { BODY; ++idx;
3461 // __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only.
3462 // } // inner loop
3463 // }
3464 // __kmpc_dispatch_deinit();
3465 //
3466 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
3467 // When schedule(static, chunk_size) is specified, iterations are divided into
3468 // chunks of size chunk_size, and the chunks are assigned to the threads in
3469 // the team in a round-robin fashion in the order of the thread number.
3470 //
3471 // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) {
3472 // while (idx <= UB) { BODY; ++idx; } // inner loop
3473 // LB = LB + ST;
3474 // UB = UB + ST;
3475 // }
3476 //
3477
3478 const Expr *IVExpr = S.getIterationVariable();
3479 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3480 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3481
3482 if (DynamicOrOrdered) {
3483 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3484 CGDispatchBounds(*this, S, LoopArgs.LB, LoopArgs.UB);
3485 llvm::Value *LBVal = DispatchBounds.first;
3486 llvm::Value *UBVal = DispatchBounds.second;
3487 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3488 LoopArgs.Chunk};
3489 RT.emitForDispatchInit(*this, S.getBeginLoc(), ScheduleKind, IVSize,
3490 IVSigned, Ordered, DipatchRTInputValues);
3491 } else {
3492 CGOpenMPRuntime::StaticRTInput StaticInit(
3493 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3494 LoopArgs.ST, LoopArgs.Chunk);
3496 RT.emitForStaticInit(*this, S.getBeginLoc(), EKind, ScheduleKind,
3497 StaticInit);
3498 }
3499
3500 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3501 const unsigned IVSize,
3502 const bool IVSigned) {
3503 if (Ordered) {
3504 CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(CGF, Loc, IVSize,
3505 IVSigned);
3506 }
3507 };
3508
3509 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3510 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3511 OuterLoopArgs.IncExpr = S.getInc();
3512 OuterLoopArgs.Init = S.getInit();
3513 OuterLoopArgs.Cond = S.getCond();
3514 OuterLoopArgs.NextLB = S.getNextLowerBound();
3515 OuterLoopArgs.NextUB = S.getNextUpperBound();
3516 OuterLoopArgs.DKind = LoopArgs.DKind;
3517 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3518 emitOMPLoopBodyWithStopPoint, CodeGenOrdered);
3519 if (DynamicOrOrdered) {
3520 RT.emitForDispatchDeinit(*this, S.getBeginLoc());
3521 }
3522}
3523
3525 const unsigned IVSize, const bool IVSigned) {}
3526
3527void CodeGenFunction::EmitOMPDistributeOuterLoop(
3528 OpenMPDistScheduleClauseKind ScheduleKind, const OMPLoopDirective &S,
3529 OMPPrivateScope &LoopScope, const OMPLoopArguments &LoopArgs,
3530 const CodeGenLoopTy &CodeGenLoopContent) {
3531
3532 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
3533
3534 // Emit outer loop.
3535 // Same behavior as a OMPForOuterLoop, except that schedule cannot be
3536 // dynamic
3537 //
3538
3539 const Expr *IVExpr = S.getIterationVariable();
3540 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3541 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3543
3544 CGOpenMPRuntime::StaticRTInput StaticInit(
3545 IVSize, IVSigned, /* Ordered = */ false, LoopArgs.IL, LoopArgs.LB,
3546 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3547 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, StaticInit);
3548
3549 // for combined 'distribute' and 'for' the increment expression of distribute
3550 // is stored in DistInc. For 'distribute' alone, it is in Inc.
3551 Expr *IncExpr;
3553 IncExpr = S.getDistInc();
3554 else
3555 IncExpr = S.getInc();
3556
3557 // this routine is shared by 'omp distribute parallel for' and
3558 // 'omp distribute': select the right EUB expression depending on the
3559 // directive
3560 OMPLoopArguments OuterLoopArgs;
3561 OuterLoopArgs.LB = LoopArgs.LB;
3562 OuterLoopArgs.UB = LoopArgs.UB;
3563 OuterLoopArgs.ST = LoopArgs.ST;
3564 OuterLoopArgs.IL = LoopArgs.IL;
3565 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3566 OuterLoopArgs.EUB = isOpenMPLoopBoundSharingDirective(EKind)
3567 ? S.getCombinedEnsureUpperBound()
3568 : S.getEnsureUpperBound();
3569 OuterLoopArgs.IncExpr = IncExpr;
3570 OuterLoopArgs.Init = isOpenMPLoopBoundSharingDirective(EKind)
3571 ? S.getCombinedInit()
3572 : S.getInit();
3573 OuterLoopArgs.Cond = isOpenMPLoopBoundSharingDirective(EKind)
3574 ? S.getCombinedCond()
3575 : S.getCond();
3576 OuterLoopArgs.NextLB = isOpenMPLoopBoundSharingDirective(EKind)
3577 ? S.getCombinedNextLowerBound()
3578 : S.getNextLowerBound();
3579 OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(EKind)
3580 ? S.getCombinedNextUpperBound()
3581 : S.getNextUpperBound();
3582 OuterLoopArgs.DKind = OMPD_distribute;
3583
3584 EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S,
3585 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3587}
3588
3589static std::pair<LValue, LValue>
3591 const OMPExecutableDirective &S) {
3593 LValue LB =
3594 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
3595 LValue UB =
3596 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable()));
3597
3598 // When composing 'distribute' with 'for' (e.g. as in 'distribute
3599 // parallel for') we need to use the 'distribute'
3600 // chunk lower and upper bounds rather than the whole loop iteration
3601 // space. These are parameters to the outlined function for 'parallel'
3602 // and we copy the bounds of the previous schedule into the
3603 // the current ones.
3604 LValue PrevLB = CGF.EmitLValue(LS.getPrevLowerBoundVariable());
3605 LValue PrevUB = CGF.EmitLValue(LS.getPrevUpperBoundVariable());
3606 llvm::Value *PrevLBVal = CGF.EmitLoadOfScalar(
3607 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3608 PrevLBVal = CGF.EmitScalarConversion(
3609 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3610 LS.getIterationVariable()->getType(),
3611 LS.getPrevLowerBoundVariable()->getExprLoc());
3612 llvm::Value *PrevUBVal = CGF.EmitLoadOfScalar(
3613 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3614 PrevUBVal = CGF.EmitScalarConversion(
3615 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3616 LS.getIterationVariable()->getType(),
3617 LS.getPrevUpperBoundVariable()->getExprLoc());
3618
3619 CGF.EmitStoreOfScalar(PrevLBVal, LB);
3620 CGF.EmitStoreOfScalar(PrevUBVal, UB);
3621
3622 return {LB, UB};
3623}
3624
3625/// if the 'for' loop has a dispatch schedule (e.g. dynamic, guided) then
3626/// we need to use the LB and UB expressions generated by the worksharing
3627/// code generation support, whereas in non combined situations we would
3628/// just emit 0 and the LastIteration expression
3629/// This function is necessary due to the difference of the LB and UB
3630/// types for the RT emission routines for 'for_static_init' and
3631/// 'for_dispatch_init'
3632static std::pair<llvm::Value *, llvm::Value *>
3634 const OMPExecutableDirective &S,
3635 Address LB, Address UB) {
3637 const Expr *IVExpr = LS.getIterationVariable();
3638 // when implementing a dynamic schedule for a 'for' combined with a
3639 // 'distribute' (e.g. 'distribute parallel for'), the 'for' loop
3640 // is not normalized as each team only executes its own assigned
3641 // distribute chunk
3642 QualType IteratorTy = IVExpr->getType();
3643 llvm::Value *LBVal =
3644 CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
3645 llvm::Value *UBVal =
3646 CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
3647 return {LBVal, UBVal};
3648}
3649
3653 const auto &Dir = cast<OMPLoopDirective>(S);
3654 LValue LB =
3655 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable()));
3656 llvm::Value *LBCast = CGF.Builder.CreateIntCast(
3657 CGF.Builder.CreateLoad(LB.getAddress()), CGF.SizeTy, /*isSigned=*/false);
3658 CapturedVars.push_back(LBCast);
3659 LValue UB =
3660 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable()));
3661
3662 llvm::Value *UBCast = CGF.Builder.CreateIntCast(
3663 CGF.Builder.CreateLoad(UB.getAddress()), CGF.SizeTy, /*isSigned=*/false);
3664 CapturedVars.push_back(UBCast);
3665}
3666
3667static void
3669 const OMPLoopDirective &S,
3672 auto &&CGInlinedWorksharingLoop = [&S, EKind](CodeGenFunction &CGF,
3673 PrePostActionTy &Action) {
3674 Action.Enter(CGF);
3675 bool HasCancel = false;
3676 if (!isOpenMPSimdDirective(EKind)) {
3677 if (const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3678 HasCancel = D->hasCancel();
3679 else if (const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3680 HasCancel = D->hasCancel();
3681 else if (const auto *D =
3682 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3683 HasCancel = D->hasCancel();
3684 }
3685 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
3686 CGF.EmitOMPWorksharingLoop(S, S.getPrevEnsureUpperBound(),
3689 };
3690
3692 CGF, S, isOpenMPSimdDirective(EKind) ? OMPD_for_simd : OMPD_for,
3693 CGInlinedWorksharingLoop,
3695}
3696
3699 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
3701 S.getDistInc());
3702 };
3703 OMPLexicalScope Scope(*this, S, OMPD_parallel);
3704 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
3705}
3706
3709 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
3711 S.getDistInc());
3712 };
3713 OMPLexicalScope Scope(*this, S, OMPD_parallel);
3714 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
3715}
3716
3718 const OMPDistributeSimdDirective &S) {
3719 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
3721 };
3722 OMPLexicalScope Scope(*this, S, OMPD_unknown);
3723 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
3724}
3725
3727 CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S) {
3728 // Emit SPMD target parallel for region as a standalone region.
3729 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3730 emitOMPSimdRegion(CGF, S, Action);
3731 };
3732 llvm::Function *Fn;
3733 llvm::Constant *Addr;
3734 // Emit target region as a standalone region.
3735 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3736 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
3737 assert(Fn && Addr && "Target device function emission failed.");
3738}
3739
3741 const OMPTargetSimdDirective &S) {
3742 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3743 emitOMPSimdRegion(CGF, S, Action);
3744 };
3746}
3747
3748namespace {
3749struct ScheduleKindModifiersTy {
3753 ScheduleKindModifiersTy(OpenMPScheduleClauseKind Kind,
3756 : Kind(Kind), M1(M1), M2(M2) {}
3757};
3758} // namespace
3759
3761 const OMPLoopDirective &S, Expr *EUB,
3762 const CodeGenLoopBoundsTy &CodeGenLoopBounds,
3763 const CodeGenDispatchBoundsTy &CGDispatchBounds) {
3764 // Emit the loop iteration variable.
3765 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
3766 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
3767 EmitVarDecl(*IVDecl);
3768
3769 // Emit the iterations count variable.
3770 // If it is not a variable, Sema decided to calculate iterations count on each
3771 // iteration (e.g., it is foldable into a constant).
3772 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3773 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
3774 // Emit calculation of the iterations count.
3775 EmitIgnoredExpr(S.getCalcLastIteration());
3776 }
3777
3778 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
3779
3780 bool HasLastprivateClause;
3781 // Check pre-condition.
3782 {
3783 OMPLoopScope PreInitScope(*this, S);
3784 // Skip the entire loop if we don't meet the precondition.
3785 // If the condition constant folds and can be elided, avoid emitting the
3786 // whole loop.
3787 bool CondConstant;
3788 llvm::BasicBlock *ContBlock = nullptr;
3789 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
3790 if (!CondConstant)
3791 return false;
3792 } else {
3793 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
3794 ContBlock = createBasicBlock("omp.precond.end");
3795 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
3796 getProfileCount(&S));
3797 EmitBlock(ThenBlock);
3799 }
3800
3801 RunCleanupsScope DoacrossCleanupScope(*this);
3802 bool Ordered = false;
3803 if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3804 if (OrderedClause->getNumForLoops())
3805 RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations());
3806 else
3807 Ordered = true;
3808 }
3809
3810 emitAlignedClause(*this, S);
3811 bool HasLinears = EmitOMPLinearClauseInit(S);
3812 // Emit helper vars inits.
3813
3814 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*this, S);
3815 LValue LB = Bounds.first;
3816 LValue UB = Bounds.second;
3817 LValue ST =
3818 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
3819 LValue IL =
3820 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
3821
3822 // Emit 'then' code.
3823 {
3825 OMPPrivateScope LoopScope(*this);
3826 if (EmitOMPFirstprivateClause(S, LoopScope) || HasLinears) {
3827 // Emit implicit barrier to synchronize threads and avoid data races on
3828 // initialization of firstprivate variables and post-update of
3829 // lastprivate variables.
3830 CGM.getOpenMPRuntime().emitBarrierCall(
3831 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
3832 /*ForceSimpleCall=*/true);
3833 }
3834 EmitOMPPrivateClause(S, LoopScope);
3836 *this, S, EmitLValue(S.getIterationVariable()));
3837 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
3838 EmitOMPReductionClauseInit(S, LoopScope);
3839 EmitOMPPrivateLoopCounters(S, LoopScope);
3840 EmitOMPLinearClause(S, LoopScope);
3841 (void)LoopScope.Privatize();
3843 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S);
3844
3845 // Detect the loop schedule kind and chunk.
3846 const Expr *ChunkExpr = nullptr;
3847 OpenMPScheduleTy ScheduleKind;
3848 if (const auto *C = S.getSingleClause<OMPScheduleClause>()) {
3849 ScheduleKind.Schedule = C->getScheduleKind();
3850 ScheduleKind.M1 = C->getFirstScheduleModifier();
3851 ScheduleKind.M2 = C->getSecondScheduleModifier();
3852 ChunkExpr = C->getChunkSize();
3853 } else {
3854 // Default behaviour for schedule clause.
3855 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3856 *this, S, ScheduleKind.Schedule, ChunkExpr);
3857 }
3858 bool HasChunkSizeOne = false;
3859 llvm::Value *Chunk = nullptr;
3860 if (ChunkExpr) {
3861 Chunk = EmitScalarExpr(ChunkExpr);
3862 Chunk = EmitScalarConversion(Chunk, ChunkExpr->getType(),
3863 S.getIterationVariable()->getType(),
3864 S.getBeginLoc());
3866 if (ChunkExpr->EvaluateAsInt(Result, getContext())) {
3867 llvm::APSInt EvaluatedChunk = Result.Val.getInt();
3868 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3869 }
3870 }
3871 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3872 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3873 // OpenMP 4.5, 2.7.1 Loop Construct, Description.
3874 // If the static schedule kind is specified or if the ordered clause is
3875 // specified, and if no monotonic modifier is specified, the effect will
3876 // be as if the monotonic modifier was specified.
3877 bool StaticChunkedOne =
3878 RT.isStaticChunked(ScheduleKind.Schedule,
3879 /* Chunked */ Chunk != nullptr) &&
3880 HasChunkSizeOne && isOpenMPLoopBoundSharingDirective(EKind);
3881 bool IsMonotonic =
3882 Ordered ||
3883 (ScheduleKind.Schedule == OMPC_SCHEDULE_static &&
3884 !(ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3885 ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3886 ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3887 ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3888 if ((RT.isStaticNonchunked(ScheduleKind.Schedule,
3889 /* Chunked */ Chunk != nullptr) ||
3890 StaticChunkedOne) &&
3891 !Ordered) {
3895 *this, S,
3896 [&S, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3897 if (isOpenMPSimdDirective(EKind)) {
3898 CGF.EmitOMPSimdInit(S);
3899 } else if (const auto *C = S.getSingleClause<OMPOrderClause>()) {
3900 if (C->getKind() == OMPC_ORDER_concurrent)
3901 CGF.LoopStack.setParallel(/*Enable=*/true);
3902 }
3903 },
3904 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3905 &S, ScheduleKind, LoopExit, EKind,
3906 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3907 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
3908 // When no chunk_size is specified, the iteration space is divided
3909 // into chunks that are approximately equal in size, and at most
3910 // one chunk is distributed to each thread. Note that the size of
3911 // the chunks is unspecified in this case.
3913 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3914 UB.getAddress(), ST.getAddress(),
3915 StaticChunkedOne ? Chunk : nullptr);
3917 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3918 // UB = min(UB, GlobalUB);
3919 if (!StaticChunkedOne)
3920 CGF.EmitIgnoredExpr(S.getEnsureUpperBound());
3921 // IV = LB;
3922 CGF.EmitIgnoredExpr(S.getInit());
3923 // For unchunked static schedule generate:
3924 //
3925 // while (idx <= UB) {
3926 // BODY;
3927 // ++idx;
3928 // }
3929 //
3930 // For static schedule with chunk one:
3931 //
3932 // while (IV <= PrevUB) {
3933 // BODY;
3934 // IV += ST;
3935 // }
3936 CGF.EmitOMPInnerLoop(
3937 S, LoopScope.requiresCleanups(),
3938 StaticChunkedOne ? S.getCombinedParForInDistCond()
3939 : S.getCond(),
3940 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3941 [&S, LoopExit](CodeGenFunction &CGF) {
3942 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3943 },
3944 [](CodeGenFunction &) {});
3945 });
3946 EmitBlock(LoopExit.getBlock());
3947 // Tell the runtime we are done.
3948 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
3949 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3950 OMPD_for);
3951 };
3952 OMPCancelStack.emitExit(*this, EKind, CodeGen);
3953 } else {
3954 // Emit the outer loop, which requests its work chunk [LB..UB] from
3955 // runtime and runs the inner loop to process it.
3956 OMPLoopArguments LoopArguments(LB.getAddress(), UB.getAddress(),
3957 ST.getAddress(), IL.getAddress(), Chunk,
3958 EUB);
3959 LoopArguments.DKind = OMPD_for;
3960 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3961 LoopArguments, CGDispatchBounds);
3962 }
3963 if (isOpenMPSimdDirective(EKind)) {
3964 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
3965 return CGF.Builder.CreateIsNotNull(
3966 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
3967 });
3968 }
3970 S, /*ReductionKind=*/isOpenMPSimdDirective(EKind)
3971 ? /*Parallel and Simd*/ OMPD_parallel_for_simd
3972 : /*Parallel only*/ OMPD_parallel);
3973 // Emit post-update of the reduction variables if IsLastIter != 0.
3975 *this, S, [IL, &S](CodeGenFunction &CGF) {
3976 return CGF.Builder.CreateIsNotNull(
3977 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
3978 });
3979 // Emit final copy of the lastprivate variables if IsLastIter != 0.
3980 if (HasLastprivateClause)
3982 S, isOpenMPSimdDirective(EKind),
3983 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
3984 LoopScope.restoreMap();
3985 EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) {
3986 return CGF.Builder.CreateIsNotNull(
3987 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
3988 });
3989 }
3990 DoacrossCleanupScope.ForceCleanup();
3991 // We're now done with the loop, so jump to the continuation block.
3992 if (ContBlock) {
3993 EmitBranch(ContBlock);
3994 EmitBlock(ContBlock, /*IsFinished=*/true);
3995 }
3996 }
3997 return HasLastprivateClause;
3998}
3999
4000/// The following two functions generate expressions for the loop lower
4001/// and upper bounds in case of static and dynamic (dispatch) schedule
4002/// of the associated 'for' or 'distribute' loop.
4003static std::pair<LValue, LValue>
4005 const auto &LS = cast<OMPLoopDirective>(S);
4006 LValue LB =
4007 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
4008 LValue UB =
4009 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable()));
4010 return {LB, UB};
4011}
4012
4013/// When dealing with dispatch schedules (e.g. dynamic, guided) we do not
4014/// consider the lower and upper bound expressions generated by the
4015/// worksharing loop support, but we use 0 and the iteration space size as
4016/// constants
4017static std::pair<llvm::Value *, llvm::Value *>
4019 Address LB, Address UB) {
4020 const auto &LS = cast<OMPLoopDirective>(S);
4021 const Expr *IVExpr = LS.getIterationVariable();
4022 const unsigned IVSize = CGF.getContext().getTypeSize(IVExpr->getType());
4023 llvm::Value *LBVal = CGF.Builder.getIntN(IVSize, 0);
4024 llvm::Value *UBVal = CGF.EmitScalarExpr(LS.getLastIteration());
4025 return {LBVal, UBVal};
4026}
4027
4028/// Emits internal temp array declarations for the directive with inscan
4029/// reductions.
4030/// The code is the following:
4031/// \code
4032/// size num_iters = <num_iters>;
4033/// <type> buffer[num_iters];
4034/// \endcode
4036 CodeGenFunction &CGF, const OMPLoopDirective &S,
4037 llvm::function_ref<llvm::Value *(CodeGenFunction &)> NumIteratorsGen) {
4038 llvm::Value *OMPScanNumIterations = CGF.Builder.CreateIntCast(
4039 NumIteratorsGen(CGF), CGF.SizeTy, /*isSigned=*/false);
4042 SmallVector<const Expr *, 4> ReductionOps;
4043 SmallVector<const Expr *, 4> CopyArrayTemps;
4044 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
4045 assert(C->getModifier() == OMPC_REDUCTION_inscan &&
4046 "Only inscan reductions are expected.");
4047 Shareds.append(C->varlist_begin(), C->varlist_end());
4048 Privates.append(C->privates().begin(), C->privates().end());
4049 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
4050 CopyArrayTemps.append(C->copy_array_temps().begin(),
4051 C->copy_array_temps().end());
4052 }
4053 {
4054 // Emit buffers for each reduction variables.
4055 // ReductionCodeGen is required to emit correctly the code for array
4056 // reductions.
4057 ReductionCodeGen RedCG(Shareds, Shareds, Privates, ReductionOps);
4058 unsigned Count = 0;
4059 auto *ITA = CopyArrayTemps.begin();
4060 for (const Expr *IRef : Privates) {
4061 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
4062 // Emit variably modified arrays, used for arrays/array sections
4063 // reductions.
4064 if (PrivateVD->getType()->isVariablyModifiedType()) {
4065 RedCG.emitSharedOrigLValue(CGF, Count);
4066 RedCG.emitAggregateType(CGF, Count);
4067 }
4069 CGF,
4071 cast<VariableArrayType>((*ITA)->getType()->getAsArrayTypeUnsafe())
4072 ->getSizeExpr()),
4073 RValue::get(OMPScanNumIterations));
4074 // Emit temp buffer.
4075 CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(*ITA)->getDecl()));
4076 ++ITA;
4077 ++Count;
4078 }
4079 }
4080}
4081
4082/// Copies final inscan reductions values to the original variables.
4083/// The code is the following:
4084/// \code
4085/// <orig_var> = buffer[num_iters-1];
4086/// \endcode
4088 CodeGenFunction &CGF, const OMPLoopDirective &S,
4089 llvm::function_ref<llvm::Value *(CodeGenFunction &)> NumIteratorsGen) {
4090 llvm::Value *OMPScanNumIterations = CGF.Builder.CreateIntCast(
4091 NumIteratorsGen(CGF), CGF.SizeTy, /*isSigned=*/false);
4097 SmallVector<const Expr *, 4> CopyArrayElems;
4098 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
4099 assert(C->getModifier() == OMPC_REDUCTION_inscan &&
4100 "Only inscan reductions are expected.");
4101 Shareds.append(C->varlist_begin(), C->varlist_end());
4102 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
4103 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
4104 Privates.append(C->privates().begin(), C->privates().end());
4105 CopyOps.append(C->copy_ops().begin(), C->copy_ops().end());
4106 CopyArrayElems.append(C->copy_array_elems().begin(),
4107 C->copy_array_elems().end());
4108 }
4109 // Create temp var and copy LHS value to this temp value.
4110 // LHS = TMP[LastIter];
4111 llvm::Value *OMPLast = CGF.Builder.CreateNSWSub(
4112 OMPScanNumIterations,
4113 llvm::ConstantInt::get(CGF.SizeTy, 1, /*isSigned=*/false));
4114 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4115 const Expr *PrivateExpr = Privates[I];
4116 const Expr *OrigExpr = Shareds[I];
4117 const Expr *CopyArrayElem = CopyArrayElems[I];
4119 CGF,
4121 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
4122 RValue::get(OMPLast));
4123 LValue DestLVal = CGF.EmitLValue(OrigExpr);
4124 LValue SrcLVal = CGF.EmitLValue(CopyArrayElem);
4125 CGF.EmitOMPCopy(
4126 PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4127 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
4128 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
4129 }
4130}
4131
4132/// Emits the code for the directive with inscan reductions.
4133/// The code is the following:
4134/// \code
4135/// #pragma omp ...
4136/// for (i: 0..<num_iters>) {
4137/// <input phase>;
4138/// buffer[i] = red;
4139/// }
4140/// #pragma omp master // in parallel region
4141/// for (int k = 0; k != ceil(log2(num_iters)); ++k)
4142/// for (size cnt = last_iter; cnt >= pow(2, k); --k)
4143/// buffer[i] op= buffer[i-pow(2,k)];
4144/// #pragma omp barrier // in parallel region
4145/// #pragma omp ...
4146/// for (0..<num_iters>) {
4147/// red = InclusiveScan ? buffer[i] : buffer[i-1];
4148/// <scan phase>;
4149/// }
4150/// \endcode
4152 CodeGenFunction &CGF, const OMPLoopDirective &S,
4153 llvm::function_ref<llvm::Value *(CodeGenFunction &)> NumIteratorsGen,
4154 llvm::function_ref<void(CodeGenFunction &)> FirstGen,
4155 llvm::function_ref<void(CodeGenFunction &)> SecondGen) {
4156 llvm::Value *OMPScanNumIterations = CGF.Builder.CreateIntCast(
4157 NumIteratorsGen(CGF), CGF.SizeTy, /*isSigned=*/false);
4159 SmallVector<const Expr *, 4> ReductionOps;
4162 SmallVector<const Expr *, 4> CopyArrayElems;
4163 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
4164 assert(C->getModifier() == OMPC_REDUCTION_inscan &&
4165 "Only inscan reductions are expected.");
4166 Privates.append(C->privates().begin(), C->privates().end());
4167 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
4168 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
4169 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
4170 CopyArrayElems.append(C->copy_array_elems().begin(),
4171 C->copy_array_elems().end());
4172 }
4174 {
4175 // Emit loop with input phase:
4176 // #pragma omp ...
4177 // for (i: 0..<num_iters>) {
4178 // <input phase>;
4179 // buffer[i] = red;
4180 // }
4181 CGF.OMPFirstScanLoop = true;
4183 FirstGen(CGF);
4184 }
4185 // #pragma omp barrier // in parallel region
4186 auto &&CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4187 &ReductionOps,
4188 &Privates](CodeGenFunction &CGF, PrePostActionTy &Action) {
4189 Action.Enter(CGF);
4190 // Emit prefix reduction:
4191 // #pragma omp master // in parallel region
4192 // for (int k = 0; k <= ceil(log2(n)); ++k)
4193 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4194 llvm::BasicBlock *LoopBB = CGF.createBasicBlock("omp.outer.log.scan.body");
4195 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("omp.outer.log.scan.exit");
4196 llvm::Function *F =
4197 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4198 llvm::Value *Arg =
4199 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4200 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4201 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4202 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4203 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4204 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4205 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4206 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, S.getBeginLoc());
4207 CGF.EmitBlock(LoopBB);
4208 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4209 // size pow2k = 1;
4210 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4211 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4212 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4213 // for (size i = n - 1; i >= 2 ^ k; --i)
4214 // tmp[i] op= tmp[i-pow2k];
4215 llvm::BasicBlock *InnerLoopBB =
4216 CGF.createBasicBlock("omp.inner.log.scan.body");
4217 llvm::BasicBlock *InnerExitBB =
4218 CGF.createBasicBlock("omp.inner.log.scan.exit");
4219 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4220 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4221 CGF.EmitBlock(InnerLoopBB);
4222 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4223 IVal->addIncoming(NMin1, LoopBB);
4224 {
4225 CodeGenFunction::OMPPrivateScope PrivScope(CGF);
4226 auto *ILHS = LHSs.begin();
4227 auto *IRHS = RHSs.begin();
4228 for (const Expr *CopyArrayElem : CopyArrayElems) {
4229 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4230 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4231 Address LHSAddr = Address::invalid();
4232 {
4234 CGF,
4236 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
4237 RValue::get(IVal));
4238 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4239 }
4240 PrivScope.addPrivate(LHSVD, LHSAddr);
4241 Address RHSAddr = Address::invalid();
4242 {
4243 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4245 CGF,
4247 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
4248 RValue::get(OffsetIVal));
4249 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4250 }
4251 PrivScope.addPrivate(RHSVD, RHSAddr);
4252 ++ILHS;
4253 ++IRHS;
4254 }
4255 PrivScope.Privatize();
4256 CGF.CGM.getOpenMPRuntime().emitReduction(
4257 CGF, S.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
4258 {/*WithNowait=*/true, /*SimpleReduction=*/true,
4259 /*IsPrivateVarReduction*/ {}, OMPD_unknown});
4260 }
4261 llvm::Value *NextIVal =
4262 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4263 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4264 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4265 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4266 CGF.EmitBlock(InnerExitBB);
4267 llvm::Value *Next =
4268 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4269 Counter->addIncoming(Next, CGF.Builder.GetInsertBlock());
4270 // pow2k <<= 1;
4271 llvm::Value *NextPow2K =
4272 CGF.Builder.CreateShl(Pow2K, 1, "", /*HasNUW=*/true);
4273 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4274 llvm::Value *Cmp = CGF.Builder.CreateICmpNE(Next, LogVal);
4275 CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
4276 auto DL1 = ApplyDebugLocation::CreateDefaultArtificial(CGF, S.getEndLoc());
4277 CGF.EmitBlock(ExitBB);
4278 };
4280 if (isOpenMPParallelDirective(EKind)) {
4281 CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc());
4283 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
4284 /*ForceSimpleCall=*/true);
4285 } else {
4286 RegionCodeGenTy RCG(CodeGen);
4287 RCG(CGF);
4288 }
4289
4290 CGF.OMPFirstScanLoop = false;
4291 SecondGen(CGF);
4292}
4293
4295 const OMPLoopDirective &S,
4296 bool HasCancel) {
4297 bool HasLastprivates;
4299 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4300 [](const OMPReductionClause *C) {
4301 return C->getModifier() == OMPC_REDUCTION_inscan;
4302 })) {
4303 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4305 OMPLoopScope LoopScope(CGF, S);
4306 return CGF.EmitScalarExpr(S.getNumIterations());
4307 };
4308 const auto &&FirstGen = [&S, HasCancel, EKind](CodeGenFunction &CGF) {
4309 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
4310 (void)CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
4313 // Emit an implicit barrier at the end.
4314 CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getBeginLoc(),
4315 OMPD_for);
4316 };
4317 const auto &&SecondGen = [&S, HasCancel, EKind,
4318 &HasLastprivates](CodeGenFunction &CGF) {
4319 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
4320 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
4323 };
4324 if (!isOpenMPParallelDirective(EKind))
4325 emitScanBasedDirectiveDecls(CGF, S, NumIteratorsGen);
4326 emitScanBasedDirective(CGF, S, NumIteratorsGen, FirstGen, SecondGen);
4327 if (!isOpenMPParallelDirective(EKind))
4328 emitScanBasedDirectiveFinals(CGF, S, NumIteratorsGen);
4329 } else {
4330 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
4331 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
4334 }
4335 return HasLastprivates;
4336}
4337
4338// Pass OMPLoopDirective (instead of OMPForDirective) to make this check
4339// available for "loop bind(parallel)", which maps to "for".
4341 bool HasCancel) {
4342 if (HasCancel)
4343 return false;
4344 for (OMPClause *C : S.clauses()) {
4346 continue;
4347
4348 if (auto *SC = dyn_cast<OMPScheduleClause>(C)) {
4349 if (SC->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown)
4350 return false;
4351 if (SC->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown)
4352 return false;
4353 switch (SC->getScheduleKind()) {
4354 case OMPC_SCHEDULE_auto:
4355 case OMPC_SCHEDULE_dynamic:
4356 case OMPC_SCHEDULE_runtime:
4357 case OMPC_SCHEDULE_guided:
4358 case OMPC_SCHEDULE_static:
4359 continue;
4361 return false;
4362 }
4363 }
4364
4365 return false;
4366 }
4367
4368 return true;
4369}
4370
4371static llvm::omp::ScheduleKind
4373 switch (ScheduleClauseKind) {
4375 return llvm::omp::OMP_SCHEDULE_Default;
4376 case OMPC_SCHEDULE_auto:
4377 return llvm::omp::OMP_SCHEDULE_Auto;
4378 case OMPC_SCHEDULE_dynamic:
4379 return llvm::omp::OMP_SCHEDULE_Dynamic;
4380 case OMPC_SCHEDULE_guided:
4381 return llvm::omp::OMP_SCHEDULE_Guided;
4382 case OMPC_SCHEDULE_runtime:
4383 return llvm::omp::OMP_SCHEDULE_Runtime;
4384 case OMPC_SCHEDULE_static:
4385 return llvm::omp::OMP_SCHEDULE_Static;
4386 }
4387 llvm_unreachable("Unhandled schedule kind");
4388}
4389
4390// Pass OMPLoopDirective (instead of OMPForDirective) to make this function
4391// available for "loop bind(parallel)", which maps to "for".
4393 CodeGenModule &CGM, bool HasCancel) {
4394 bool HasLastprivates = false;
4395 bool UseOMPIRBuilder = CGM.getLangOpts().OpenMPIRBuilder &&
4396 isForSupportedByOpenMPIRBuilder(S, HasCancel);
4397 auto &&CodeGen = [&S, &CGM, HasCancel, &HasLastprivates,
4398 UseOMPIRBuilder](CodeGenFunction &CGF, PrePostActionTy &) {
4399 // Use the OpenMPIRBuilder if enabled.
4400 if (UseOMPIRBuilder) {
4401 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4402
4403 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4404 llvm::Value *ChunkSize = nullptr;
4405 if (auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4406 SchedKind =
4407 convertClauseKindToSchedKind(SchedClause->getScheduleKind());
4408 if (const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4409 ChunkSize = CGF.EmitScalarExpr(ChunkSizeExpr);
4410 }
4411
4412 // Emit the associated statement and get its loop representation.
4413 const Stmt *Inner = S.getRawStmt();
4414 llvm::CanonicalLoopInfo *CLI =
4416
4417 llvm::OpenMPIRBuilder &OMPBuilder =
4419 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4420 CGF.AllocaInsertPt->getParent(), CGF.AllocaInsertPt->getIterator());
4421 cantFail(OMPBuilder.applyWorkshareLoop(
4422 CGF.Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4423 SchedKind, ChunkSize, /*HasSimdModifier=*/false,
4424 /*HasMonotonicModifier=*/false, /*HasNonmonotonicModifier=*/false,
4425 /*HasOrderedClause=*/false));
4426 return;
4427 }
4428
4429 HasLastprivates = emitWorksharingDirective(CGF, S, HasCancel);
4430 };
4431 {
4432 auto LPCRegion =
4434 OMPLexicalScope Scope(CGF, S, OMPD_unknown);
4436 HasCancel);
4437 }
4438
4439 if (!UseOMPIRBuilder) {
4440 // Emit an implicit barrier at the end.
4441 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4442 CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getBeginLoc(), OMPD_for);
4443 }
4444 // Check for outer lastprivate conditional update.
4446}
4447
4448void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
4449 return emitOMPForDirective(S, *this, CGM, S.hasCancel());
4450}
4451
4452void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
4453 bool HasLastprivates = false;
4454 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4455 PrePostActionTy &) {
4456 HasLastprivates = emitWorksharingDirective(CGF, S, /*HasCancel=*/false);
4457 };
4458 {
4459 auto LPCRegion =
4461 OMPLexicalScope Scope(*this, S, OMPD_unknown);
4462 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
4463 }
4464
4465 // Emit an implicit barrier at the end.
4466 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4467 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
4468 // Check for outer lastprivate conditional update.
4470}
4471
4473 const Twine &Name,
4474 llvm::Value *Init = nullptr) {
4475 LValue LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
4476 if (Init)
4477 CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true);
4478 return LVal;
4479}
4480
4481void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
4482 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4483 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4484 bool HasLastprivates = false;
4486 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4487 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4488 const ASTContext &C = CGF.getContext();
4489 QualType KmpInt32Ty =
4490 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
4491 // Emit helper vars inits.
4492 LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
4493 CGF.Builder.getInt32(0));
4494 llvm::ConstantInt *GlobalUBVal = CS != nullptr
4495 ? CGF.Builder.getInt32(CS->size() - 1)
4496 : CGF.Builder.getInt32(0);
4497 LValue UB =
4498 createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
4499 LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
4500 CGF.Builder.getInt32(1));
4501 LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.",
4502 CGF.Builder.getInt32(0));
4503 // Loop counter.
4504 LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
4505 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
4506 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4507 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
4508 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4509 // Generate condition for loop.
4510 BinaryOperator *Cond = BinaryOperator::Create(
4511 C, &IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_PRValue, OK_Ordinary,
4512 S.getBeginLoc(), FPOptionsOverride());
4513 // Increment for loop counter.
4514 UnaryOperator *Inc = UnaryOperator::Create(
4515 C, &IVRefExpr, UO_PreInc, KmpInt32Ty, VK_PRValue, OK_Ordinary,
4516 S.getBeginLoc(), true, FPOptionsOverride());
4517 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4518 // Iterate through all sections and emit a switch construct:
4519 // switch (IV) {
4520 // case 0:
4521 // <SectionStmt[0]>;
4522 // break;
4523 // ...
4524 // case <NumSection> - 1:
4525 // <SectionStmt[<NumSection> - 1]>;
4526 // break;
4527 // }
4528 // .omp.sections.exit:
4529 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
4530 llvm::SwitchInst *SwitchStmt =
4531 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getBeginLoc()),
4532 ExitBB, CS == nullptr ? 1 : CS->size());
4533 if (CS) {
4534 unsigned CaseNumber = 0;
4535 for (const Stmt *SubStmt : CS->children()) {
4536 auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
4537 CGF.EmitBlock(CaseBB);
4538 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4539 CGF.EmitStmt(SubStmt);
4540 CGF.EmitBranch(ExitBB);
4541 ++CaseNumber;
4542 }
4543 } else {
4544 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(".omp.sections.case");
4545 CGF.EmitBlock(CaseBB);
4546 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4547 CGF.EmitStmt(CapturedStmt);
4548 CGF.EmitBranch(ExitBB);
4549 }
4550 CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
4551 };
4552
4553 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4554 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4555 // Emit implicit barrier to synchronize threads and avoid data races on
4556 // initialization of firstprivate variables and post-update of lastprivate
4557 // variables.
4558 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4559 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
4560 /*ForceSimpleCall=*/true);
4561 }
4562 CGF.EmitOMPPrivateClause(S, LoopScope);
4563 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4564 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4565 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4566 (void)LoopScope.Privatize();
4568 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4569
4570 // Emit static non-chunked loop.
4571 OpenMPScheduleTy ScheduleKind;
4572 ScheduleKind.Schedule = OMPC_SCHEDULE_static;
4573 CGOpenMPRuntime::StaticRTInput StaticInit(
4574 /*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(),
4575 LB.getAddress(), UB.getAddress(), ST.getAddress());
4576 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.getBeginLoc(), EKind,
4577 ScheduleKind, StaticInit);
4578 // UB = min(UB, GlobalUB);
4579 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getBeginLoc());
4580 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4581 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4582 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4583 // IV = LB;
4584 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV);
4585 // while (idx <= UB) { BODY; ++idx; }
4586 CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, Cond, Inc, BodyGen,
4587 [](CodeGenFunction &) {});
4588 // Tell the runtime we are done.
4589 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4590 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
4591 OMPD_sections);
4592 };
4593 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4594 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
4595 // Emit post-update of the reduction variables if IsLastIter != 0.
4596 emitPostUpdateForReductionClause(CGF, S, [IL, &S](CodeGenFunction &CGF) {
4597 return CGF.Builder.CreateIsNotNull(
4598 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
4599 });
4600
4601 // Emit final copy of the lastprivate variables if IsLastIter != 0.
4602 if (HasLastprivates)
4604 S, /*NoFinals=*/false,
4605 CGF.Builder.CreateIsNotNull(
4606 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())));
4607 };
4608
4609 bool HasCancel = false;
4610 if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4611 HasCancel = OSD->hasCancel();
4612 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4613 HasCancel = OPSD->hasCancel();
4614 OMPCancelStackRAII CancelRegion(*this, EKind, HasCancel);
4615 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen,
4616 HasCancel);
4617 // Emit barrier for lastprivates only if 'sections' directive has 'nowait'
4618 // clause. Otherwise the barrier will be generated by the codegen for the
4619 // directive.
4620 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4621 // Emit implicit barrier to synchronize threads and avoid data races on
4622 // initialization of firstprivate variables.
4623 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
4624 OMPD_unknown);
4625 }
4626}
4627
4628void CodeGenFunction::EmitOMPScopeDirective(const OMPScopeDirective &S) {
4629 {
4630 // Emit code for 'scope' region
4631 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4632 Action.Enter(CGF);
4633 OMPPrivateScope PrivateScope(CGF);
4634 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4635 CGF.EmitOMPPrivateClause(S, PrivateScope);
4636 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4637 (void)PrivateScope.Privatize();
4638 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4639 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
4640 };
4641 auto LPCRegion =
4643 OMPLexicalScope Scope(*this, S, OMPD_unknown);
4644 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_scope, CodeGen);
4645 }
4646 // Emit an implicit barrier at the end.
4647 if (!S.getSingleClause<OMPNowaitClause>()) {
4648 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_scope);
4649 }
4650 // Check for outer lastprivate conditional update.
4652}
4653
4654void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
4655 if (CGM.getLangOpts().OpenMPIRBuilder) {
4656 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
4657 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4658 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4659
4660 auto FiniCB = [](InsertPointTy IP) {
4661 // Don't FinalizeOMPRegion because this is done inside of OMPIRBuilder for
4662 // sections.
4663 return llvm::Error::success();
4664 };
4665
4666 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4667 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4668 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4670 if (CS) {
4671 for (const Stmt *SubStmt : CS->children()) {
4672 auto SectionCB = [this, SubStmt](InsertPointTy AllocaIP,
4673 InsertPointTy CodeGenIP) {
4675 *this, SubStmt, AllocaIP, CodeGenIP, "section");
4676 return llvm::Error::success();
4677 };
4678 SectionCBVector.push_back(SectionCB);
4679 }
4680 } else {
4681 auto SectionCB = [this, CapturedStmt](InsertPointTy AllocaIP,
4682 InsertPointTy CodeGenIP) {
4684 *this, CapturedStmt, AllocaIP, CodeGenIP, "section");
4685 return llvm::Error::success();
4686 };
4687 SectionCBVector.push_back(SectionCB);
4688 }
4689
4690 // Privatization callback that performs appropriate action for
4691 // shared/private/firstprivate/lastprivate/copyin/... variables.
4692 //
4693 // TODO: This defaults to shared right now.
4694 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4695 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4696 // The next line is appropriate only for variables (Val) with the
4697 // data-sharing attribute "shared".
4698 ReplVal = &Val;
4699
4700 return CodeGenIP;
4701 };
4702
4703 CGCapturedStmtInfo CGSI(*ICS, CR_OpenMP);
4704 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
4705 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4706 AllocaInsertPt->getParent(), AllocaInsertPt->getIterator());
4707 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4708 cantFail(OMPBuilder.createSections(
4709 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4710 S.getSingleClause<OMPNowaitClause>()));
4711 Builder.restoreIP(AfterIP);
4712 return;
4713 }
4714 {
4715 auto LPCRegion =
4717 OMPLexicalScope Scope(*this, S, OMPD_unknown);
4718 EmitSections(S);
4719 }
4720 // Emit an implicit barrier at the end.
4721 if (!S.getSingleClause<OMPNowaitClause>()) {
4722 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
4723 OMPD_sections);
4724 }
4725 // Check for outer lastprivate conditional update.
4727}
4728
4729void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
4730 if (CGM.getLangOpts().OpenMPIRBuilder) {
4731 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
4732 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4733
4734 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4735 auto FiniCB = [this](InsertPointTy IP) {
4737 return llvm::Error::success();
4738 };
4739
4740 auto BodyGenCB = [SectionRegionBodyStmt, this](InsertPointTy AllocaIP,
4741 InsertPointTy CodeGenIP) {
4743 *this, SectionRegionBodyStmt, AllocaIP, CodeGenIP, "section");
4744 return llvm::Error::success();
4745 };
4746
4747 LexicalScope Scope(*this, S.getSourceRange());
4748 EmitStopPoint(&S);
4749 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4750 cantFail(OMPBuilder.createSection(Builder, BodyGenCB, FiniCB));
4751 Builder.restoreIP(AfterIP);
4752
4753 return;
4754 }
4755 LexicalScope Scope(*this, S.getSourceRange());
4756 EmitStopPoint(&S);
4757 EmitStmt(S.getAssociatedStmt());
4758}
4759
4760void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
4761 llvm::SmallVector<const Expr *, 8> CopyprivateVars;
4765 // Check if there are any 'copyprivate' clauses associated with this
4766 // 'single' construct.
4767 // Build a list of copyprivate variables along with helper expressions
4768 // (<source>, <destination>, <destination>=<source> expressions)
4769 for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) {
4770 CopyprivateVars.append(C->varlist_begin(), C->varlist_end());
4771 DestExprs.append(C->destination_exprs().begin(),
4772 C->destination_exprs().end());
4773 SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end());
4774 AssignmentOps.append(C->assignment_ops().begin(),
4775 C->assignment_ops().end());
4776 }
4777 // Emit code for 'single' region along with 'copyprivate' clauses
4778 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4779 Action.Enter(CGF);
4783 (void)SingleScope.Privatize();
4784 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4785 };
4786 {
4787 auto LPCRegion =
4789 OMPLexicalScope Scope(*this, S, OMPD_unknown);
4790 CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getBeginLoc(),
4791 CopyprivateVars, DestExprs,
4792 SrcExprs, AssignmentOps);
4793 }
4794 // Emit an implicit barrier at the end (to avoid data race on firstprivate
4795 // init or if no 'nowait' clause was specified and no 'copyprivate' clause).
4796 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4797 CGM.getOpenMPRuntime().emitBarrierCall(
4798 *this, S.getBeginLoc(),
4799 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4800 }
4801 // Check for outer lastprivate conditional update.
4803}
4804
4806 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4807 Action.Enter(CGF);
4808 CGF.EmitStmt(S.getRawStmt());
4809 };
4810 CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc());
4811}
4812
4813void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
4814 if (CGM.getLangOpts().OpenMPIRBuilder) {
4815 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
4816 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4817
4818 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4819
4820 auto FiniCB = [this](InsertPointTy IP) {
4822 return llvm::Error::success();
4823 };
4824
4825 auto BodyGenCB = [MasterRegionBodyStmt, this](InsertPointTy AllocaIP,
4826 InsertPointTy CodeGenIP) {
4828 *this, MasterRegionBodyStmt, AllocaIP, CodeGenIP, "master");
4829 return llvm::Error::success();
4830 };
4831
4832 LexicalScope Scope(*this, S.getSourceRange());
4833 EmitStopPoint(&S);
4834 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4835 cantFail(OMPBuilder.createMaster(Builder, BodyGenCB, FiniCB));
4836 Builder.restoreIP(AfterIP);
4837
4838 return;
4839 }
4840 LexicalScope Scope(*this, S.getSourceRange());
4841 EmitStopPoint(&S);
4842 emitMaster(*this, S);
4843}
4844
4846 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4847 Action.Enter(CGF);
4848 CGF.EmitStmt(S.getRawStmt());
4849 };
4850 Expr *Filter = nullptr;
4851 if (const auto *FilterClause = S.getSingleClause<OMPFilterClause>())
4852 Filter = FilterClause->getThreadID();
4853 CGF.CGM.getOpenMPRuntime().emitMaskedRegion(CGF, CodeGen, S.getBeginLoc(),
4854 Filter);
4855}
4856
4858 if (CGM.getLangOpts().OpenMPIRBuilder) {
4859 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
4860 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4861
4862 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4863 const Expr *Filter = nullptr;
4864 if (const auto *FilterClause = S.getSingleClause<OMPFilterClause>())
4865 Filter = FilterClause->getThreadID();
4866 llvm::Value *FilterVal = Filter
4867 ? EmitScalarExpr(Filter, CGM.Int32Ty)
4868 : llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/0);
4869
4870 auto FiniCB = [this](InsertPointTy IP) {
4872 return llvm::Error::success();
4873 };
4874
4875 auto BodyGenCB = [MaskedRegionBodyStmt, this](InsertPointTy AllocaIP,
4876 InsertPointTy CodeGenIP) {
4878 *this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP, "masked");
4879 return llvm::Error::success();
4880 };
4881
4882 LexicalScope Scope(*this, S.getSourceRange());
4883 EmitStopPoint(&S);
4884 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4885 OMPBuilder.createMasked(Builder, BodyGenCB, FiniCB, FilterVal));
4886 Builder.restoreIP(AfterIP);
4887
4888 return;
4889 }
4890 LexicalScope Scope(*this, S.getSourceRange());
4891 EmitStopPoint(&S);
4892 emitMasked(*this, S);
4893}
4894
4895void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
4896 if (CGM.getLangOpts().OpenMPIRBuilder) {
4897 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
4898 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4899
4900 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4901 const Expr *Hint = nullptr;
4902 if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
4903 Hint = HintClause->getHint();
4904
4905 // TODO: This is slightly different from what's currently being done in
4906 // clang. Fix the Int32Ty to IntPtrTy (pointer width size) when everything
4907 // about typing is final.
4908 llvm::Value *HintInst = nullptr;
4909 if (Hint)
4910 HintInst =
4911 Builder.CreateIntCast(EmitScalarExpr(Hint), CGM.Int32Ty, false);
4912
4913 auto FiniCB = [this](InsertPointTy IP) {
4915 return llvm::Error::success();
4916 };
4917
4918 auto BodyGenCB = [CriticalRegionBodyStmt, this](InsertPointTy AllocaIP,
4919 InsertPointTy CodeGenIP) {
4921 *this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP, "critical");
4922 return llvm::Error::success();
4923 };
4924
4925 LexicalScope Scope(*this, S.getSourceRange());
4926 EmitStopPoint(&S);
4927 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4928 cantFail(OMPBuilder.createCritical(Builder, BodyGenCB, FiniCB,
4929 S.getDirectiveName().getAsString(),
4930 HintInst));
4931 Builder.restoreIP(AfterIP);
4932
4933 return;
4934 }
4935
4936 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4937 Action.Enter(CGF);
4938 CGF.EmitStmt(S.getAssociatedStmt());
4939 };
4940 const Expr *Hint = nullptr;
4941 if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
4942 Hint = HintClause->getHint();
4943 LexicalScope Scope(*this, S.getSourceRange());
4944 EmitStopPoint(&S);
4945 CGM.getOpenMPRuntime().emitCriticalRegion(*this,
4946 S.getDirectiveName().getAsString(),
4947 CodeGen, S.getBeginLoc(), Hint);
4948}
4949
4951 const OMPParallelForDirective &S) {
4952 // Emit directive as a combined directive that consists of two implicit
4953 // directives: 'parallel' with 'for' directive.
4954 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4955 Action.Enter(CGF);
4956 emitOMPCopyinClause(CGF, S);
4957 (void)emitWorksharingDirective(CGF, S, S.hasCancel());
4958 };
4959 {
4960 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4963 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGSI);
4964 OMPLoopScope LoopScope(CGF, S);
4965 return CGF.EmitScalarExpr(S.getNumIterations());
4966 };
4967 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4968 [](const OMPReductionClause *C) {
4969 return C->getModifier() == OMPC_REDUCTION_inscan;
4970 });
4971 if (IsInscan)
4972 emitScanBasedDirectiveDecls(*this, S, NumIteratorsGen);
4973 auto LPCRegion =
4975 emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen,
4977 if (IsInscan)
4978 emitScanBasedDirectiveFinals(*this, S, NumIteratorsGen);
4979 }
4980 // Check for outer lastprivate conditional update.
4982}
4983
4985 const OMPParallelForSimdDirective &S) {
4986 // Emit directive as a combined directive that consists of two implicit
4987 // directives: 'parallel' with 'for' directive.
4988 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4989 Action.Enter(CGF);
4990 emitOMPCopyinClause(CGF, S);
4991 (void)emitWorksharingDirective(CGF, S, /*HasCancel=*/false);
4992 };
4993 {
4994 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4997 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGSI);
4998 OMPLoopScope LoopScope(CGF, S);
4999 return CGF.EmitScalarExpr(S.getNumIterations());
5000 };
5001 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5002 [](const OMPReductionClause *C) {
5003 return C->getModifier() == OMPC_REDUCTION_inscan;
5004 });
5005 if (IsInscan)
5006 emitScanBasedDirectiveDecls(*this, S, NumIteratorsGen);
5007 auto LPCRegion =
5009 emitCommonOMPParallelDirective(*this, S, OMPD_for_simd, CodeGen,
5011 if (IsInscan)
5012 emitScanBasedDirectiveFinals(*this, S, NumIteratorsGen);
5013 }
5014 // Check for outer lastprivate conditional update.
5016}
5017
5019 const OMPParallelMasterDirective &S) {
5020 // Emit directive as a combined directive that consists of two implicit
5021 // directives: 'parallel' with 'master' directive.
5022 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5023 Action.Enter(CGF);
5024 OMPPrivateScope PrivateScope(CGF);
5025 emitOMPCopyinClause(CGF, S);
5026 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
5027 CGF.EmitOMPPrivateClause(S, PrivateScope);
5028 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5029 (void)PrivateScope.Privatize();
5030 emitMaster(CGF, S);
5031 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
5032 };
5033 {
5034 auto LPCRegion =
5036 emitCommonOMPParallelDirective(*this, S, OMPD_master, CodeGen,
5039 [](CodeGenFunction &) { return nullptr; });
5040 }
5041 // Check for outer lastprivate conditional update.
5043}
5044
5046 const OMPParallelMaskedDirective &S) {
5047 // Emit directive as a combined directive that consists of two implicit
5048 // directives: 'parallel' with 'masked' directive.
5049 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5050 Action.Enter(CGF);
5051 OMPPrivateScope PrivateScope(CGF);
5052 emitOMPCopyinClause(CGF, S);
5053 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
5054 CGF.EmitOMPPrivateClause(S, PrivateScope);
5055 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5056 (void)PrivateScope.Privatize();
5057 emitMasked(CGF, S);
5058 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
5059 };
5060 {
5061 auto LPCRegion =
5063 emitCommonOMPParallelDirective(*this, S, OMPD_masked, CodeGen,
5066 [](CodeGenFunction &) { return nullptr; });
5067 }
5068 // Check for outer lastprivate conditional update.
5070}
5071
5073 const OMPParallelSectionsDirective &S) {
5074 // Emit directive as a combined directive that consists of two implicit
5075 // directives: 'parallel' with 'sections' directive.
5076 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5077 Action.Enter(CGF);
5078 emitOMPCopyinClause(CGF, S);
5079 CGF.EmitSections(S);
5080 };
5081 {
5082 auto LPCRegion =
5084 emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen,
5086 }
5087 // Check for outer lastprivate conditional update.
5089}
5090
5091namespace {
5092/// Get the list of variables declared in the context of the untied tasks.
5093class CheckVarsEscapingUntiedTaskDeclContext final
5094 : public ConstStmtVisitor<CheckVarsEscapingUntiedTaskDeclContext> {
5096
5097public:
5098 explicit CheckVarsEscapingUntiedTaskDeclContext() = default;
5099 ~CheckVarsEscapingUntiedTaskDeclContext() = default;
5100 void VisitDeclStmt(const DeclStmt *S) {
5101 if (!S)
5102 return;
5103 // Need to privatize only local vars, static locals can be processed as is.
5104 for (const Decl *D : S->decls()) {
5105 if (const auto *VD = dyn_cast_or_null<VarDecl>(D))
5106 if (VD->hasLocalStorage())
5107 PrivateDecls.push_back(VD);
5108 }
5109 }
5110 void VisitOMPExecutableDirective(const OMPExecutableDirective *) {}
5111 void VisitCapturedStmt(const CapturedStmt *) {}
5112 void VisitLambdaExpr(const LambdaExpr *) {}
5113 void VisitBlockExpr(const BlockExpr *) {}
5114 void VisitStmt(const Stmt *S) {
5115 if (!S)
5116 return;
5117 for (const Stmt *Child : S->children())
5118 if (Child)
5119 Visit(Child);
5120 }
5121
5122 /// Swaps list of vars with the provided one.
5123 ArrayRef<const VarDecl *> getPrivateDecls() const { return PrivateDecls; }
5124};
5125} // anonymous namespace
5126
5129
5130 // First look for 'omp_all_memory' and add this first.
5131 bool OmpAllMemory = false;
5132 if (llvm::any_of(
5133 S.getClausesOfKind<OMPDependClause>(), [](const OMPDependClause *C) {
5134 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5135 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5136 })) {
5137 OmpAllMemory = true;
5138 // Since both OMPC_DEPEND_outallmemory and OMPC_DEPEND_inoutallmemory are
5139 // equivalent to the runtime, always use OMPC_DEPEND_outallmemory to
5140 // simplify.
5142 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5143 /*IteratorExpr=*/nullptr);
5144 // Add a nullptr Expr to simplify the codegen in emitDependData.
5145 DD.DepExprs.push_back(nullptr);
5146 }
5147 // Add remaining dependences skipping any 'out' or 'inout' if they are
5148 // overridden by 'omp_all_memory'.
5149 for (const auto *C : S.getClausesOfKind<OMPDependClause>()) {
5150 OpenMPDependClauseKind Kind = C->getDependencyKind();
5151 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5152 continue;
5153 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5154 continue;
5156 Data.Dependences.emplace_back(C->getDependencyKind(), C->getModifier());
5157 DD.DepExprs.append(C->varlist_begin(), C->varlist_end());
5158 }
5159}
5160
5162 const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion,
5163 const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen,
5165 // Emit outlined function for task construct.
5166 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5167 auto I = CS->getCapturedDecl()->param_begin();
5168 auto PartId = std::next(I);
5169 auto TaskT = std::next(I, 4);
5170 // Check if the task is final
5171 if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
5172 // If the condition constant folds and can be elided, try to avoid emitting
5173 // the condition and the dead arm of the if/else.
5174 const Expr *Cond = Clause->getCondition();
5175 bool CondConstant;
5176 if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
5177 Data.Final.setInt(CondConstant);
5178 else
5179 Data.Final.setPointer(EvaluateExprAsBool(Cond));
5180 } else {
5181 // By default the task is not final.
5182 Data.Final.setInt(/*IntVal=*/false);
5183 }
5184 // Check if the task has 'priority' clause.
5185 if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) {
5186 const Expr *Prio = Clause->getPriority();
5187 Data.Priority.setInt(/*IntVal=*/true);
5188 Data.Priority.setPointer(EmitScalarConversion(
5189 EmitScalarExpr(Prio), Prio->getType(),
5190 getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
5191 Prio->getExprLoc()));
5192 }
5193 // The first function argument for tasks is a thread id, the second one is a
5194 // part id (0 for tied tasks, >=0 for untied task).
5195 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
5196 // Get list of private variables.
5197 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
5198 auto IRef = C->varlist_begin();
5199 for (const Expr *IInit : C->private_copies()) {
5200 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
5201 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5202 Data.PrivateVars.push_back(*IRef);
5203 Data.PrivateCopies.push_back(IInit);
5204 }
5205 ++IRef;
5206 }
5207 }
5208 EmittedAsPrivate.clear();
5209 // Get list of firstprivate variables.
5210 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5211 auto IRef = C->varlist_begin();
5212 auto IElemInitRef = C->inits().begin();
5213 for (const Expr *IInit : C->private_copies()) {
5214 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
5215 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5216 Data.FirstprivateVars.push_back(*IRef);
5217 Data.FirstprivateCopies.push_back(IInit);
5218 Data.FirstprivateInits.push_back(*IElemInitRef);
5219 }
5220 ++IRef;
5221 ++IElemInitRef;
5222 }
5223 }
5224 // Get list of lastprivate variables (for taskloops).
5225 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5226 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
5227 auto IRef = C->varlist_begin();
5228 auto ID = C->destination_exprs().begin();
5229 for (const Expr *IInit : C->private_copies()) {
5230 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
5231 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5232 Data.LastprivateVars.push_back(*IRef);
5233 Data.LastprivateCopies.push_back(IInit);
5234 }
5235 LastprivateDstsOrigs.insert(
5236 std::make_pair(cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
5237 cast<DeclRefExpr>(*IRef)));
5238 ++IRef;
5239 ++ID;
5240 }
5241 }
5244 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
5245 Data.ReductionVars.append(C->varlist_begin(), C->varlist_end());
5246 Data.ReductionOrigs.append(C->varlist_begin(), C->varlist_end());
5247 Data.ReductionCopies.append(C->privates().begin(), C->privates().end());
5248 Data.ReductionOps.append(C->reduction_ops().begin(),
5249 C->reduction_ops().end());
5250 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
5251 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
5252 }
5253 Data.Reductions = CGM.getOpenMPRuntime().emitTaskReductionInit(
5254 *this, S.getBeginLoc(), LHSs, RHSs, Data);
5255 // Build list of dependences.
5257 // Get list of local vars for untied tasks.
5258 if (!Data.Tied) {
5259 CheckVarsEscapingUntiedTaskDeclContext Checker;
5260 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5261 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5262 Checker.getPrivateDecls().end());
5263 }
5264 auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5265 CapturedRegion](CodeGenFunction &CGF,
5266 PrePostActionTy &Action) {
5267 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5268 std::pair<Address, Address>>
5269 UntiedLocalVars;
5270 // Set proper addresses for generated private copies.
5272 // Generate debug info for variables present in shared clause.
5273 if (auto *DI = CGF.getDebugInfo()) {
5274 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5275 CGF.CapturedStmtInfo->getCaptureFields();
5276 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5277 if (CaptureFields.size() && ContextValue) {
5278 unsigned CharWidth = CGF.getContext().getCharWidth();
5279 // The shared variables are packed together as members of structure.
5280 // So the address of each shared variable can be computed by adding
5281 // offset of it (within record) to the base address of record. For each
5282 // shared variable, debug intrinsic llvm.dbg.declare is generated with
5283 // appropriate expressions (DIExpression).
5284 // Ex:
5285 // %12 = load %struct.anon*, %struct.anon** %__context.addr.i
5286 // call void @llvm.dbg.declare(metadata %struct.anon* %12,
5287 // metadata !svar1,
5288 // metadata !DIExpression(DW_OP_deref))
5289 // call void @llvm.dbg.declare(metadata %struct.anon* %12,
5290 // metadata !svar2,
5291 // metadata !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref))
5292 for (auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5293 const VarDecl *SharedVar = It->first;
5294 RecordDecl *CaptureRecord = It->second->getParent();
5295 const ASTRecordLayout &Layout =
5296 CGF.getContext().getASTRecordLayout(CaptureRecord);
5297 unsigned Offset =
5298 Layout.getFieldOffset(It->second->getFieldIndex()) / CharWidth;
5299 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5300 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5301 CGF.Builder, false);
5302 // Get the call dbg.declare instruction we just created and update
5303 // its DIExpression to add offset to base address.
5304 auto UpdateExpr = [](llvm::LLVMContext &Ctx, auto *Declare,
5305 unsigned Offset) {
5307 // Add offset to the base address if non zero.
5308 if (Offset) {
5309 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5310 Ops.push_back(Offset);
5311 }
5312 Ops.push_back(llvm::dwarf::DW_OP_deref);
5313 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5314 };
5315 llvm::Instruction &Last = CGF.Builder.GetInsertBlock()->back();
5316 if (auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&Last))
5317 UpdateExpr(DDI->getContext(), DDI, Offset);
5318 // If we're emitting using the new debug info format into a block
5319 // without a terminator, the record will be "trailing".
5320 assert(!Last.isTerminator() && "unexpected terminator");
5321 if (auto *Marker =
5322 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5323 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5324 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5325 UpdateExpr(Last.getContext(), &DVR, Offset);
5326 break;
5327 }
5328 }
5329 }
5330 }
5331 }
5333 if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() ||
5334 !Data.LastprivateVars.empty() || !Data.PrivateLocals.empty()) {
5335 enum { PrivatesParam = 2, CopyFnParam = 3 };
5336 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5337 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
5338 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5339 CS->getCapturedDecl()->getParam(PrivatesParam)));
5340 // Map privates.
5344 CallArgs.push_back(PrivatesPtr);
5345 ParamTypes.push_back(PrivatesPtr->getType());
5346 for (const Expr *E : Data.PrivateVars) {
5347 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5348 RawAddress PrivatePtr = CGF.CreateMemTemp(
5349 CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr");
5350 PrivatePtrs.emplace_back(VD, PrivatePtr);
5351 CallArgs.push_back(PrivatePtr.getPointer());
5352 ParamTypes.push_back(PrivatePtr.getType());
5353 }
5354 for (const Expr *E : Data.FirstprivateVars) {
5355 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5356 RawAddress PrivatePtr =
5357 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
5358 ".firstpriv.ptr.addr");
5359 PrivatePtrs.emplace_back(VD, PrivatePtr);
5360 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5361 CallArgs.push_back(PrivatePtr.getPointer());
5362 ParamTypes.push_back(PrivatePtr.getType());
5363 }
5364 for (const Expr *E : Data.LastprivateVars) {
5365 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5366 RawAddress PrivatePtr =
5367 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
5368 ".lastpriv.ptr.addr");
5369 PrivatePtrs.emplace_back(VD, PrivatePtr);
5370 CallArgs.push_back(PrivatePtr.getPointer());
5371 ParamTypes.push_back(PrivatePtr.getType());
5372 }
5373 for (const VarDecl *VD : Data.PrivateLocals) {
5375 if (VD->getType()->isLValueReferenceType())
5376 Ty = CGF.getContext().getPointerType(Ty);
5377 if (isAllocatableDecl(VD))
5378 Ty = CGF.getContext().getPointerType(Ty);
5379 RawAddress PrivatePtr = CGF.CreateMemTemp(
5380 CGF.getContext().getPointerType(Ty), ".local.ptr.addr");
5381 auto Result = UntiedLocalVars.insert(
5382 std::make_pair(VD, std::make_pair(PrivatePtr, Address::invalid())));
5383 // If key exists update in place.
5384 if (Result.second == false)
5385 *Result.first = std::make_pair(
5386 VD, std::make_pair(PrivatePtr, Address::invalid()));
5387 CallArgs.push_back(PrivatePtr.getPointer());
5388 ParamTypes.push_back(PrivatePtr.getType());
5389 }
5390 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5391 ParamTypes, /*isVarArg=*/false);
5392 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5393 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5394 for (const auto &Pair : LastprivateDstsOrigs) {
5395 const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
5396 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(OrigVD),
5397 /*RefersToEnclosingVariableOrCapture=*/
5398 CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,
5399 Pair.second->getType(), VK_LValue,
5400 Pair.second->getExprLoc());
5401 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5402 }
5403 for (const auto &Pair : PrivatePtrs) {
5404 Address Replacement = Address(
5405 CGF.Builder.CreateLoad(Pair.second),
5406 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5407 CGF.getContext().getDeclAlign(Pair.first));
5408 Scope.addPrivate(Pair.first, Replacement);
5409 if (auto *DI = CGF.getDebugInfo())
5410 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5411 (void)DI->EmitDeclareOfAutoVariable(
5412 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5413 /*UsePointerValue*/ true);
5414 }
5415 // Adjust mapping for internal locals by mapping actual memory instead of
5416 // a pointer to this memory.
5417 for (auto &Pair : UntiedLocalVars) {
5418 QualType VDType = Pair.first->getType().getNonReferenceType();
5419 if (Pair.first->getType()->isLValueReferenceType())
5420 VDType = CGF.getContext().getPointerType(VDType);
5421 if (isAllocatableDecl(Pair.first)) {
5422 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5423 Address Replacement(
5424 Ptr,
5425 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5426 CGF.getPointerAlign());
5427 Pair.second.first = Replacement;
5428 Ptr = CGF.Builder.CreateLoad(Replacement);
5429 Replacement = Address(Ptr, CGF.ConvertTypeForMem(VDType),
5430 CGF.getContext().getDeclAlign(Pair.first));
5431 Pair.second.second = Replacement;
5432 } else {
5433 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5434 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5435 CGF.getContext().getDeclAlign(Pair.first));
5436 Pair.second.first = Replacement;
5437 }
5438 }
5439 }
5440 if (Data.Reductions) {
5441 OMPPrivateScope FirstprivateScope(CGF);
5442 for (const auto &Pair : FirstprivatePtrs) {
5443 Address Replacement(
5444 CGF.Builder.CreateLoad(Pair.second),
5445 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5446 CGF.getContext().getDeclAlign(Pair.first));
5447 FirstprivateScope.addPrivate(Pair.first, Replacement);
5448 }
5449 (void)FirstprivateScope.Privatize();
5450 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5451 ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionVars,
5452 Data.ReductionCopies, Data.ReductionOps);
5453 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5454 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9)));
5455 for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5456 RedCG.emitSharedOrigLValue(CGF, Cnt);
5457 RedCG.emitAggregateType(CGF, Cnt);
5458 // FIXME: This must removed once the runtime library is fixed.
5459 // Emit required threadprivate variables for
5460 // initializer/combiner/finalizer.
5461 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5462 RedCG, Cnt);
5463 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5464 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5465 Replacement = Address(
5466 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5467 CGF.getContext().VoidPtrTy,
5468 CGF.getContext().getPointerType(
5469 Data.ReductionCopies[Cnt]->getType()),
5470 Data.ReductionCopies[Cnt]->getExprLoc()),
5471 CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()),
5472 Replacement.getAlignment());
5473 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5474 Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5475 }
5476 }
5477 // Privatize all private variables except for in_reduction items.
5478 (void)Scope.Privatize();
5482 SmallVector<const Expr *, 4> TaskgroupDescriptors;
5483 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) {
5484 auto IPriv = C->privates().begin();
5485 auto IRed = C->reduction_ops().begin();
5486 auto ITD = C->taskgroup_descriptors().begin();
5487 for (const Expr *Ref : C->varlist()) {
5488 InRedVars.emplace_back(Ref);
5489 InRedPrivs.emplace_back(*IPriv);
5490 InRedOps.emplace_back(*IRed);
5491 TaskgroupDescriptors.emplace_back(*ITD);
5492 std::advance(IPriv, 1);
5493 std::advance(IRed, 1);
5494 std::advance(ITD, 1);
5495 }
5496 }
5497 // Privatize in_reduction items here, because taskgroup descriptors must be
5498 // privatized earlier.
5499 OMPPrivateScope InRedScope(CGF);
5500 if (!InRedVars.empty()) {
5501 ReductionCodeGen RedCG(InRedVars, InRedVars, InRedPrivs, InRedOps);
5502 for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5503 RedCG.emitSharedOrigLValue(CGF, Cnt);
5504 RedCG.emitAggregateType(CGF, Cnt);
5505 // The taskgroup descriptor variable is always implicit firstprivate and
5506 // privatized already during processing of the firstprivates.
5507 // FIXME: This must removed once the runtime library is fixed.
5508 // Emit required threadprivate variables for
5509 // initializer/combiner/finalizer.
5510 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5511 RedCG, Cnt);
5512 llvm::Value *ReductionsPtr;
5513 if (const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5514 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5515 TRExpr->getExprLoc());
5516 } else {
5517 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5518 }
5519 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5520 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5521 Replacement = Address(
5522 CGF.EmitScalarConversion(
5523 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5524 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5525 InRedPrivs[Cnt]->getExprLoc()),
5526 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5527 Replacement.getAlignment());
5528 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5529 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5530 }
5531 }
5532 (void)InRedScope.Privatize();
5533
5535 UntiedLocalVars);
5536 Action.Enter(CGF);
5537 BodyGen(CGF);
5538 };
5540 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5541 S, *I, *PartId, *TaskT, EKind, CodeGen, Data.Tied, Data.NumberOfParts);
5542 OMPLexicalScope Scope(*this, S, std::nullopt,
5543 !isOpenMPParallelDirective(EKind) &&
5544 !isOpenMPSimdDirective(EKind));
5545 TaskGen(*this, OutlinedFn, Data);
5546}
5547
5548static ImplicitParamDecl *
5550 QualType Ty, CapturedDecl *CD,
5551 SourceLocation Loc) {
5552 auto *OrigVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
5554 auto *OrigRef = DeclRefExpr::Create(
5556 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
5557 auto *PrivateVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
5559 auto *PrivateRef = DeclRefExpr::Create(
5560 C, NestedNameSpecifierLoc(), SourceLocation(), PrivateVD,
5561 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
5562 QualType ElemType = C.getBaseElementType(Ty);
5563 auto *InitVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, ElemType,
5565 auto *InitRef = DeclRefExpr::Create(
5567 /*RefersToEnclosingVariableOrCapture=*/false, Loc, ElemType, VK_LValue);
5568 PrivateVD->setInitStyle(VarDecl::CInit);
5569 PrivateVD->setInit(ImplicitCastExpr::Create(C, ElemType, CK_LValueToRValue,
5570 InitRef, /*BasePath=*/nullptr,
5572 Data.FirstprivateVars.emplace_back(OrigRef);
5573 Data.FirstprivateCopies.emplace_back(PrivateRef);
5574 Data.FirstprivateInits.emplace_back(InitRef);
5575 return OrigVD;
5576}
5577
5579 const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen,
5580 OMPTargetDataInfo &InputInfo) {
5581 // Emit outlined function for task construct.
5582 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
5583 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
5584 CanQualType SharedsTy =
5586 auto I = CS->getCapturedDecl()->param_begin();
5587 auto PartId = std::next(I);
5588 auto TaskT = std::next(I, 4);
5590 // The task is not final.
5591 Data.Final.setInt(/*IntVal=*/false);
5592 // Get list of firstprivate variables.
5593 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5594 auto IRef = C->varlist_begin();
5595 auto IElemInitRef = C->inits().begin();
5596 for (auto *IInit : C->private_copies()) {
5597 Data.FirstprivateVars.push_back(*IRef);
5598 Data.FirstprivateCopies.push_back(IInit);
5599 Data.FirstprivateInits.push_back(*IElemInitRef);
5600 ++IRef;
5601 ++IElemInitRef;
5602 }
5603 }
5606 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) {
5607 Data.ReductionVars.append(C->varlist_begin(), C->varlist_end());
5608 Data.ReductionOrigs.append(C->varlist_begin(), C->varlist_end());
5609 Data.ReductionCopies.append(C->privates().begin(), C->privates().end());
5610 Data.ReductionOps.append(C->reduction_ops().begin(),
5611 C->reduction_ops().end());
5612 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
5613 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
5614 }
5615 OMPPrivateScope TargetScope(*this);
5616 VarDecl *BPVD = nullptr;
5617 VarDecl *PVD = nullptr;
5618 VarDecl *SVD = nullptr;
5619 VarDecl *MVD = nullptr;
5620 if (InputInfo.NumberOfTargetItems > 0) {
5621 auto *CD = CapturedDecl::Create(
5622 getContext(), getContext().getTranslationUnitDecl(), /*NumParams=*/0);
5623 llvm::APInt ArrSize(/*numBits=*/32, InputInfo.NumberOfTargetItems);
5624 QualType BaseAndPointerAndMapperType = getContext().getConstantArrayType(
5625 getContext().VoidPtrTy, ArrSize, nullptr, ArraySizeModifier::Normal,
5626 /*IndexTypeQuals=*/0);
5628 getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5630 getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5632 getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1),
5633 ArrSize, nullptr, ArraySizeModifier::Normal,
5634 /*IndexTypeQuals=*/0);
5635 SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD,
5636 S.getBeginLoc());
5637 TargetScope.addPrivate(BPVD, InputInfo.BasePointersArray);
5638 TargetScope.addPrivate(PVD, InputInfo.PointersArray);
5639 TargetScope.addPrivate(SVD, InputInfo.SizesArray);
5640 // If there is no user-defined mapper, the mapper array will be nullptr. In
5641 // this case, we don't need to privatize it.
5642 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5643 InputInfo.MappersArray.emitRawPointer(*this))) {
5645 getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5646 TargetScope.addPrivate(MVD, InputInfo.MappersArray);
5647 }
5648 }
5649 (void)TargetScope.Privatize();
5652 auto &&CodeGen = [&Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5653 &InputInfo](CodeGenFunction &CGF, PrePostActionTy &Action) {
5654 // Set proper addresses for generated private copies.
5656 if (!Data.FirstprivateVars.empty()) {
5657 enum { PrivatesParam = 2, CopyFnParam = 3 };
5658 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5659 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
5660 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5661 CS->getCapturedDecl()->getParam(PrivatesParam)));
5662 // Map privates.
5666 CallArgs.push_back(PrivatesPtr);
5667 ParamTypes.push_back(PrivatesPtr->getType());
5668 for (const Expr *E : Data.FirstprivateVars) {
5669 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5670 RawAddress PrivatePtr =
5671 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
5672 ".firstpriv.ptr.addr");
5673 PrivatePtrs.emplace_back(VD, PrivatePtr);
5674 CallArgs.push_back(PrivatePtr.getPointer());
5675 ParamTypes.push_back(PrivatePtr.getType());
5676 }
5677 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5678 ParamTypes, /*isVarArg=*/false);
5679 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5680 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5681 for (const auto &Pair : PrivatePtrs) {
5682 Address Replacement(
5683 CGF.Builder.CreateLoad(Pair.second),
5684 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5685 CGF.getContext().getDeclAlign(Pair.first));
5686 Scope.addPrivate(Pair.first, Replacement);
5687 }
5688 }
5689 CGF.processInReduction(S, Data, CGF, CS, Scope);
5690 if (InputInfo.NumberOfTargetItems > 0) {
5691 InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP(
5692 CGF.GetAddrOfLocalVar(BPVD), /*Index=*/0);
5693 InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP(
5694 CGF.GetAddrOfLocalVar(PVD), /*Index=*/0);
5695 InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP(
5696 CGF.GetAddrOfLocalVar(SVD), /*Index=*/0);
5697 // If MVD is nullptr, the mapper array is not privatized
5698 if (MVD)
5699 InputInfo.MappersArray = CGF.Builder.CreateConstArrayGEP(
5700 CGF.GetAddrOfLocalVar(MVD), /*Index=*/0);
5701 }
5702
5703 Action.Enter(CGF);
5704 OMPLexicalScope LexScope(CGF, S, OMPD_task, /*EmitPreInitStmt=*/false);
5705 auto *TL = S.getSingleClause<OMPThreadLimitClause>();
5706 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5707 needsTaskBasedThreadLimit(EKind) && TL) {
5708 // Emit __kmpc_set_thread_limit() to set the thread_limit for the task
5709 // enclosing this target region. This will indirectly set the thread_limit
5710 // for every applicable construct within target region.
5711 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5712 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5713 }
5714 BodyGen(CGF);
5715 };
5716 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5717 S, *I, *PartId, *TaskT, EKind, CodeGen, /*Tied=*/true,
5718 Data.NumberOfParts);
5719 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5720 IntegerLiteral IfCond(getContext(), TrueOrFalse,
5721 getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
5722 SourceLocation());
5723 CGM.getOpenMPRuntime().emitTaskCall(*this, S.getBeginLoc(), S, OutlinedFn,
5724 SharedsTy, CapturedStruct, &IfCond, Data);
5725}
5726
5729 CodeGenFunction &CGF,
5730 const CapturedStmt *CS,
5733 if (Data.Reductions) {
5734 OpenMPDirectiveKind CapturedRegion = EKind;
5735 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5736 ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionVars,
5737 Data.ReductionCopies, Data.ReductionOps);
5738 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5740 for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5741 RedCG.emitSharedOrigLValue(CGF, Cnt);
5742 RedCG.emitAggregateType(CGF, Cnt);
5743 // FIXME: This must removed once the runtime library is fixed.
5744 // Emit required threadprivate variables for
5745 // initializer/combiner/finalizer.
5746 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5747 RedCG, Cnt);
5749 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5750 Replacement = Address(
5751 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5752 CGF.getContext().VoidPtrTy,
5754 Data.ReductionCopies[Cnt]->getType()),
5755 Data.ReductionCopies[Cnt]->getExprLoc()),
5756 CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()),
5757 Replacement.getAlignment());
5758 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5759 Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5760 }
5761 }
5762 (void)Scope.Privatize();
5766 SmallVector<const Expr *, 4> TaskgroupDescriptors;
5767 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) {
5768 auto IPriv = C->privates().begin();
5769 auto IRed = C->reduction_ops().begin();
5770 auto ITD = C->taskgroup_descriptors().begin();
5771 for (const Expr *Ref : C->varlist()) {
5772 InRedVars.emplace_back(Ref);
5773 InRedPrivs.emplace_back(*IPriv);
5774 InRedOps.emplace_back(*IRed);
5775 TaskgroupDescriptors.emplace_back(*ITD);
5776 std::advance(IPriv, 1);
5777 std::advance(IRed, 1);
5778 std::advance(ITD, 1);
5779 }
5780 }
5781 OMPPrivateScope InRedScope(CGF);
5782 if (!InRedVars.empty()) {
5783 ReductionCodeGen RedCG(InRedVars, InRedVars, InRedPrivs, InRedOps);
5784 for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5785 RedCG.emitSharedOrigLValue(CGF, Cnt);
5786 RedCG.emitAggregateType(CGF, Cnt);
5787 // FIXME: This must removed once the runtime library is fixed.
5788 // Emit required threadprivate variables for
5789 // initializer/combiner/finalizer.
5790 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5791 RedCG, Cnt);
5792 llvm::Value *ReductionsPtr;
5793 if (const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5794 ReductionsPtr =
5795 CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr), TRExpr->getExprLoc());
5796 } else {
5797 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5798 }
5800 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5801 Replacement = Address(
5803 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5804 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5805 InRedPrivs[Cnt]->getExprLoc()),
5806 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5807 Replacement.getAlignment());
5808 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5809 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5810 }
5811 }
5812 (void)InRedScope.Privatize();
5813}
5814
5815void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
5816 // Emit outlined function for task construct.
5817 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
5818 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
5819 CanQualType SharedsTy =
5821 const Expr *IfCond = nullptr;
5822 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
5823 if (C->getNameModifier() == OMPD_unknown ||
5824 C->getNameModifier() == OMPD_task) {
5825 IfCond = C->getCondition();
5826 break;
5827 }
5828 }
5829
5831 // Check if we should emit tied or untied task.
5832 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5833 auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) {
5834 CGF.EmitStmt(CS->getCapturedStmt());
5835 };
5836 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5837 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5838 const OMPTaskDataTy &Data) {
5839 CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getBeginLoc(), S, OutlinedFn,
5840 SharedsTy, CapturedStruct, IfCond,
5841 Data);
5842 };
5843 auto LPCRegion =
5845 EmitOMPTaskBasedDirective(S, OMPD_task, BodyGen, TaskGen, Data);
5846}
5847
5849 const OMPTaskyieldDirective &S) {
5850 CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getBeginLoc());
5851}
5852
5854 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5855 Expr *ME = MC ? MC->getMessageString() : nullptr;
5856 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5857 bool IsFatal = false;
5858 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5859 IsFatal = true;
5860 CGM.getOpenMPRuntime().emitErrorCall(*this, S.getBeginLoc(), ME, IsFatal);
5861}
5862
5863void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
5864 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_barrier);
5865}
5866
5867void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
5869 // Build list of dependences
5871 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5872 CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data);
5873}
5874
5875static bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T) {
5876 return T.clauses().empty();
5877}
5878
5880 const OMPTaskgroupDirective &S) {
5881 OMPLexicalScope Scope(*this, S, OMPD_unknown);
5882 if (CGM.getLangOpts().OpenMPIRBuilder && isSupportedByOpenMPIRBuilder(S)) {
5883 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
5884 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5885 InsertPointTy AllocaIP(AllocaInsertPt->getParent(),
5886 AllocaInsertPt->getIterator());
5887
5888 auto BodyGenCB = [&, this](InsertPointTy AllocaIP,
5889 InsertPointTy CodeGenIP) {
5890 Builder.restoreIP(CodeGenIP);
5891 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5892 return llvm::Error::success();
5893 };
5895 if (!CapturedStmtInfo)
5896 CapturedStmtInfo = &CapStmtInfo;
5897 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5898 cantFail(OMPBuilder.createTaskgroup(Builder, AllocaIP, BodyGenCB));
5899 Builder.restoreIP(AfterIP);
5900 return;
5901 }
5902 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5903 Action.Enter(CGF);
5904 if (const Expr *E = S.getReductionRef()) {
5908 for (const auto *C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5909 Data.ReductionVars.append(C->varlist_begin(), C->varlist_end());
5910 Data.ReductionOrigs.append(C->varlist_begin(), C->varlist_end());
5911 Data.ReductionCopies.append(C->privates().begin(), C->privates().end());
5912 Data.ReductionOps.append(C->reduction_ops().begin(),
5913 C->reduction_ops().end());
5914 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
5915 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
5916 }
5917 llvm::Value *ReductionDesc =
5918 CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getBeginLoc(),
5919 LHSs, RHSs, Data);
5920 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5921 CGF.EmitVarDecl(*VD);
5922 CGF.EmitStoreOfScalar(ReductionDesc, CGF.GetAddrOfLocalVar(VD),
5923 /*Volatile=*/false, E->getType());
5924 }
5925 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5926 };
5927 CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc());
5928}
5929
5930void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
5931 llvm::AtomicOrdering AO = S.getSingleClause<OMPFlushClause>()
5932 ? llvm::AtomicOrdering::NotAtomic
5933 : llvm::AtomicOrdering::AcquireRelease;
5934 CGM.getOpenMPRuntime().emitFlush(
5935 *this,
5936 [&S]() -> ArrayRef<const Expr *> {
5937 if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>())
5938 return llvm::ArrayRef(FlushClause->varlist_begin(),
5939 FlushClause->varlist_end());
5940 return {};
5941 }(),
5942 S.getBeginLoc(), AO);
5943}
5944
5945void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) {
5946 const auto *DO = S.getSingleClause<OMPDepobjClause>();
5947 LValue DOLVal = EmitLValue(DO->getDepobj());
5948 if (const auto *DC = S.getSingleClause<OMPDependClause>()) {
5949 // Build list and emit dependences
5952 for (auto &Dep : Data.Dependences) {
5953 Address DepAddr = CGM.getOpenMPRuntime().emitDepobjDependClause(
5954 *this, Dep, DC->getBeginLoc());
5955 EmitStoreOfScalar(DepAddr.emitRawPointer(*this), DOLVal);
5956 }
5957 return;
5958 }
5959 if (const auto *DC = S.getSingleClause<OMPDestroyClause>()) {
5960 CGM.getOpenMPRuntime().emitDestroyClause(*this, DOLVal, DC->getBeginLoc());
5961 return;
5962 }
5963 if (const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
5964 CGM.getOpenMPRuntime().emitUpdateClause(
5965 *this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5966 return;
5967 }
5968}
5969
5972 return;
5974 bool IsInclusive = S.hasClausesOfKind<OMPInclusiveClause>();
5979 SmallVector<const Expr *, 4> ReductionOps;
5981 SmallVector<const Expr *, 4> CopyArrayTemps;
5982 SmallVector<const Expr *, 4> CopyArrayElems;
5983 for (const auto *C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
5984 if (C->getModifier() != OMPC_REDUCTION_inscan)
5985 continue;
5986 Shareds.append(C->varlist_begin(), C->varlist_end());
5987 Privates.append(C->privates().begin(), C->privates().end());
5988 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
5989 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
5990 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
5991 CopyOps.append(C->copy_ops().begin(), C->copy_ops().end());
5992 CopyArrayTemps.append(C->copy_array_temps().begin(),
5993 C->copy_array_temps().end());
5994 CopyArrayElems.append(C->copy_array_elems().begin(),
5995 C->copy_array_elems().end());
5996 }
5997 if (ParentDir.getDirectiveKind() == OMPD_simd ||
5998 (getLangOpts().OpenMPSimd &&
5999 isOpenMPSimdDirective(ParentDir.getDirectiveKind()))) {
6000 // For simd directive and simd-based directives in simd only mode, use the
6001 // following codegen:
6002 // int x = 0;
6003 // #pragma omp simd reduction(inscan, +: x)
6004 // for (..) {
6005 // <first part>
6006 // #pragma omp scan inclusive(x)
6007 // <second part>
6008 // }
6009 // is transformed to:
6010 // int x = 0;
6011 // for (..) {
6012 // int x_priv = 0;
6013 // <first part>
6014 // x = x_priv + x;
6015 // x_priv = x;
6016 // <second part>
6017 // }
6018 // and
6019 // int x = 0;
6020 // #pragma omp simd reduction(inscan, +: x)
6021 // for (..) {
6022 // <first part>
6023 // #pragma omp scan exclusive(x)
6024 // <second part>
6025 // }
6026 // to
6027 // int x = 0;
6028 // for (..) {
6029 // int x_priv = 0;
6030 // <second part>
6031 // int temp = x;
6032 // x = x_priv + x;
6033 // x_priv = temp;
6034 // <first part>
6035 // }
6036 llvm::BasicBlock *OMPScanReduce = createBasicBlock("omp.inscan.reduce");
6037 EmitBranch(IsInclusive
6038 ? OMPScanReduce
6039 : BreakContinueStack.back().ContinueBlock.getBlock());
6041 {
6042 // New scope for correct construction/destruction of temp variables for
6043 // exclusive scan.
6044 LexicalScope Scope(*this, S.getSourceRange());
6046 EmitBlock(OMPScanReduce);
6047 if (!IsInclusive) {
6048 // Create temp var and copy LHS value to this temp value.
6049 // TMP = LHS;
6050 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6051 const Expr *PrivateExpr = Privates[I];
6052 const Expr *TempExpr = CopyArrayTemps[I];
6054 *cast<VarDecl>(cast<DeclRefExpr>(TempExpr)->getDecl()));
6055 LValue DestLVal = EmitLValue(TempExpr);
6056 LValue SrcLVal = EmitLValue(LHSs[I]);
6057 EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(),
6058 SrcLVal.getAddress(),
6059 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
6060 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()),
6061 CopyOps[I]);
6062 }
6063 }
6064 CGM.getOpenMPRuntime().emitReduction(
6065 *this, ParentDir.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
6066 {/*WithNowait=*/true, /*SimpleReduction=*/true,
6067 /*IsPrivateVarReduction*/ {}, OMPD_simd});
6068 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6069 const Expr *PrivateExpr = Privates[I];
6070 LValue DestLVal;
6071 LValue SrcLVal;
6072 if (IsInclusive) {
6073 DestLVal = EmitLValue(RHSs[I]);
6074 SrcLVal = EmitLValue(LHSs[I]);
6075 } else {
6076 const Expr *TempExpr = CopyArrayTemps[I];
6077 DestLVal = EmitLValue(RHSs[I]);
6078 SrcLVal = EmitLValue(TempExpr);
6079 }
6081 PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6082 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
6083 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
6084 }
6085 }
6087 OMPScanExitBlock = IsInclusive
6088 ? BreakContinueStack.back().ContinueBlock.getBlock()
6089 : OMPScanReduce;
6091 return;
6092 }
6093 if (!IsInclusive) {
6094 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6096 }
6097 if (OMPFirstScanLoop) {
6098 // Emit buffer[i] = red; at the end of the input phase.
6099 const auto *IVExpr = cast<OMPLoopDirective>(ParentDir)
6100 .getIterationVariable()
6101 ->IgnoreParenImpCasts();
6102 LValue IdxLVal = EmitLValue(IVExpr);
6103 llvm::Value *IdxVal = EmitLoadOfScalar(IdxLVal, IVExpr->getExprLoc());
6104 IdxVal = Builder.CreateIntCast(IdxVal, SizeTy, /*isSigned=*/false);
6105 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6106 const Expr *PrivateExpr = Privates[I];
6107 const Expr *OrigExpr = Shareds[I];
6108 const Expr *CopyArrayElem = CopyArrayElems[I];
6109 OpaqueValueMapping IdxMapping(
6110 *this,
6112 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
6113 RValue::get(IdxVal));
6114 LValue DestLVal = EmitLValue(CopyArrayElem);
6115 LValue SrcLVal = EmitLValue(OrigExpr);
6117 PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6118 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
6119 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
6120 }
6121 }
6122 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6123 if (IsInclusive) {
6125 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6126 }
6128 if (!OMPFirstScanLoop) {
6129 // Emit red = buffer[i]; at the entrance to the scan phase.
6130 const auto *IVExpr = cast<OMPLoopDirective>(ParentDir)
6131 .getIterationVariable()
6132 ->IgnoreParenImpCasts();
6133 LValue IdxLVal = EmitLValue(IVExpr);
6134 llvm::Value *IdxVal = EmitLoadOfScalar(IdxLVal, IVExpr->getExprLoc());
6135 IdxVal = Builder.CreateIntCast(IdxVal, SizeTy, /*isSigned=*/false);
6136 llvm::BasicBlock *ExclusiveExitBB = nullptr;
6137 if (!IsInclusive) {
6138 llvm::BasicBlock *ContBB = createBasicBlock("omp.exclusive.dec");
6139 ExclusiveExitBB = createBasicBlock("omp.exclusive.copy.exit");
6140 llvm::Value *Cmp = Builder.CreateIsNull(IdxVal);
6141 Builder.CreateCondBr(Cmp, ExclusiveExitBB, ContBB);
6142 EmitBlock(ContBB);
6143 // Use idx - 1 iteration for exclusive scan.
6144 IdxVal = Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(SizeTy, 1));
6145 }
6146 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6147 const Expr *PrivateExpr = Privates[I];
6148 const Expr *OrigExpr = Shareds[I];
6149 const Expr *CopyArrayElem = CopyArrayElems[I];
6150 OpaqueValueMapping IdxMapping(
6151 *this,
6153 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
6154 RValue::get(IdxVal));
6155 LValue SrcLVal = EmitLValue(CopyArrayElem);
6156 LValue DestLVal = EmitLValue(OrigExpr);
6158 PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6159 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
6160 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
6161 }
6162 if (!IsInclusive) {
6163 EmitBlock(ExclusiveExitBB);
6164 }
6165 }
6169}
6170
6172 const CodeGenLoopTy &CodeGenLoop,
6173 Expr *IncExpr) {
6174 // Emit the loop iteration variable.
6175 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
6176 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
6177 EmitVarDecl(*IVDecl);
6178
6179 // Emit the iterations count variable.
6180 // If it is not a variable, Sema decided to calculate iterations count on each
6181 // iteration (e.g., it is foldable into a constant).
6182 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
6183 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
6184 // Emit calculation of the iterations count.
6185 EmitIgnoredExpr(S.getCalcLastIteration());
6186 }
6187
6188 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
6189
6190 bool HasLastprivateClause = false;
6191 // Check pre-condition.
6192 {
6193 OMPLoopScope PreInitScope(*this, S);
6194 // Skip the entire loop if we don't meet the precondition.
6195 // If the condition constant folds and can be elided, avoid emitting the
6196 // whole loop.
6197 bool CondConstant;
6198 llvm::BasicBlock *ContBlock = nullptr;
6199 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
6200 if (!CondConstant)
6201 return;
6202 } else {
6203 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
6204 ContBlock = createBasicBlock("omp.precond.end");
6205 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
6206 getProfileCount(&S));
6207 EmitBlock(ThenBlock);
6209 }
6210
6211 emitAlignedClause(*this, S);
6212 // Emit 'then' code.
6213 {
6214 // Emit helper vars inits.
6215
6217 *this, cast<DeclRefExpr>(
6218 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
6219 ? S.getCombinedLowerBoundVariable()
6220 : S.getLowerBoundVariable())));
6222 *this, cast<DeclRefExpr>(
6223 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
6224 ? S.getCombinedUpperBoundVariable()
6225 : S.getUpperBoundVariable())));
6226 LValue ST =
6227 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
6228 LValue IL =
6229 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
6230
6231 OMPPrivateScope LoopScope(*this);
6232 if (EmitOMPFirstprivateClause(S, LoopScope)) {
6233 // Emit implicit barrier to synchronize threads and avoid data races
6234 // on initialization of firstprivate variables and post-update of
6235 // lastprivate variables.
6236 CGM.getOpenMPRuntime().emitBarrierCall(
6237 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
6238 /*ForceSimpleCall=*/true);
6239 }
6240 EmitOMPPrivateClause(S, LoopScope);
6241 if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
6242 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
6243 !isOpenMPTeamsDirective(S.getDirectiveKind()))
6244 EmitOMPReductionClauseInit(S, LoopScope);
6245 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
6246 EmitOMPPrivateLoopCounters(S, LoopScope);
6247 (void)LoopScope.Privatize();
6248 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
6249 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S);
6250
6251 // Detect the distribute schedule kind and chunk.
6252 llvm::Value *Chunk = nullptr;
6254 if (const auto *C = S.getSingleClause<OMPDistScheduleClause>()) {
6255 ScheduleKind = C->getDistScheduleKind();
6256 if (const Expr *Ch = C->getChunkSize()) {
6257 Chunk = EmitScalarExpr(Ch);
6258 Chunk = EmitScalarConversion(Chunk, Ch->getType(),
6259 S.getIterationVariable()->getType(),
6260 S.getBeginLoc());
6261 }
6262 } else {
6263 // Default behaviour for dist_schedule clause.
6264 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6265 *this, S, ScheduleKind, Chunk);
6266 }
6267 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
6268 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
6269
6270 // OpenMP [2.10.8, distribute Construct, Description]
6271 // If dist_schedule is specified, kind must be static. If specified,
6272 // iterations are divided into chunks of size chunk_size, chunks are
6273 // assigned to the teams of the league in a round-robin fashion in the
6274 // order of the team number. When no chunk_size is specified, the
6275 // iteration space is divided into chunks that are approximately equal
6276 // in size, and at most one chunk is distributed to each team of the
6277 // league. The size of the chunks is unspecified in this case.
6278 bool StaticChunked =
6279 RT.isStaticChunked(ScheduleKind, /* Chunked */ Chunk != nullptr) &&
6280 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
6281 if (RT.isStaticNonchunked(ScheduleKind,
6282 /* Chunked */ Chunk != nullptr) ||
6283 StaticChunked) {
6285 IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(),
6286 LB.getAddress(), UB.getAddress(), ST.getAddress(),
6287 StaticChunked ? Chunk : nullptr);
6288 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind,
6289 StaticInit);
6292 // UB = min(UB, GlobalUB);
6294 ? S.getCombinedEnsureUpperBound()
6295 : S.getEnsureUpperBound());
6296 // IV = LB;
6298 ? S.getCombinedInit()
6299 : S.getInit());
6300
6301 const Expr *Cond =
6302 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
6303 ? S.getCombinedCond()
6304 : S.getCond();
6305
6306 if (StaticChunked)
6307 Cond = S.getCombinedDistCond();
6308
6309 // For static unchunked schedules generate:
6310 //
6311 // 1. For distribute alone, codegen
6312 // while (idx <= UB) {
6313 // BODY;
6314 // ++idx;
6315 // }
6316 //
6317 // 2. When combined with 'for' (e.g. as in 'distribute parallel for')
6318 // while (idx <= UB) {
6319 // <CodeGen rest of pragma>(LB, UB);
6320 // idx += ST;
6321 // }
6322 //
6323 // For static chunk one schedule generate:
6324 //
6325 // while (IV <= GlobalUB) {
6326 // <CodeGen rest of pragma>(LB, UB);
6327 // LB += ST;
6328 // UB += ST;
6329 // UB = min(UB, GlobalUB);
6330 // IV = LB;
6331 // }
6332 //
6334 *this, S,
6335 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
6336 if (isOpenMPSimdDirective(S.getDirectiveKind()))
6337 CGF.EmitOMPSimdInit(S);
6338 },
6339 [&S, &LoopScope, Cond, IncExpr, LoopExit, &CodeGenLoop,
6340 StaticChunked](CodeGenFunction &CGF, PrePostActionTy &) {
6341 CGF.EmitOMPInnerLoop(
6342 S, LoopScope.requiresCleanups(), Cond, IncExpr,
6343 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6344 CodeGenLoop(CGF, S, LoopExit);
6345 },
6346 [&S, StaticChunked](CodeGenFunction &CGF) {
6347 if (StaticChunked) {
6348 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6349 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6350 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6351 CGF.EmitIgnoredExpr(S.getCombinedInit());
6352 }
6353 });
6354 });
6355 EmitBlock(LoopExit.getBlock());
6356 // Tell the runtime we are done.
6357 RT.emitForStaticFinish(*this, S.getEndLoc(), OMPD_distribute);
6358 } else {
6359 // Emit the outer loop, which requests its work chunk [LB..UB] from
6360 // runtime and runs the inner loop to process it.
6361 const OMPLoopArguments LoopArguments = {
6362 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(),
6363 Chunk};
6364 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6365 CodeGenLoop);
6366 }
6367 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
6368 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
6369 return CGF.Builder.CreateIsNotNull(
6370 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
6371 });
6372 }
6373 if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
6374 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
6375 !isOpenMPTeamsDirective(S.getDirectiveKind())) {
6376 EmitOMPReductionClauseFinal(S, OMPD_simd);
6377 // Emit post-update of the reduction variables if IsLastIter != 0.
6379 *this, S, [IL, &S](CodeGenFunction &CGF) {
6380 return CGF.Builder.CreateIsNotNull(
6381 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
6382 });
6383 }
6384 // Emit final copy of the lastprivate variables if IsLastIter != 0.
6385 if (HasLastprivateClause) {
6387 S, /*NoFinals=*/false,
6388 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
6389 }
6390 }
6391
6392 // We're now done with the loop, so jump to the continuation block.
6393 if (ContBlock) {
6394 EmitBranch(ContBlock);
6395 EmitBlock(ContBlock, true);
6396 }
6397 }
6398}
6399
6400// Pass OMPLoopDirective (instead of OMPDistributeDirective) to make this
6401// function available for "loop bind(teams)", which maps to "distribute".
6403 CodeGenFunction &CGF,
6404 CodeGenModule &CGM) {
6405 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
6407 };
6408 OMPLexicalScope Scope(CGF, S, OMPD_unknown);
6409 CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, CodeGen);
6410}
6411
6416
6417static llvm::Function *
6419 const OMPExecutableDirective &D) {
6420 CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
6422 CGF.CapturedStmtInfo = &CapStmtInfo;
6423 llvm::Function *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S, D);
6424 Fn->setDoesNotRecurse();
6425 return Fn;
6426}
6427
6428template <typename T>
6429static void emitRestoreIP(CodeGenFunction &CGF, const T *C,
6430 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6431 llvm::OpenMPIRBuilder &OMPBuilder) {
6432
6433 unsigned NumLoops = C->getNumLoops();
6435 /*DestWidth=*/64, /*Signed=*/1);
6437 for (unsigned I = 0; I < NumLoops; I++) {
6438 const Expr *CounterVal = C->getLoopData(I);
6439 assert(CounterVal);
6440 llvm::Value *StoreValue = CGF.EmitScalarConversion(
6441 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
6442 CounterVal->getExprLoc());
6443 StoreValues.emplace_back(StoreValue);
6444 }
6445 OMPDoacrossKind<T> ODK;
6446 bool IsDependSource = ODK.isSource(C);
6447 CGF.Builder.restoreIP(
6448 OMPBuilder.createOrderedDepend(CGF.Builder, AllocaIP, NumLoops,
6449 StoreValues, ".cnt.addr", IsDependSource));
6450}
6451
6452void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
6453 if (CGM.getLangOpts().OpenMPIRBuilder) {
6454 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
6455 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6456
6457 if (S.hasClausesOfKind<OMPDependClause>() ||
6458 S.hasClausesOfKind<OMPDoacrossClause>()) {
6459 // The ordered directive with depend clause.
6460 assert(!S.hasAssociatedStmt() && "No associated statement must be in "
6461 "ordered depend|doacross construct.");
6462 InsertPointTy AllocaIP(AllocaInsertPt->getParent(),
6463 AllocaInsertPt->getIterator());
6464 for (const auto *DC : S.getClausesOfKind<OMPDependClause>())
6465 emitRestoreIP(*this, DC, AllocaIP, OMPBuilder);
6466 for (const auto *DC : S.getClausesOfKind<OMPDoacrossClause>())
6467 emitRestoreIP(*this, DC, AllocaIP, OMPBuilder);
6468 } else {
6469 // The ordered directive with threads or simd clause, or without clause.
6470 // Without clause, it behaves as if the threads clause is specified.
6471 const auto *C = S.getSingleClause<OMPSIMDClause>();
6472
6473 auto FiniCB = [this](InsertPointTy IP) {
6475 return llvm::Error::success();
6476 };
6477
6478 auto BodyGenCB = [&S, C, this](InsertPointTy AllocaIP,
6479 InsertPointTy CodeGenIP) {
6480 Builder.restoreIP(CodeGenIP);
6481
6482 const CapturedStmt *CS = S.getInnermostCapturedStmt();
6483 if (C) {
6484 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6485 Builder, /*CreateBranch=*/false, ".ordered.after");
6487 GenerateOpenMPCapturedVars(*CS, CapturedVars);
6488 llvm::Function *OutlinedFn = emitOutlinedOrderedFunction(CGM, CS, S);
6489 assert(S.getBeginLoc().isValid() &&
6490 "Outlined function call location must be valid.");
6491 ApplyDebugLocation::CreateDefaultArtificial(*this, S.getBeginLoc());
6492 OMPBuilderCBHelpers::EmitCaptureStmt(*this, CodeGenIP, *FiniBB,
6493 OutlinedFn, CapturedVars);
6494 } else {
6496 *this, CS->getCapturedStmt(), AllocaIP, CodeGenIP, "ordered");
6497 }
6498 return llvm::Error::success();
6499 };
6500
6501 OMPLexicalScope Scope(*this, S, OMPD_unknown);
6502 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6503 OMPBuilder.createOrderedThreadsSimd(Builder, BodyGenCB, FiniCB, !C));
6504 Builder.restoreIP(AfterIP);
6505 }
6506 return;
6507 }
6508
6509 if (S.hasClausesOfKind<OMPDependClause>()) {
6510 assert(!S.hasAssociatedStmt() &&
6511 "No associated statement must be in ordered depend construct.");
6512 for (const auto *DC : S.getClausesOfKind<OMPDependClause>())
6513 CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC);
6514 return;
6515 }
6516 if (S.hasClausesOfKind<OMPDoacrossClause>()) {
6517 assert(!S.hasAssociatedStmt() &&
6518 "No associated statement must be in ordered doacross construct.");
6519 for (const auto *DC : S.getClausesOfKind<OMPDoacrossClause>())
6520 CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC);
6521 return;
6522 }
6523 const auto *C = S.getSingleClause<OMPSIMDClause>();
6524 auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF,
6525 PrePostActionTy &Action) {
6526 const CapturedStmt *CS = S.getInnermostCapturedStmt();
6527 if (C) {
6529 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6530 llvm::Function *OutlinedFn = emitOutlinedOrderedFunction(CGM, CS, S);
6531 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6532 OutlinedFn, CapturedVars);
6533 } else {
6534 Action.Enter(CGF);
6535 CGF.EmitStmt(CS->getCapturedStmt());
6536 }
6537 };
6538 OMPLexicalScope Scope(*this, S, OMPD_unknown);
6539 CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getBeginLoc(), !C);
6540}
6541
6542static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val,
6543 QualType SrcType, QualType DestType,
6544 SourceLocation Loc) {
6545 assert(CGF.hasScalarEvaluationKind(DestType) &&
6546 "DestType must have scalar evaluation kind.");
6547 assert(!Val.isAggregate() && "Must be a scalar or complex.");
6548 return Val.isScalar() ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType,
6549 DestType, Loc)
6551 Val.getComplexVal(), SrcType, DestType, Loc);
6552}
6553
6556 QualType DestType, SourceLocation Loc) {
6557 assert(CGF.getEvaluationKind(DestType) == TEK_Complex &&
6558 "DestType must have complex evaluation kind.");
6560 if (Val.isScalar()) {
6561 // Convert the input element to the element type of the complex.
6562 QualType DestElementType =
6563 DestType->castAs<ComplexType>()->getElementType();
6564 llvm::Value *ScalarVal = CGF.EmitScalarConversion(
6565 Val.getScalarVal(), SrcType, DestElementType, Loc);
6566 ComplexVal = CodeGenFunction::ComplexPairTy(
6567 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6568 } else {
6569 assert(Val.isComplex() && "Must be a scalar or complex.");
6570 QualType SrcElementType = SrcType->castAs<ComplexType>()->getElementType();
6571 QualType DestElementType =
6572 DestType->castAs<ComplexType>()->getElementType();
6573 ComplexVal.first = CGF.EmitScalarConversion(
6574 Val.getComplexVal().first, SrcElementType, DestElementType, Loc);
6575 ComplexVal.second = CGF.EmitScalarConversion(
6576 Val.getComplexVal().second, SrcElementType, DestElementType, Loc);
6577 }
6578 return ComplexVal;
6579}
6580
6581static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO,
6582 LValue LVal, RValue RVal) {
6583 if (LVal.isGlobalReg())
6584 CGF.EmitStoreThroughGlobalRegLValue(RVal, LVal);
6585 else
6586 CGF.EmitAtomicStore(RVal, LVal, AO, LVal.isVolatile(), /*isInit=*/false);
6587}
6588
6590 llvm::AtomicOrdering AO, LValue LVal,
6591 SourceLocation Loc) {
6592 if (LVal.isGlobalReg())
6593 return CGF.EmitLoadOfLValue(LVal, Loc);
6594 return CGF.EmitAtomicLoad(
6595 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6596 LVal.isVolatile());
6597}
6598
6600 QualType RValTy, SourceLocation Loc) {
6601 switch (getEvaluationKind(LVal.getType())) {
6602 case TEK_Scalar:
6604 *this, RVal, RValTy, LVal.getType(), Loc)),
6605 LVal);
6606 break;
6607 case TEK_Complex:
6609 convertToComplexValue(*this, RVal, RValTy, LVal.getType(), Loc), LVal,
6610 /*isInit=*/false);
6611 break;
6612 case TEK_Aggregate:
6613 llvm_unreachable("Must be a scalar or complex.");
6614 }
6615}
6616
6617static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO,
6618 const Expr *X, const Expr *V,
6619 SourceLocation Loc) {
6620 // v = x;
6621 assert(V->isLValue() && "V of 'omp atomic read' is not lvalue");
6622 assert(X->isLValue() && "X of 'omp atomic read' is not lvalue");
6623 LValue XLValue = CGF.EmitLValue(X);
6624 LValue VLValue = CGF.EmitLValue(V);
6625 RValue Res = emitSimpleAtomicLoad(CGF, AO, XLValue, Loc);
6626 // OpenMP, 2.17.7, atomic Construct
6627 // If the read or capture clause is specified and the acquire, acq_rel, or
6628 // seq_cst clause is specified then the strong flush on exit from the atomic
6629 // operation is also an acquire flush.
6630 switch (AO) {
6631 case llvm::AtomicOrdering::Acquire:
6632 case llvm::AtomicOrdering::AcquireRelease:
6633 case llvm::AtomicOrdering::SequentiallyConsistent:
6634 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, {}, Loc,
6635 llvm::AtomicOrdering::Acquire);
6636 break;
6637 case llvm::AtomicOrdering::Monotonic:
6638 case llvm::AtomicOrdering::Release:
6639 break;
6640 case llvm::AtomicOrdering::NotAtomic:
6641 case llvm::AtomicOrdering::Unordered:
6642 llvm_unreachable("Unexpected ordering.");
6643 }
6644 CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc);
6646}
6647
6649 llvm::AtomicOrdering AO, const Expr *X,
6650 const Expr *E, SourceLocation Loc) {
6651 // x = expr;
6652 assert(X->isLValue() && "X of 'omp atomic write' is not lvalue");
6653 emitSimpleAtomicStore(CGF, AO, CGF.EmitLValue(X), CGF.EmitAnyExpr(E));
6655 // OpenMP, 2.17.7, atomic Construct
6656 // If the write, update, or capture clause is specified and the release,
6657 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
6658 // the atomic operation is also a release flush.
6659 switch (AO) {
6660 case llvm::AtomicOrdering::Release:
6661 case llvm::AtomicOrdering::AcquireRelease:
6662 case llvm::AtomicOrdering::SequentiallyConsistent:
6663 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, {}, Loc,
6664 llvm::AtomicOrdering::Release);
6665 break;
6666 case llvm::AtomicOrdering::Acquire:
6667 case llvm::AtomicOrdering::Monotonic:
6668 break;
6669 case llvm::AtomicOrdering::NotAtomic:
6670 case llvm::AtomicOrdering::Unordered:
6671 llvm_unreachable("Unexpected ordering.");
6672 }
6673}
6674
6675static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
6676 RValue Update,
6678 llvm::AtomicOrdering AO,
6679 bool IsXLHSInRHSPart) {
6680 ASTContext &Context = CGF.getContext();
6681 // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x'
6682 // expression is simple and atomic is allowed for the given type for the
6683 // target platform.
6684 if (BO == BO_Comma || !Update.isScalar() || !X.isSimple() ||
6685 (!isa<llvm::ConstantInt>(Update.getScalarVal()) &&
6686 (Update.getScalarVal()->getType() != X.getAddress().getElementType())) ||
6687 !Context.getTargetInfo().hasBuiltinAtomic(
6688 Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment())))
6689 return std::make_pair(false, RValue::get(nullptr));
6690
6691 auto &&CheckAtomicSupport = [&CGF](llvm::Type *T, BinaryOperatorKind BO) {
6692 if (T->isIntegerTy())
6693 return true;
6694
6695 if (T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6696 return llvm::isPowerOf2_64(CGF.CGM.getDataLayout().getTypeStoreSize(T));
6697
6698 return false;
6699 };
6700
6701 if (!CheckAtomicSupport(Update.getScalarVal()->getType(), BO) ||
6702 !CheckAtomicSupport(X.getAddress().getElementType(), BO))
6703 return std::make_pair(false, RValue::get(nullptr));
6704
6705 bool IsInteger = X.getAddress().getElementType()->isIntegerTy();
6706 llvm::AtomicRMWInst::BinOp RMWOp;
6707 switch (BO) {
6708 case BO_Add:
6709 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6710 break;
6711 case BO_Sub:
6712 if (!IsXLHSInRHSPart)
6713 return std::make_pair(false, RValue::get(nullptr));
6714 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6715 break;
6716 case BO_And:
6717 RMWOp = llvm::AtomicRMWInst::And;
6718 break;
6719 case BO_Or:
6720 RMWOp = llvm::AtomicRMWInst::Or;
6721 break;
6722 case BO_Xor:
6723 RMWOp = llvm::AtomicRMWInst::Xor;
6724 break;
6725 case BO_LT:
6726 if (IsInteger)
6727 RMWOp = X.getType()->hasSignedIntegerRepresentation()
6728 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
6729 : llvm::AtomicRMWInst::Max)
6730 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
6731 : llvm::AtomicRMWInst::UMax);
6732 else
6733 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMin
6734 : llvm::AtomicRMWInst::FMax;
6735 break;
6736 case BO_GT:
6737 if (IsInteger)
6738 RMWOp = X.getType()->hasSignedIntegerRepresentation()
6739 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
6740 : llvm::AtomicRMWInst::Min)
6741 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
6742 : llvm::AtomicRMWInst::UMin);
6743 else
6744 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMax
6745 : llvm::AtomicRMWInst::FMin;
6746 break;
6747 case BO_Assign:
6748 RMWOp = llvm::AtomicRMWInst::Xchg;
6749 break;
6750 case BO_Mul:
6751 case BO_Div:
6752 case BO_Rem:
6753 case BO_Shl:
6754 case BO_Shr:
6755 case BO_LAnd:
6756 case BO_LOr:
6757 return std::make_pair(false, RValue::get(nullptr));
6758 case BO_PtrMemD:
6759 case BO_PtrMemI:
6760 case BO_LE:
6761 case BO_GE:
6762 case BO_EQ:
6763 case BO_NE:
6764 case BO_Cmp:
6765 case BO_AddAssign:
6766 case BO_SubAssign:
6767 case BO_AndAssign:
6768 case BO_OrAssign:
6769 case BO_XorAssign:
6770 case BO_MulAssign:
6771 case BO_DivAssign:
6772 case BO_RemAssign:
6773 case BO_ShlAssign:
6774 case BO_ShrAssign:
6775 case BO_Comma:
6776 llvm_unreachable("Unsupported atomic update operation");
6777 }
6778 llvm::Value *UpdateVal = Update.getScalarVal();
6779 if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6780 if (IsInteger)
6781 UpdateVal = CGF.Builder.CreateIntCast(
6782 IC, X.getAddress().getElementType(),
6783 X.getType()->hasSignedIntegerRepresentation());
6784 else
6785 UpdateVal = CGF.Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6786 X.getAddress().getElementType());
6787 }
6788 llvm::AtomicRMWInst *Res =
6789 CGF.emitAtomicRMWInst(RMWOp, X.getAddress(), UpdateVal, AO);
6790 return std::make_pair(true, RValue::get(Res));
6791}
6792
6795 llvm::AtomicOrdering AO, SourceLocation Loc,
6796 const llvm::function_ref<RValue(RValue)> CommonGen) {
6797 // Update expressions are allowed to have the following forms:
6798 // x binop= expr; -> xrval + expr;
6799 // x++, ++x -> xrval + 1;
6800 // x--, --x -> xrval - 1;
6801 // x = x binop expr; -> xrval binop expr
6802 // x = expr Op x; - > expr binop xrval;
6803 auto Res = emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart);
6804 if (!Res.first) {
6805 if (X.isGlobalReg()) {
6806 // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop
6807 // 'xrval'.
6808 EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X);
6809 } else {
6810 // Perform compare-and-swap procedure.
6811 EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified());
6812 }
6813 }
6814 return Res;
6815}
6816
6818 llvm::AtomicOrdering AO, const Expr *X,
6819 const Expr *E, const Expr *UE,
6820 bool IsXLHSInRHSPart, SourceLocation Loc) {
6821 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
6822 "Update expr in 'atomic update' must be a binary operator.");
6823 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
6824 // Update expressions are allowed to have the following forms:
6825 // x binop= expr; -> xrval + expr;
6826 // x++, ++x -> xrval + 1;
6827 // x--, --x -> xrval - 1;
6828 // x = x binop expr; -> xrval binop expr
6829 // x = expr Op x; - > expr binop xrval;
6830 assert(X->isLValue() && "X of 'omp atomic update' is not lvalue");
6831 LValue XLValue = CGF.EmitLValue(X);
6832 RValue ExprRValue = CGF.EmitAnyExpr(E);
6833 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
6834 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
6835 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
6836 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
6837 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) {
6838 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6839 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
6840 return CGF.EmitAnyExpr(UE);
6841 };
6843 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
6845 // OpenMP, 2.17.7, atomic Construct
6846 // If the write, update, or capture clause is specified and the release,
6847 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
6848 // the atomic operation is also a release flush.
6849 switch (AO) {
6850 case llvm::AtomicOrdering::Release:
6851 case llvm::AtomicOrdering::AcquireRelease:
6852 case llvm::AtomicOrdering::SequentiallyConsistent:
6853 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, {}, Loc,
6854 llvm::AtomicOrdering::Release);
6855 break;
6856 case llvm::AtomicOrdering::Acquire:
6857 case llvm::AtomicOrdering::Monotonic:
6858 break;
6859 case llvm::AtomicOrdering::NotAtomic:
6860 case llvm::AtomicOrdering::Unordered:
6861 llvm_unreachable("Unexpected ordering.");
6862 }
6863}
6864
6866 QualType SourceType, QualType ResType,
6867 SourceLocation Loc) {
6868 switch (CGF.getEvaluationKind(ResType)) {
6869 case TEK_Scalar:
6870 return RValue::get(
6871 convertToScalarValue(CGF, Value, SourceType, ResType, Loc));
6872 case TEK_Complex: {
6873 auto Res = convertToComplexValue(CGF, Value, SourceType, ResType, Loc);
6874 return RValue::getComplex(Res.first, Res.second);
6875 }
6876 case TEK_Aggregate:
6877 break;
6878 }
6879 llvm_unreachable("Must be a scalar or complex.");
6880}
6881
6883 llvm::AtomicOrdering AO,
6884 bool IsPostfixUpdate, const Expr *V,
6885 const Expr *X, const Expr *E,
6886 const Expr *UE, bool IsXLHSInRHSPart,
6887 SourceLocation Loc) {
6888 assert(X->isLValue() && "X of 'omp atomic capture' is not lvalue");
6889 assert(V->isLValue() && "V of 'omp atomic capture' is not lvalue");
6890 RValue NewVVal;
6891 LValue VLValue = CGF.EmitLValue(V);
6892 LValue XLValue = CGF.EmitLValue(X);
6893 RValue ExprRValue = CGF.EmitAnyExpr(E);
6894 QualType NewVValType;
6895 if (UE) {
6896 // 'x' is updated with some additional value.
6897 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
6898 "Update expr in 'atomic capture' must be a binary operator.");
6899 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
6900 // Update expressions are allowed to have the following forms:
6901 // x binop= expr; -> xrval + expr;
6902 // x++, ++x -> xrval + 1;
6903 // x--, --x -> xrval - 1;
6904 // x = x binop expr; -> xrval binop expr
6905 // x = expr Op x; - > expr binop xrval;
6906 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
6907 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
6908 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
6909 NewVValType = XRValExpr->getType();
6910 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
6911 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6912 IsPostfixUpdate](RValue XRValue) {
6913 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6914 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
6915 RValue Res = CGF.EmitAnyExpr(UE);
6916 NewVVal = IsPostfixUpdate ? XRValue : Res;
6917 return Res;
6918 };
6919 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
6920 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
6922 if (Res.first) {
6923 // 'atomicrmw' instruction was generated.
6924 if (IsPostfixUpdate) {
6925 // Use old value from 'atomicrmw'.
6926 NewVVal = Res.second;
6927 } else {
6928 // 'atomicrmw' does not provide new value, so evaluate it using old
6929 // value of 'x'.
6930 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6931 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second);
6932 NewVVal = CGF.EmitAnyExpr(UE);
6933 }
6934 }
6935 } else {
6936 // 'x' is simply rewritten with some 'expr'.
6937 NewVValType = X->getType().getNonReferenceType();
6938 ExprRValue = convertToType(CGF, ExprRValue, E->getType(),
6939 X->getType().getNonReferenceType(), Loc);
6940 auto &&Gen = [&NewVVal, ExprRValue](RValue XRValue) {
6941 NewVVal = XRValue;
6942 return ExprRValue;
6943 };
6944 // Try to perform atomicrmw xchg, otherwise simple exchange.
6945 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
6946 XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO,
6947 Loc, Gen);
6949 if (Res.first) {
6950 // 'atomicrmw' instruction was generated.
6951 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
6952 }
6953 }
6954 // Emit post-update store to 'v' of old/new 'x' value.
6955 CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc);
6957 // OpenMP 5.1 removes the required flush for capture clause.
6958 if (CGF.CGM.getLangOpts().OpenMP < 51) {
6959 // OpenMP, 2.17.7, atomic Construct
6960 // If the write, update, or capture clause is specified and the release,
6961 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
6962 // the atomic operation is also a release flush.
6963 // If the read or capture clause is specified and the acquire, acq_rel, or
6964 // seq_cst clause is specified then the strong flush on exit from the atomic
6965 // operation is also an acquire flush.
6966 switch (AO) {
6967 case llvm::AtomicOrdering::Release:
6968 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, {}, Loc,
6969 llvm::AtomicOrdering::Release);
6970 break;
6971 case llvm::AtomicOrdering::Acquire:
6972 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, {}, Loc,
6973 llvm::AtomicOrdering::Acquire);
6974 break;
6975 case llvm::AtomicOrdering::AcquireRelease:
6976 case llvm::AtomicOrdering::SequentiallyConsistent:
6978 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
6979 break;
6980 case llvm::AtomicOrdering::Monotonic:
6981 break;
6982 case llvm::AtomicOrdering::NotAtomic:
6983 case llvm::AtomicOrdering::Unordered:
6984 llvm_unreachable("Unexpected ordering.");
6985 }
6986 }
6987}
6988
6990 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6991 const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *D,
6992 const Expr *CE, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly,
6993 SourceLocation Loc) {
6994 llvm::OpenMPIRBuilder &OMPBuilder =
6996
6997 OMPAtomicCompareOp Op;
6998 assert(isa<BinaryOperator>(CE) && "CE is not a BinaryOperator");
6999 switch (cast<BinaryOperator>(CE)->getOpcode()) {
7000 case BO_EQ:
7001 Op = OMPAtomicCompareOp::EQ;
7002 break;
7003 case BO_LT:
7004 Op = OMPAtomicCompareOp::MIN;
7005 break;
7006 case BO_GT:
7007 Op = OMPAtomicCompareOp::MAX;
7008 break;
7009 default:
7010 llvm_unreachable("unsupported atomic compare binary operator");
7011 }
7012
7013 LValue XLVal = CGF.EmitLValue(X);
7014 Address XAddr = XLVal.getAddress();
7015
7016 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](const Expr *X, const Expr *E) {
7017 if (X->getType() == E->getType())
7018 return CGF.EmitScalarExpr(E);
7019 const Expr *NewE = E->IgnoreImplicitAsWritten();
7020 llvm::Value *V = CGF.EmitScalarExpr(NewE);
7021 if (NewE->getType() == X->getType())
7022 return V;
7023 return CGF.EmitScalarConversion(V, NewE->getType(), X->getType(), Loc);
7024 };
7025
7026 llvm::Value *EVal = EmitRValueWithCastIfNeeded(X, E);
7027 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(X, D) : nullptr;
7028 if (auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7029 EVal = CGF.Builder.CreateIntCast(
7030 CI, XLVal.getAddress().getElementType(),
7032 if (DVal)
7033 if (auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7034 DVal = CGF.Builder.CreateIntCast(
7035 CI, XLVal.getAddress().getElementType(),
7037
7038 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7039 XAddr.emitRawPointer(CGF), XAddr.getElementType(),
7040 X->getType()->hasSignedIntegerRepresentation(),
7041 X->getType().isVolatileQualified()};
7042 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7043 if (V) {
7044 LValue LV = CGF.EmitLValue(V);
7045 Address Addr = LV.getAddress();
7046 VOpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(),
7047 V->getType()->hasSignedIntegerRepresentation(),
7048 V->getType().isVolatileQualified()};
7049 }
7050 if (R) {
7051 LValue LV = CGF.EmitLValue(R);
7052 Address Addr = LV.getAddress();
7053 ROpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(),
7054 R->getType()->hasSignedIntegerRepresentation(),
7055 R->getType().isVolatileQualified()};
7056 }
7057
7058 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7059 // fail clause was not mentioned on the
7060 // "#pragma omp atomic compare" construct.
7061 CGF.Builder.restoreIP(OMPBuilder.createAtomicCompare(
7062 CGF.Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7064 } else
7065 CGF.Builder.restoreIP(OMPBuilder.createAtomicCompare(
7066 CGF.Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7067 IsPostfixUpdate, IsFailOnly, FailAO));
7068}
7069
7071 llvm::AtomicOrdering AO,
7072 llvm::AtomicOrdering FailAO, bool IsPostfixUpdate,
7073 const Expr *X, const Expr *V, const Expr *R,
7074 const Expr *E, const Expr *UE, const Expr *D,
7075 const Expr *CE, bool IsXLHSInRHSPart,
7076 bool IsFailOnly, SourceLocation Loc) {
7077 switch (Kind) {
7078 case OMPC_read:
7079 emitOMPAtomicReadExpr(CGF, AO, X, V, Loc);
7080 break;
7081 case OMPC_write:
7082 emitOMPAtomicWriteExpr(CGF, AO, X, E, Loc);
7083 break;
7084 case OMPC_unknown:
7085 case OMPC_update:
7086 emitOMPAtomicUpdateExpr(CGF, AO, X, E, UE, IsXLHSInRHSPart, Loc);
7087 break;
7088 case OMPC_capture:
7089 emitOMPAtomicCaptureExpr(CGF, AO, IsPostfixUpdate, V, X, E, UE,
7090 IsXLHSInRHSPart, Loc);
7091 break;
7092 case OMPC_compare: {
7093 emitOMPAtomicCompareExpr(CGF, AO, FailAO, X, V, R, E, D, CE,
7095 break;
7096 }
7097 default:
7098 llvm_unreachable("Clause is not allowed in 'omp atomic'.");
7099 }
7100}
7101
7102void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
7103 llvm::AtomicOrdering AO = CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7104 // Fail Memory Clause Ordering.
7105 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7106 bool MemOrderingSpecified = false;
7107 if (S.getSingleClause<OMPSeqCstClause>()) {
7108 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7109 MemOrderingSpecified = true;
7110 } else if (S.getSingleClause<OMPAcqRelClause>()) {
7111 AO = llvm::AtomicOrdering::AcquireRelease;
7112 MemOrderingSpecified = true;
7113 } else if (S.getSingleClause<OMPAcquireClause>()) {
7114 AO = llvm::AtomicOrdering::Acquire;
7115 MemOrderingSpecified = true;
7116 } else if (S.getSingleClause<OMPReleaseClause>()) {
7117 AO = llvm::AtomicOrdering::Release;
7118 MemOrderingSpecified = true;
7119 } else if (S.getSingleClause<OMPRelaxedClause>()) {
7120 AO = llvm::AtomicOrdering::Monotonic;
7121 MemOrderingSpecified = true;
7122 }
7123 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7124 OpenMPClauseKind Kind = OMPC_unknown;
7125 for (const OMPClause *C : S.clauses()) {
7126 // Find first clause (skip seq_cst|acq_rel|aqcuire|release|relaxed clause,
7127 // if it is first).
7128 OpenMPClauseKind K = C->getClauseKind();
7129 // TBD
7130 if (K == OMPC_weak)
7131 return;
7132 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7133 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7134 continue;
7135 Kind = K;
7136 KindsEncountered.insert(K);
7137 }
7138 // We just need to correct Kind here. No need to set a bool saying it is
7139 // actually compare capture because we can tell from whether V and R are
7140 // nullptr.
7141 if (KindsEncountered.contains(OMPC_compare) &&
7142 KindsEncountered.contains(OMPC_capture))
7143 Kind = OMPC_compare;
7144 if (!MemOrderingSpecified) {
7145 llvm::AtomicOrdering DefaultOrder =
7146 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7147 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7148 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7149 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7150 Kind == OMPC_capture)) {
7151 AO = DefaultOrder;
7152 } else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7153 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7154 AO = llvm::AtomicOrdering::Release;
7155 } else if (Kind == OMPC_read) {
7156 assert(Kind == OMPC_read && "Unexpected atomic kind.");
7157 AO = llvm::AtomicOrdering::Acquire;
7158 }
7159 }
7160 }
7161
7162 if (KindsEncountered.contains(OMPC_compare) &&
7163 KindsEncountered.contains(OMPC_fail)) {
7164 Kind = OMPC_compare;
7165 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7166 if (FailClause) {
7167 OpenMPClauseKind FailParameter = FailClause->getFailParameter();
7168 if (FailParameter == llvm::omp::OMPC_relaxed)
7169 FailAO = llvm::AtomicOrdering::Monotonic;
7170 else if (FailParameter == llvm::omp::OMPC_acquire)
7171 FailAO = llvm::AtomicOrdering::Acquire;
7172 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7173 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7174 }
7175 }
7176
7177 LexicalScope Scope(*this, S.getSourceRange());
7178 EmitStopPoint(S.getAssociatedStmt());
7179 emitOMPAtomicExpr(*this, Kind, AO, FailAO, S.isPostfixUpdate(), S.getX(),
7180 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
7181 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
7182 S.isFailOnly(), S.getBeginLoc());
7183}
7184
7186 const OMPExecutableDirective &S,
7187 const RegionCodeGenTy &CodeGen) {
7188 assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind()));
7189 CodeGenModule &CGM = CGF.CGM;
7190
7191 // On device emit this construct as inlined code.
7192 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
7193 OMPLexicalScope Scope(CGF, S, OMPD_target);
7195 CGF, OMPD_target, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7196 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7197 });
7198 return;
7199 }
7200
7202 llvm::Function *Fn = nullptr;
7203 llvm::Constant *FnID = nullptr;
7204
7205 const Expr *IfCond = nullptr;
7206 // Check for the at most one if clause associated with the target region.
7207 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
7208 if (C->getNameModifier() == OMPD_unknown ||
7209 C->getNameModifier() == OMPD_target) {
7210 IfCond = C->getCondition();
7211 break;
7212 }
7213 }
7214
7215 // Check if we have any device clause associated with the directive.
7216 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device(
7217 nullptr, OMPC_DEVICE_unknown);
7218 if (auto *C = S.getSingleClause<OMPDeviceClause>())
7219 Device.setPointerAndInt(C->getDevice(), C->getModifier());
7220
7221 // Check if we have an if clause whose conditional always evaluates to false
7222 // or if we do not have any targets specified. If so the target region is not
7223 // an offload entry point.
7224 bool IsOffloadEntry = true;
7225 if (IfCond) {
7226 bool Val;
7227 if (CGF.ConstantFoldsToSimpleInteger(IfCond, Val) && !Val)
7228 IsOffloadEntry = false;
7229 }
7230 if (CGM.getLangOpts().OMPTargetTriples.empty())
7231 IsOffloadEntry = false;
7232
7233 if (CGM.getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7234 CGM.getDiags().Report(diag::err_missing_mandatory_offloading);
7235 }
7236
7237 assert(CGF.CurFuncDecl && "No parent declaration for target region!");
7238 StringRef ParentName;
7239 // In case we have Ctors/Dtors we use the complete type variant to produce
7240 // the mangling of the device outlined kernel.
7241 if (const auto *D = dyn_cast<CXXConstructorDecl>(CGF.CurFuncDecl))
7242 ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete));
7243 else if (const auto *D = dyn_cast<CXXDestructorDecl>(CGF.CurFuncDecl))
7244 ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete));
7245 else
7246 ParentName =
7248
7249 // Emit target region as a standalone region.
7250 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID,
7251 IsOffloadEntry, CodeGen);
7252 OMPLexicalScope Scope(CGF, S, OMPD_task);
7253 auto &&SizeEmitter =
7254 [IsOffloadEntry](CodeGenFunction &CGF,
7255 const OMPLoopDirective &D) -> llvm::Value * {
7256 if (IsOffloadEntry) {
7257 OMPLoopScope(CGF, D);
7258 // Emit calculation of the iterations count.
7259 llvm::Value *NumIterations = CGF.EmitScalarExpr(D.getNumIterations());
7260 NumIterations = CGF.Builder.CreateIntCast(NumIterations, CGF.Int64Ty,
7261 /*isSigned=*/false);
7262 return NumIterations;
7263 }
7264 return nullptr;
7265 };
7266 CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device,
7267 SizeEmitter);
7268}
7269
7271 PrePostActionTy &Action) {
7272 Action.Enter(CGF);
7273 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7274 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
7275 CGF.EmitOMPPrivateClause(S, PrivateScope);
7276 (void)PrivateScope.Privatize();
7277 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
7279
7280 CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7281 CGF.EnsureInsertPoint();
7282}
7283
7285 StringRef ParentName,
7286 const OMPTargetDirective &S) {
7287 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7288 emitTargetRegion(CGF, S, Action);
7289 };
7290 llvm::Function *Fn;
7291 llvm::Constant *Addr;
7292 // Emit target region as a standalone region.
7293 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7294 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7295 assert(Fn && Addr && "Target device function emission failed.");
7296}
7297
7299 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7300 emitTargetRegion(CGF, S, Action);
7301 };
7303}
7304
7306 const OMPExecutableDirective &S,
7307 OpenMPDirectiveKind InnermostKind,
7308 const RegionCodeGenTy &CodeGen) {
7309 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7310 llvm::Function *OutlinedFn =
7312 CGF, S, *CS->getCapturedDecl()->param_begin(), InnermostKind,
7313 CodeGen);
7314
7315 const auto *NT = S.getSingleClause<OMPNumTeamsClause>();
7316 const auto *TL = S.getSingleClause<OMPThreadLimitClause>();
7317 if (NT || TL) {
7318 const Expr *NumTeams = NT ? NT->getNumTeams().front() : nullptr;
7319 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() : nullptr;
7320
7321 CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit,
7322 S.getBeginLoc());
7323 }
7324
7325 OMPTeamsScope Scope(CGF, S);
7327 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
7328 CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getBeginLoc(), OutlinedFn,
7329 CapturedVars);
7330}
7331
7333 // Emit teams region as a standalone region.
7334 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7335 Action.Enter(CGF);
7336 OMPPrivateScope PrivateScope(CGF);
7337 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
7338 CGF.EmitOMPPrivateClause(S, PrivateScope);
7339 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7340 (void)PrivateScope.Privatize();
7341 CGF.EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7342 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7343 };
7344 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
7346 [](CodeGenFunction &) { return nullptr; });
7347}
7348
7350 const OMPTargetTeamsDirective &S) {
7351 auto *CS = S.getCapturedStmt(OMPD_teams);
7352 Action.Enter(CGF);
7353 // Emit teams region as a standalone region.
7354 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
7355 Action.Enter(CGF);
7356 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7357 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
7358 CGF.EmitOMPPrivateClause(S, PrivateScope);
7359 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7360 (void)PrivateScope.Privatize();
7361 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
7363 CGF.EmitStmt(CS->getCapturedStmt());
7364 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7365 };
7366 emitCommonOMPTeamsDirective(CGF, S, OMPD_teams, CodeGen);
7368 [](CodeGenFunction &) { return nullptr; });
7369}
7370
7372 CodeGenModule &CGM, StringRef ParentName,
7373 const OMPTargetTeamsDirective &S) {
7374 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7375 emitTargetTeamsRegion(CGF, Action, S);
7376 };
7377 llvm::Function *Fn;
7378 llvm::Constant *Addr;
7379 // Emit target region as a standalone region.
7380 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7381 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7382 assert(Fn && Addr && "Target device function emission failed.");
7383}
7384
7386 const OMPTargetTeamsDirective &S) {
7387 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7388 emitTargetTeamsRegion(CGF, Action, S);
7389 };
7391}
7392
7393static void
7396 Action.Enter(CGF);
7397 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7399 };
7400
7401 // Emit teams region as a standalone region.
7402 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7403 PrePostActionTy &Action) {
7404 Action.Enter(CGF);
7405 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7406 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7407 (void)PrivateScope.Privatize();
7408 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7409 CodeGenDistribute);
7410 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7411 };
7412 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute, CodeGen);
7414 [](CodeGenFunction &) { return nullptr; });
7415}
7416
7418 CodeGenModule &CGM, StringRef ParentName,
7420 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7421 emitTargetTeamsDistributeRegion(CGF, Action, S);
7422 };
7423 llvm::Function *Fn;
7424 llvm::Constant *Addr;
7425 // Emit target region as a standalone region.
7426 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7427 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7428 assert(Fn && Addr && "Target device function emission failed.");
7429}
7430
7433 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7434 emitTargetTeamsDistributeRegion(CGF, Action, S);
7435 };
7437}
7438
7440 CodeGenFunction &CGF, PrePostActionTy &Action,
7442 Action.Enter(CGF);
7443 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7445 };
7446
7447 // Emit teams region as a standalone region.
7448 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7449 PrePostActionTy &Action) {
7450 Action.Enter(CGF);
7451 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7452 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7453 (void)PrivateScope.Privatize();
7454 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7455 CodeGenDistribute);
7456 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7457 };
7458 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_simd, CodeGen);
7460 [](CodeGenFunction &) { return nullptr; });
7461}
7462
7464 CodeGenModule &CGM, StringRef ParentName,
7466 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7468 };
7469 llvm::Function *Fn;
7470 llvm::Constant *Addr;
7471 // Emit target region as a standalone region.
7472 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7473 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7474 assert(Fn && Addr && "Target device function emission failed.");
7475}
7476
7479 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7481 };
7483}
7484
7486 const OMPTeamsDistributeDirective &S) {
7487
7488 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7490 };
7491
7492 // Emit teams region as a standalone region.
7493 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7494 PrePostActionTy &Action) {
7495 Action.Enter(CGF);
7496 OMPPrivateScope PrivateScope(CGF);
7497 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7498 (void)PrivateScope.Privatize();
7499 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7500 CodeGenDistribute);
7501 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7502 };
7503 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
7505 [](CodeGenFunction &) { return nullptr; });
7506}
7507
7510 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7512 };
7513
7514 // Emit teams region as a standalone region.
7515 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7516 PrePostActionTy &Action) {
7517 Action.Enter(CGF);
7518 OMPPrivateScope PrivateScope(CGF);
7519 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7520 (void)PrivateScope.Privatize();
7521 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
7522 CodeGenDistribute);
7523 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7524 };
7525 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_simd, CodeGen);
7527 [](CodeGenFunction &) { return nullptr; });
7528}
7529
7532 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7534 S.getDistInc());
7535 };
7536
7537 // Emit teams region as a standalone region.
7538 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7539 PrePostActionTy &Action) {
7540 Action.Enter(CGF);
7541 OMPPrivateScope PrivateScope(CGF);
7542 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7543 (void)PrivateScope.Privatize();
7544 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7545 CodeGenDistribute);
7546 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7547 };
7548 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for, CodeGen);
7550 [](CodeGenFunction &) { return nullptr; });
7551}
7552
7555 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7557 S.getDistInc());
7558 };
7559
7560 // Emit teams region as a standalone region.
7561 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7562 PrePostActionTy &Action) {
7563 Action.Enter(CGF);
7564 OMPPrivateScope PrivateScope(CGF);
7565 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7566 (void)PrivateScope.Privatize();
7568 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
7569 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7570 };
7571 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for_simd,
7572 CodeGen);
7574 [](CodeGenFunction &) { return nullptr; });
7575}
7576
7578 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
7579 llvm::Value *Device = nullptr;
7580 llvm::Value *NumDependences = nullptr;
7581 llvm::Value *DependenceList = nullptr;
7582
7583 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
7584 Device = EmitScalarExpr(C->getDevice());
7585
7586 // Build list and emit dependences
7589 if (!Data.Dependences.empty()) {
7590 Address DependenciesArray = Address::invalid();
7591 std::tie(NumDependences, DependenciesArray) =
7592 CGM.getOpenMPRuntime().emitDependClause(*this, Data.Dependences,
7593 S.getBeginLoc());
7594 DependenceList = DependenciesArray.emitRawPointer(*this);
7595 }
7596 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7597
7598 assert(!(Data.HasNowaitClause && !(S.getSingleClause<OMPInitClause>() ||
7599 S.getSingleClause<OMPDestroyClause>() ||
7600 S.getSingleClause<OMPUseClause>())) &&
7601 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7602
7603 auto ItOMPInitClause = S.getClausesOfKind<OMPInitClause>();
7604 if (!ItOMPInitClause.empty()) {
7605 // Look at the multiple init clauses
7606 for (const OMPInitClause *C : ItOMPInitClause) {
7607 llvm::Value *InteropvarPtr =
7608 EmitLValue(C->getInteropVar()).getPointer(*this);
7609 llvm::omp::OMPInteropType InteropType =
7610 llvm::omp::OMPInteropType::Unknown;
7611 if (C->getIsTarget()) {
7612 InteropType = llvm::omp::OMPInteropType::Target;
7613 } else {
7614 assert(C->getIsTargetSync() &&
7615 "Expected interop-type target/targetsync");
7616 InteropType = llvm::omp::OMPInteropType::TargetSync;
7617 }
7618 OMPBuilder.createOMPInteropInit(Builder, InteropvarPtr, InteropType,
7619 Device, NumDependences, DependenceList,
7620 Data.HasNowaitClause);
7621 }
7622 }
7623 auto ItOMPDestroyClause = S.getClausesOfKind<OMPDestroyClause>();
7624 if (!ItOMPDestroyClause.empty()) {
7625 // Look at the multiple destroy clauses
7626 for (const OMPDestroyClause *C : ItOMPDestroyClause) {
7627 llvm::Value *InteropvarPtr =
7628 EmitLValue(C->getInteropVar()).getPointer(*this);
7629 OMPBuilder.createOMPInteropDestroy(Builder, InteropvarPtr, Device,
7630 NumDependences, DependenceList,
7631 Data.HasNowaitClause);
7632 }
7633 }
7634 auto ItOMPUseClause = S.getClausesOfKind<OMPUseClause>();
7635 if (!ItOMPUseClause.empty()) {
7636 // Look at the multiple use clauses
7637 for (const OMPUseClause *C : ItOMPUseClause) {
7638 llvm::Value *InteropvarPtr =
7639 EmitLValue(C->getInteropVar()).getPointer(*this);
7640 OMPBuilder.createOMPInteropUse(Builder, InteropvarPtr, Device,
7641 NumDependences, DependenceList,
7642 Data.HasNowaitClause);
7643 }
7644 }
7645}
7646
7649 PrePostActionTy &Action) {
7650 Action.Enter(CGF);
7651 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7653 S.getDistInc());
7654 };
7655
7656 // Emit teams region as a standalone region.
7657 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7658 PrePostActionTy &Action) {
7659 Action.Enter(CGF);
7660 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7661 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7662 (void)PrivateScope.Privatize();
7664 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
7665 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7666 };
7667
7668 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for,
7669 CodeGenTeams);
7671 [](CodeGenFunction &) { return nullptr; });
7672}
7673
7675 CodeGenModule &CGM, StringRef ParentName,
7677 // Emit SPMD target teams distribute parallel for region as a standalone
7678 // region.
7679 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7681 };
7682 llvm::Function *Fn;
7683 llvm::Constant *Addr;
7684 // Emit target region as a standalone region.
7685 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7686 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7687 assert(Fn && Addr && "Target device function emission failed.");
7688}
7689
7697
7699 CodeGenFunction &CGF,
7701 PrePostActionTy &Action) {
7702 Action.Enter(CGF);
7703 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7705 S.getDistInc());
7706 };
7707
7708 // Emit teams region as a standalone region.
7709 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7710 PrePostActionTy &Action) {
7711 Action.Enter(CGF);
7712 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7713 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7714 (void)PrivateScope.Privatize();
7716 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
7717 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
7718 };
7719
7720 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for_simd,
7721 CodeGenTeams);
7723 [](CodeGenFunction &) { return nullptr; });
7724}
7725
7727 CodeGenModule &CGM, StringRef ParentName,
7729 // Emit SPMD target teams distribute parallel for simd region as a standalone
7730 // region.
7731 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
7733 };
7734 llvm::Function *Fn;
7735 llvm::Constant *Addr;
7736 // Emit target region as a standalone region.
7737 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7738 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
7739 assert(Fn && Addr && "Target device function emission failed.");
7740}
7741
7749
7752 CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getBeginLoc(),
7753 S.getCancelRegion());
7754}
7755
7757 const Expr *IfCond = nullptr;
7758 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
7759 if (C->getNameModifier() == OMPD_unknown ||
7760 C->getNameModifier() == OMPD_cancel) {
7761 IfCond = C->getCondition();
7762 break;
7763 }
7764 }
7765 if (CGM.getLangOpts().OpenMPIRBuilder) {
7766 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
7767 // TODO: This check is necessary as we only generate `omp parallel` through
7768 // the OpenMPIRBuilder for now.
7769 if (S.getCancelRegion() == OMPD_parallel ||
7770 S.getCancelRegion() == OMPD_sections ||
7771 S.getCancelRegion() == OMPD_section) {
7772 llvm::Value *IfCondition = nullptr;
7773 if (IfCond)
7774 IfCondition = EmitScalarExpr(IfCond,
7775 /*IgnoreResultAssign=*/true);
7776 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7777 OMPBuilder.createCancel(Builder, IfCondition, S.getCancelRegion()));
7778 return Builder.restoreIP(AfterIP);
7779 }
7780 }
7781
7782 CGM.getOpenMPRuntime().emitCancelCall(*this, S.getBeginLoc(), IfCond,
7783 S.getCancelRegion());
7784}
7785
7788 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7789 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7790 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7791 return ReturnBlock;
7792 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7793 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7794 Kind == OMPD_distribute_parallel_for ||
7795 Kind == OMPD_target_parallel_for ||
7796 Kind == OMPD_teams_distribute_parallel_for ||
7797 Kind == OMPD_target_teams_distribute_parallel_for);
7798 return OMPCancelStack.getExitBlock();
7799}
7800
7802 const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope,
7803 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7804 CaptureDeviceAddrMap) {
7805 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7806 for (const Expr *OrigVarIt : C.varlist()) {
7807 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(OrigVarIt)->getDecl());
7808 if (!Processed.insert(OrigVD).second)
7809 continue;
7810
7811 // In order to identify the right initializer we need to match the
7812 // declaration used by the mapping logic. In some cases we may get
7813 // OMPCapturedExprDecl that refers to the original declaration.
7814 const ValueDecl *MatchingVD = OrigVD;
7815 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7816 // OMPCapturedExprDecl are used to privative fields of the current
7817 // structure.
7818 const auto *ME = cast<MemberExpr>(OED->getInit());
7819 assert(isa<CXXThisExpr>(ME->getBase()->IgnoreImpCasts()) &&
7820 "Base should be the current struct!");
7821 MatchingVD = ME->getMemberDecl();
7822 }
7823
7824 // If we don't have information about the current list item, move on to
7825 // the next one.
7826 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7827 if (InitAddrIt == CaptureDeviceAddrMap.end())
7828 continue;
7829
7830 llvm::Type *Ty = ConvertTypeForMem(OrigVD->getType().getNonReferenceType());
7831
7832 // Return the address of the private variable.
7833 bool IsRegistered = PrivateScope.addPrivate(
7834 OrigVD,
7835 Address(InitAddrIt->second, Ty,
7836 getContext().getTypeAlignInChars(getContext().VoidPtrTy)));
7837 assert(IsRegistered && "firstprivate var already registered as private");
7838 // Silence the warning about unused variable.
7839 (void)IsRegistered;
7840 }
7841}
7842
7843static const VarDecl *getBaseDecl(const Expr *Ref) {
7844 const Expr *Base = Ref->IgnoreParenImpCasts();
7845 while (const auto *OASE = dyn_cast<ArraySectionExpr>(Base))
7846 Base = OASE->getBase()->IgnoreParenImpCasts();
7847 while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Base))
7848 Base = ASE->getBase()->IgnoreParenImpCasts();
7849 return cast<VarDecl>(cast<DeclRefExpr>(Base)->getDecl());
7850}
7851
7853 const OMPUseDeviceAddrClause &C, OMPPrivateScope &PrivateScope,
7854 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7855 CaptureDeviceAddrMap) {
7856 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7857 for (const Expr *Ref : C.varlist()) {
7858 const VarDecl *OrigVD = getBaseDecl(Ref);
7859 if (!Processed.insert(OrigVD).second)
7860 continue;
7861 // In order to identify the right initializer we need to match the
7862 // declaration used by the mapping logic. In some cases we may get
7863 // OMPCapturedExprDecl that refers to the original declaration.
7864 const ValueDecl *MatchingVD = OrigVD;
7865 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7866 // OMPCapturedExprDecl are used to privative fields of the current
7867 // structure.
7868 const auto *ME = cast<MemberExpr>(OED->getInit());
7869 assert(isa<CXXThisExpr>(ME->getBase()) &&
7870 "Base should be the current struct!");
7871 MatchingVD = ME->getMemberDecl();
7872 }
7873
7874 // If we don't have information about the current list item, move on to
7875 // the next one.
7876 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7877 if (InitAddrIt == CaptureDeviceAddrMap.end())
7878 continue;
7879
7880 llvm::Type *Ty = ConvertTypeForMem(OrigVD->getType().getNonReferenceType());
7881
7882 Address PrivAddr =
7883 Address(InitAddrIt->second, Ty,
7884 getContext().getTypeAlignInChars(getContext().VoidPtrTy));
7885 // For declrefs and variable length array need to load the pointer for
7886 // correct mapping, since the pointer to the data was passed to the runtime.
7887 if (isa<DeclRefExpr>(Ref->IgnoreParenImpCasts()) ||
7888 MatchingVD->getType()->isArrayType()) {
7890 OrigVD->getType().getNonReferenceType());
7891 PrivAddr =
7893 PtrTy->castAs<PointerType>());
7894 }
7895
7896 (void)PrivateScope.addPrivate(OrigVD, PrivAddr);
7897 }
7898}
7899
7900// Generate the instructions for '#pragma omp target data' directive.
7902 const OMPTargetDataDirective &S) {
7903 // Emit vtable only from host for target data directive.
7904 if (!CGM.getLangOpts().OpenMPIsTargetDevice)
7905 CGM.getOpenMPRuntime().registerVTable(S);
7906
7907 CGOpenMPRuntime::TargetDataInfo Info(/*RequiresDevicePointerInfo=*/true,
7908 /*SeparateBeginEndCalls=*/true);
7909
7910 // Create a pre/post action to signal the privatization of the device pointer.
7911 // This action can be replaced by the OpenMP runtime code generation to
7912 // deactivate privatization.
7913 bool PrivatizeDevicePointers = false;
7914 class DevicePointerPrivActionTy : public PrePostActionTy {
7915 bool &PrivatizeDevicePointers;
7916
7917 public:
7918 explicit DevicePointerPrivActionTy(bool &PrivatizeDevicePointers)
7919 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7920 void Enter(CodeGenFunction &CGF) override {
7921 PrivatizeDevicePointers = true;
7922 }
7923 };
7924 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7925
7926 auto &&CodeGen = [&](CodeGenFunction &CGF, PrePostActionTy &Action) {
7927 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
7928 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7929 };
7930
7931 // Codegen that selects whether to generate the privatization code or not.
7932 auto &&PrivCodeGen = [&](CodeGenFunction &CGF, PrePostActionTy &Action) {
7933 RegionCodeGenTy RCG(InnermostCodeGen);
7934 PrivatizeDevicePointers = false;
7935
7936 // Call the pre-action to change the status of PrivatizeDevicePointers if
7937 // needed.
7938 Action.Enter(CGF);
7939
7940 if (PrivatizeDevicePointers) {
7941 OMPPrivateScope PrivateScope(CGF);
7942 // Emit all instances of the use_device_ptr clause.
7943 for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>())
7944 CGF.EmitOMPUseDevicePtrClause(*C, PrivateScope,
7946 for (const auto *C : S.getClausesOfKind<OMPUseDeviceAddrClause>())
7947 CGF.EmitOMPUseDeviceAddrClause(*C, PrivateScope,
7949 (void)PrivateScope.Privatize();
7950 RCG(CGF);
7951 } else {
7952 // If we don't have target devices, don't bother emitting the data
7953 // mapping code.
7954 std::optional<OpenMPDirectiveKind> CaptureRegion;
7955 if (CGM.getLangOpts().OMPTargetTriples.empty()) {
7956 // Emit helper decls of the use_device_ptr/use_device_addr clauses.
7957 for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>())
7958 for (const Expr *E : C->varlist()) {
7959 const Decl *D = cast<DeclRefExpr>(E)->getDecl();
7960 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7961 CGF.EmitVarDecl(*OED);
7962 }
7963 for (const auto *C : S.getClausesOfKind<OMPUseDeviceAddrClause>())
7964 for (const Expr *E : C->varlist()) {
7965 const Decl *D = getBaseDecl(E);
7966 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7967 CGF.EmitVarDecl(*OED);
7968 }
7969 } else {
7970 CaptureRegion = OMPD_unknown;
7971 }
7972
7973 OMPLexicalScope Scope(CGF, S, CaptureRegion);
7974 RCG(CGF);
7975 }
7976 };
7977
7978 // Forward the provided action to the privatization codegen.
7979 RegionCodeGenTy PrivRCG(PrivCodeGen);
7980 PrivRCG.setAction(Action);
7981
7982 // Notwithstanding the body of the region is emitted as inlined directive,
7983 // we don't use an inline scope as changes in the references inside the
7984 // region are expected to be visible outside, so we do not privative them.
7985 OMPLexicalScope Scope(CGF, S);
7986 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data,
7987 PrivRCG);
7988 };
7989
7991
7992 // If we don't have target devices, don't bother emitting the data mapping
7993 // code.
7994 if (CGM.getLangOpts().OMPTargetTriples.empty()) {
7995 RCG(*this);
7996 return;
7997 }
7998
7999 // Check if we have any if clause associated with the directive.
8000 const Expr *IfCond = nullptr;
8001 if (const auto *C = S.getSingleClause<OMPIfClause>())
8002 IfCond = C->getCondition();
8003
8004 // Check if we have any device clause associated with the directive.
8005 const Expr *Device = nullptr;
8006 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
8007 Device = C->getDevice();
8008
8009 // Set the action to signal privatization of device pointers.
8010 RCG.setAction(PrivAction);
8011
8012 // Emit region code.
8013 CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, RCG,
8014 Info);
8015}
8016
8018 const OMPTargetEnterDataDirective &S) {
8019 // If we don't have target devices, don't bother emitting the data mapping
8020 // code.
8021 if (CGM.getLangOpts().OMPTargetTriples.empty())
8022 return;
8023
8024 // Check if we have any if clause associated with the directive.
8025 const Expr *IfCond = nullptr;
8026 if (const auto *C = S.getSingleClause<OMPIfClause>())
8027 IfCond = C->getCondition();
8028
8029 // Check if we have any device clause associated with the directive.
8030 const Expr *Device = nullptr;
8031 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
8032 Device = C->getDevice();
8033
8034 OMPLexicalScope Scope(*this, S, OMPD_task);
8035 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
8036}
8037
8039 const OMPTargetExitDataDirective &S) {
8040 // If we don't have target devices, don't bother emitting the data mapping
8041 // code.
8042 if (CGM.getLangOpts().OMPTargetTriples.empty())
8043 return;
8044
8045 // Check if we have any if clause associated with the directive.
8046 const Expr *IfCond = nullptr;
8047 if (const auto *C = S.getSingleClause<OMPIfClause>())
8048 IfCond = C->getCondition();
8049
8050 // Check if we have any device clause associated with the directive.
8051 const Expr *Device = nullptr;
8052 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
8053 Device = C->getDevice();
8054
8055 OMPLexicalScope Scope(*this, S, OMPD_task);
8056 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
8057}
8058
8061 PrePostActionTy &Action) {
8062 // Get the captured statement associated with the 'parallel' region.
8063 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8064 Action.Enter(CGF);
8065 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
8066 Action.Enter(CGF);
8067 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
8068 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
8069 CGF.EmitOMPPrivateClause(S, PrivateScope);
8070 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
8071 (void)PrivateScope.Privatize();
8072 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
8074 // TODO: Add support for clauses.
8075 CGF.EmitStmt(CS->getCapturedStmt());
8076 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
8077 };
8078 emitCommonOMPParallelDirective(CGF, S, OMPD_parallel, CodeGen,
8081 [](CodeGenFunction &) { return nullptr; });
8082}
8083
8085 CodeGenModule &CGM, StringRef ParentName,
8086 const OMPTargetParallelDirective &S) {
8087 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8088 emitTargetParallelRegion(CGF, S, Action);
8089 };
8090 llvm::Function *Fn;
8091 llvm::Constant *Addr;
8092 // Emit target region as a standalone region.
8093 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8094 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
8095 assert(Fn && Addr && "Target device function emission failed.");
8096}
8097
8099 const OMPTargetParallelDirective &S) {
8100 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8101 emitTargetParallelRegion(CGF, S, Action);
8102 };
8104}
8105
8108 PrePostActionTy &Action) {
8109 Action.Enter(CGF);
8110 // Emit directive as a combined directive that consists of two implicit
8111 // directives: 'parallel' with 'for' directive.
8112 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8113 Action.Enter(CGF);
8115 CGF, OMPD_target_parallel_for, S.hasCancel());
8116 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
8118 };
8119 emitCommonOMPParallelDirective(CGF, S, OMPD_for, CodeGen,
8121}
8122
8124 CodeGenModule &CGM, StringRef ParentName,
8126 // Emit SPMD target parallel for region as a standalone region.
8127 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8128 emitTargetParallelForRegion(CGF, S, Action);
8129 };
8130 llvm::Function *Fn;
8131 llvm::Constant *Addr;
8132 // Emit target region as a standalone region.
8133 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8134 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
8135 assert(Fn && Addr && "Target device function emission failed.");
8136}
8137
8140 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8141 emitTargetParallelForRegion(CGF, S, Action);
8142 };
8144}
8145
8146static void
8149 PrePostActionTy &Action) {
8150 Action.Enter(CGF);
8151 // Emit directive as a combined directive that consists of two implicit
8152 // directives: 'parallel' with 'for' directive.
8153 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8154 Action.Enter(CGF);
8155 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
8157 };
8158 emitCommonOMPParallelDirective(CGF, S, OMPD_simd, CodeGen,
8160}
8161
8163 CodeGenModule &CGM, StringRef ParentName,
8165 // Emit SPMD target parallel for region as a standalone region.
8166 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8167 emitTargetParallelForSimdRegion(CGF, S, Action);
8168 };
8169 llvm::Function *Fn;
8170 llvm::Constant *Addr;
8171 // Emit target region as a standalone region.
8172 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8173 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
8174 assert(Fn && Addr && "Target device function emission failed.");
8175}
8176
8179 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8180 emitTargetParallelForSimdRegion(CGF, S, Action);
8181 };
8183}
8184
8185/// Emit a helper variable and return corresponding lvalue.
8186static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper,
8187 const ImplicitParamDecl *PVD,
8189 const auto *VDecl = cast<VarDecl>(Helper->getDecl());
8190 Privates.addPrivate(VDecl, CGF.GetAddrOfLocalVar(PVD));
8191}
8192
8194 assert(isOpenMPTaskLoopDirective(S.getDirectiveKind()));
8195 // Emit outlined function for task construct.
8196 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8197 Address CapturedStruct = Address::invalid();
8198 {
8199 OMPLexicalScope Scope(*this, S, OMPD_taskloop, /*EmitPreInitStmt=*/false);
8200 CapturedStruct = GenerateCapturedStmtArgument(*CS);
8201 }
8202 CanQualType SharedsTy =
8204 const Expr *IfCond = nullptr;
8205 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
8206 if (C->getNameModifier() == OMPD_unknown ||
8207 C->getNameModifier() == OMPD_taskloop) {
8208 IfCond = C->getCondition();
8209 break;
8210 }
8211 }
8212
8214 // Check if taskloop must be emitted without taskgroup.
8215 Data.Nogroup = S.getSingleClause<OMPNogroupClause>();
8216 // TODO: Check if we should emit tied or untied task.
8217 Data.Tied = true;
8218 // Set scheduling for taskloop
8219 if (const auto *Clause = S.getSingleClause<OMPGrainsizeClause>()) {
8220 // grainsize clause
8221 Data.Schedule.setInt(/*IntVal=*/false);
8222 Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize()));
8223 Data.HasModifier =
8224 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ? true : false;
8225 } else if (const auto *Clause = S.getSingleClause<OMPNumTasksClause>()) {
8226 // num_tasks clause
8227 Data.Schedule.setInt(/*IntVal=*/true);
8228 Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks()));
8229 Data.HasModifier =
8230 (Clause->getModifier() == OMPC_NUMTASKS_strict) ? true : false;
8231 }
8232
8233 auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) {
8234 // if (PreCond) {
8235 // for (IV in 0..LastIteration) BODY;
8236 // <Final counter/linear vars updates>;
8237 // }
8238 //
8239
8240 // Emit: if (PreCond) - begin.
8241 // If the condition constant folds and can be elided, avoid emitting the
8242 // whole loop.
8243 bool CondConstant;
8244 llvm::BasicBlock *ContBlock = nullptr;
8245 OMPLoopScope PreInitScope(CGF, S);
8246 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
8247 if (!CondConstant)
8248 return;
8249 } else {
8250 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("taskloop.if.then");
8251 ContBlock = CGF.createBasicBlock("taskloop.if.end");
8252 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
8253 CGF.getProfileCount(&S));
8254 CGF.EmitBlock(ThenBlock);
8255 CGF.incrementProfileCounter(&S);
8256 }
8257
8258 (void)CGF.EmitOMPLinearClauseInit(S);
8259
8260 OMPPrivateScope LoopScope(CGF);
8261 // Emit helper vars inits.
8262 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8263 auto *I = CS->getCapturedDecl()->param_begin();
8264 auto *LBP = std::next(I, LowerBound);
8265 auto *UBP = std::next(I, UpperBound);
8266 auto *STP = std::next(I, Stride);
8267 auto *LIP = std::next(I, LastIter);
8268 mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP,
8269 LoopScope);
8270 mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP,
8271 LoopScope);
8272 mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope);
8273 mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP,
8274 LoopScope);
8275 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8276 CGF.EmitOMPLinearClause(S, LoopScope);
8277 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8278 (void)LoopScope.Privatize();
8279 // Emit the loop iteration variable.
8280 const Expr *IVExpr = S.getIterationVariable();
8281 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
8282 CGF.EmitVarDecl(*IVDecl);
8283 CGF.EmitIgnoredExpr(S.getInit());
8284
8285 // Emit the iterations count variable.
8286 // If it is not a variable, Sema decided to calculate iterations count on
8287 // each iteration (e.g., it is foldable into a constant).
8288 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8289 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
8290 // Emit calculation of the iterations count.
8291 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8292 }
8293
8294 {
8295 OMPLexicalScope Scope(CGF, S, OMPD_taskloop, /*EmitPreInitStmt=*/false);
8297 CGF, S,
8298 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
8299 if (isOpenMPSimdDirective(S.getDirectiveKind()))
8300 CGF.EmitOMPSimdInit(S);
8301 },
8302 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
8303 CGF.EmitOMPInnerLoop(
8304 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
8305 [&S](CodeGenFunction &CGF) {
8306 emitOMPLoopBodyWithStopPoint(CGF, S,
8307 CodeGenFunction::JumpDest());
8308 },
8309 [](CodeGenFunction &) {});
8310 });
8311 }
8312 // Emit: if (PreCond) - end.
8313 if (ContBlock) {
8314 CGF.EmitBranch(ContBlock);
8315 CGF.EmitBlock(ContBlock, true);
8316 }
8317 // Emit final copy of the lastprivate variables if IsLastIter != 0.
8318 if (HasLastprivateClause) {
8319 CGF.EmitOMPLastprivateClauseFinal(
8320 S, isOpenMPSimdDirective(S.getDirectiveKind()),
8321 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8322 CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
8323 (*LIP)->getType(), S.getBeginLoc())));
8324 }
8325 LoopScope.restoreMap();
8326 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8327 return CGF.Builder.CreateIsNotNull(
8328 CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
8329 (*LIP)->getType(), S.getBeginLoc()));
8330 });
8331 };
8332 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8333 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8334 const OMPTaskDataTy &Data) {
8335 auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8336 &Data](CodeGenFunction &CGF, PrePostActionTy &) {
8337 OMPLoopScope PreInitScope(CGF, S);
8338 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8339 OutlinedFn, SharedsTy,
8340 CapturedStruct, IfCond, Data);
8341 };
8342 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8343 CodeGen);
8344 };
8345 if (Data.Nogroup) {
8346 EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, Data);
8347 } else {
8348 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8349 *this,
8350 [&S, &BodyGen, &TaskGen, &Data](CodeGenFunction &CGF,
8351 PrePostActionTy &Action) {
8352 Action.Enter(CGF);
8353 CGF.EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen,
8354 Data);
8355 },
8356 S.getBeginLoc());
8357 }
8358}
8359
8365
8367 const OMPTaskLoopSimdDirective &S) {
8368 auto LPCRegion =
8370 OMPLexicalScope Scope(*this, S);
8372}
8373
8375 const OMPMasterTaskLoopDirective &S) {
8376 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8377 Action.Enter(CGF);
8379 };
8380 auto LPCRegion =
8382 OMPLexicalScope Scope(*this, S, std::nullopt, /*EmitPreInitStmt=*/false);
8383 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
8384}
8385
8387 const OMPMaskedTaskLoopDirective &S) {
8388 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8389 Action.Enter(CGF);
8391 };
8392 auto LPCRegion =
8394 OMPLexicalScope Scope(*this, S, std::nullopt, /*EmitPreInitStmt=*/false);
8395 CGM.getOpenMPRuntime().emitMaskedRegion(*this, CodeGen, S.getBeginLoc());
8396}
8397
8400 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8401 Action.Enter(CGF);
8403 };
8404 auto LPCRegion =
8406 OMPLexicalScope Scope(*this, S);
8407 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
8408}
8409
8412 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8413 Action.Enter(CGF);
8415 };
8416 auto LPCRegion =
8418 OMPLexicalScope Scope(*this, S);
8419 CGM.getOpenMPRuntime().emitMaskedRegion(*this, CodeGen, S.getBeginLoc());
8420}
8421
8424 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8425 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8426 PrePostActionTy &Action) {
8427 Action.Enter(CGF);
8429 };
8430 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
8431 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8432 S.getBeginLoc());
8433 };
8434 auto LPCRegion =
8436 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop, CodeGen,
8438}
8439
8442 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8443 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8444 PrePostActionTy &Action) {
8445 Action.Enter(CGF);
8447 };
8448 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
8449 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8450 S.getBeginLoc());
8451 };
8452 auto LPCRegion =
8454 emitCommonOMPParallelDirective(*this, S, OMPD_masked_taskloop, CodeGen,
8456}
8457
8460 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8461 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8462 PrePostActionTy &Action) {
8463 Action.Enter(CGF);
8465 };
8466 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
8467 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8468 S.getBeginLoc());
8469 };
8470 auto LPCRegion =
8472 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop_simd, CodeGen,
8474}
8475
8478 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8479 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8480 PrePostActionTy &Action) {
8481 Action.Enter(CGF);
8483 };
8484 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
8485 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8486 S.getBeginLoc());
8487 };
8488 auto LPCRegion =
8490 emitCommonOMPParallelDirective(*this, S, OMPD_masked_taskloop_simd, CodeGen,
8492}
8493
8494// Generate the instructions for '#pragma omp target update' directive.
8496 const OMPTargetUpdateDirective &S) {
8497 // If we don't have target devices, don't bother emitting the data mapping
8498 // code.
8499 if (CGM.getLangOpts().OMPTargetTriples.empty())
8500 return;
8501
8502 // Check if we have any if clause associated with the directive.
8503 const Expr *IfCond = nullptr;
8504 if (const auto *C = S.getSingleClause<OMPIfClause>())
8505 IfCond = C->getCondition();
8506
8507 // Check if we have any device clause associated with the directive.
8508 const Expr *Device = nullptr;
8509 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
8510 Device = C->getDevice();
8511
8512 OMPLexicalScope Scope(*this, S, OMPD_task);
8513 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
8514}
8515
8517 const OMPGenericLoopDirective &S) {
8518 // Always expect a bind clause on the loop directive. It it wasn't
8519 // in the source, it should have been added in sema.
8520
8522 if (const auto *C = S.getSingleClause<OMPBindClause>())
8523 BindKind = C->getBindKind();
8524
8525 switch (BindKind) {
8526 case OMPC_BIND_parallel: // for
8527 return emitOMPForDirective(S, *this, CGM, /*HasCancel=*/false);
8528 case OMPC_BIND_teams: // distribute
8529 return emitOMPDistributeDirective(S, *this, CGM);
8530 case OMPC_BIND_thread: // simd
8531 return emitOMPSimdDirective(S, *this, CGM);
8532 case OMPC_BIND_unknown:
8533 break;
8534 }
8535
8536 // Unimplemented, just inline the underlying statement for now.
8537 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8538 // Emit the loop iteration variable.
8539 const Stmt *CS =
8540 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt();
8541 const auto *ForS = dyn_cast<ForStmt>(CS);
8542 if (ForS && !isa<DeclStmt>(ForS->getInit())) {
8543 OMPPrivateScope LoopScope(CGF);
8544 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8545 (void)LoopScope.Privatize();
8546 CGF.EmitStmt(CS);
8547 LoopScope.restoreMap();
8548 } else {
8549 CGF.EmitStmt(CS);
8550 }
8551 };
8552 OMPLexicalScope Scope(*this, S, OMPD_unknown);
8553 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_loop, CodeGen);
8554}
8555
8557 const OMPLoopDirective &S) {
8558 // Emit combined directive as if its constituent constructs are 'parallel'
8559 // and 'for'.
8560 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8561 Action.Enter(CGF);
8562 emitOMPCopyinClause(CGF, S);
8563 (void)emitWorksharingDirective(CGF, S, /*HasCancel=*/false);
8564 };
8565 {
8566 auto LPCRegion =
8568 emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen,
8570 }
8571 // Check for outer lastprivate conditional update.
8573}
8574
8577 // To be consistent with current behavior of 'target teams loop', emit
8578 // 'teams loop' as if its constituent constructs are 'teams' and 'distribute'.
8579 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
8581 };
8582
8583 // Emit teams region as a standalone region.
8584 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8585 PrePostActionTy &Action) {
8586 Action.Enter(CGF);
8587 OMPPrivateScope PrivateScope(CGF);
8588 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
8589 (void)PrivateScope.Privatize();
8590 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
8591 CodeGenDistribute);
8592 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
8593 };
8594 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
8596 [](CodeGenFunction &) { return nullptr; });
8597}
8598
8599#ifndef NDEBUG
8601 std::string StatusMsg,
8602 const OMPExecutableDirective &D) {
8603 bool IsDevice = CGF.CGM.getLangOpts().OpenMPIsTargetDevice;
8604 if (IsDevice)
8605 StatusMsg += ": DEVICE";
8606 else
8607 StatusMsg += ": HOST";
8608 SourceLocation L = D.getBeginLoc();
8609 auto &SM = CGF.getContext().getSourceManager();
8610 PresumedLoc PLoc = SM.getPresumedLoc(L);
8611 const char *FileName = PLoc.isValid() ? PLoc.getFilename() : nullptr;
8612 unsigned LineNo =
8613 PLoc.isValid() ? PLoc.getLine() : SM.getExpansionLineNumber(L);
8614 llvm::dbgs() << StatusMsg << ": " << FileName << ": " << LineNo << "\n";
8615}
8616#endif
8617
8619 CodeGenFunction &CGF, PrePostActionTy &Action,
8621 Action.Enter(CGF);
8622 // Emit 'teams loop' as if its constituent constructs are 'distribute,
8623 // 'parallel, and 'for'.
8624 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
8626 S.getDistInc());
8627 };
8628
8629 // Emit teams region as a standalone region.
8630 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8631 PrePostActionTy &Action) {
8632 Action.Enter(CGF);
8633 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
8634 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
8635 (void)PrivateScope.Privatize();
8637 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
8638 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
8639 };
8640 DEBUG_WITH_TYPE(TTL_CODEGEN_TYPE,
8642 CGF, TTL_CODEGEN_TYPE " as parallel for", S));
8643 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for,
8644 CodeGenTeams);
8646 [](CodeGenFunction &) { return nullptr; });
8647}
8648
8650 CodeGenFunction &CGF, PrePostActionTy &Action,
8652 Action.Enter(CGF);
8653 // Emit 'teams loop' as if its constituent construct is 'distribute'.
8654 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
8656 };
8657
8658 // Emit teams region as a standalone region.
8659 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8660 PrePostActionTy &Action) {
8661 Action.Enter(CGF);
8662 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
8663 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
8664 (void)PrivateScope.Privatize();
8666 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
8667 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
8668 };
8669 DEBUG_WITH_TYPE(TTL_CODEGEN_TYPE,
8671 CGF, TTL_CODEGEN_TYPE " as distribute", S));
8672 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute, CodeGen);
8674 [](CodeGenFunction &) { return nullptr; });
8675}
8676
8679 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8680 if (S.canBeParallelFor())
8682 else
8684 };
8686}
8687
8689 CodeGenModule &CGM, StringRef ParentName,
8691 // Emit SPMD target parallel loop region as a standalone region.
8692 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8693 if (S.canBeParallelFor())
8695 else
8697 };
8698 llvm::Function *Fn;
8699 llvm::Constant *Addr;
8700 // Emit target region as a standalone region.
8701 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8702 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
8703 assert(Fn && Addr &&
8704 "Target device function emission failed for 'target teams loop'.");
8705}
8706
8709 PrePostActionTy &Action) {
8710 Action.Enter(CGF);
8711 // Emit as 'parallel for'.
8712 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8713 Action.Enter(CGF);
8715 CGF, OMPD_target_parallel_loop, /*hasCancel=*/false);
8716 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
8718 };
8719 emitCommonOMPParallelDirective(CGF, S, OMPD_for, CodeGen,
8721}
8722
8724 CodeGenModule &CGM, StringRef ParentName,
8726 // Emit target parallel loop region as a standalone region.
8727 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8729 };
8730 llvm::Function *Fn;
8731 llvm::Constant *Addr;
8732 // Emit target region as a standalone region.
8733 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8734 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
8735 assert(Fn && Addr && "Target device function emission failed.");
8736}
8737
8738/// Emit combined directive 'target parallel loop' as if its constituent
8739/// constructs are 'target', 'parallel', and 'for'.
8742 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
8744 };
8746}
8747
8749 const OMPExecutableDirective &D) {
8750 if (const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8752 return;
8753 }
8754 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8755 return;
8756 auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) {
8757 OMPPrivateScope GlobalsScope(CGF);
8758 if (isOpenMPTaskingDirective(D.getDirectiveKind())) {
8759 // Capture global firstprivates to avoid crash.
8760 for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8761 for (const Expr *Ref : C->varlist()) {
8762 const auto *DRE = cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
8763 if (!DRE)
8764 continue;
8765 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8766 if (!VD || VD->hasLocalStorage())
8767 continue;
8768 if (!CGF.LocalDeclMap.count(VD)) {
8769 LValue GlobLVal = CGF.EmitLValue(Ref);
8770 GlobalsScope.addPrivate(VD, GlobLVal.getAddress());
8771 }
8772 }
8773 }
8774 }
8775 if (isOpenMPSimdDirective(D.getDirectiveKind())) {
8776 (void)GlobalsScope.Privatize();
8777 ParentLoopDirectiveForScanRegion ScanRegion(CGF, D);
8779 } else {
8780 if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8781 for (const Expr *E : LD->counters()) {
8782 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
8783 if (!VD->hasLocalStorage() && !CGF.LocalDeclMap.count(VD)) {
8784 LValue GlobLVal = CGF.EmitLValue(E);
8785 GlobalsScope.addPrivate(VD, GlobLVal.getAddress());
8786 }
8787 if (isa<OMPCapturedExprDecl>(VD)) {
8788 // Emit only those that were not explicitly referenced in clauses.
8789 if (!CGF.LocalDeclMap.count(VD))
8790 CGF.EmitVarDecl(*VD);
8791 }
8792 }
8793 for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) {
8794 if (!C->getNumForLoops())
8795 continue;
8796 for (unsigned I = LD->getLoopsNumber(),
8797 E = C->getLoopNumIterations().size();
8798 I < E; ++I) {
8799 if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8800 cast<DeclRefExpr>(C->getLoopCounter(I))->getDecl())) {
8801 // Emit only those that were not explicitly referenced in clauses.
8802 if (!CGF.LocalDeclMap.count(VD))
8803 CGF.EmitVarDecl(*VD);
8804 }
8805 }
8806 }
8807 }
8808 (void)GlobalsScope.Privatize();
8809 CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8810 }
8811 };
8812 if (D.getDirectiveKind() == OMPD_atomic ||
8813 D.getDirectiveKind() == OMPD_critical ||
8814 D.getDirectiveKind() == OMPD_section ||
8815 D.getDirectiveKind() == OMPD_master ||
8816 D.getDirectiveKind() == OMPD_masked ||
8817 D.getDirectiveKind() == OMPD_unroll ||
8818 D.getDirectiveKind() == OMPD_assume) {
8819 EmitStmt(D.getAssociatedStmt());
8820 } else {
8821 auto LPCRegion =
8823 OMPSimdLexicalScope Scope(*this, D);
8824 CGM.getOpenMPRuntime().emitInlinedDirective(
8825 *this,
8826 isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd
8827 : D.getDirectiveKind(),
8828 CodeGen);
8829 }
8830 // Check for outer lastprivate conditional update.
8832}
8833
8835 EmitStmt(S.getAssociatedStmt());
8836}
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:226
SourceManager & getSourceManager()
Definition ASTContext.h:859
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
IdentifierTable & Idents
Definition ASTContext.h:798
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3772
Represents an attribute applied to a statement.
Definition Stmt.h: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:4961
unsigned getNumParams() const
Definition Decl.h:4999
ImplicitParamDecl * getContextParam() const
Retrieve the parameter containing captured variables.
Definition Decl.h:5019
unsigned getContextParamPosition() const
Definition Decl.h:5028
bool isNothrow() const
Definition Decl.cpp:5703
static CapturedDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
Definition Decl.cpp:5688
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
Definition Decl.h:5036
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Definition Decl.h:5034
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition Decl.cpp:5700
ImplicitParamDecl * getParam(unsigned i) const
Definition Decl.h:5001
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:1348
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::Function * GenerateOpenMPCapturedStmtFunctionAggregate(const CapturedStmt &S, const OMPExecutableDirective &D)
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
const LangOptions & getLangOpts() const
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
Definition CGDecl.cpp:1482
void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO, const llvm::function_ref< RValue(RValue)> &UpdateOp, bool IsVolatile)
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
Definition CGExpr.cpp: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:2217
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
Definition CGExpr.cpp: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:203
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
Definition CGExpr.cpp: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:1822
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
Definition CGStmt.cpp: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:2107
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
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:3325
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:3175
Represents a function declaration or definition.
Definition Decl.h:2015
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
Definition Decl.h:2204
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2073
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Definition Decl.cpp:5604
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:2959
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3378
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
Definition TypeBase.h:937
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8616
Represents a struct/union/class.
Definition Decl.h:4342
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
Definition Decl.h:4558
field_range fields() const
Definition Decl.h:4545
field_iterator field_begin() const
Definition Decl.cpp:5277
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3623
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
Definition Stmt.h:86
child_range children()
Definition Stmt.cpp:304
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
Definition Stmt.cpp:210
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
bool isArrayType() const
Definition TypeBase.h:8767
bool isPointerType() const
Definition TypeBase.h:8668
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9328
bool isReferenceType() const
Definition TypeBase.h:8692
bool isLValueReferenceType() const
Definition TypeBase.h:8696
bool isAnyComplexType() const
Definition TypeBase.h:8803
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2275
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2850
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9314
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Definition Expr.cpp:5151
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
TLSKind getTLSKind() const
Definition Decl.cpp:2181
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:2270
@ CInit
C-style initialization with assignment.
Definition Decl.h:931
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1241
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1208
const Expr * getInit() const
Definition Decl.h:1383
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1184
@ TLS_None
Not a TLS variable.
Definition Decl.h:946
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4016
Expr * getSizeExpr() const
Definition TypeBase.h:4030
Definition SPIR.cpp:35
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:155
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:146
@ 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:926
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:1758
@ Other
Other implicit parameter.
Definition Decl.h:1761
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Definition OpenMPKinds.h:31
@ OMPC_SCHEDULE_unknown
Definition OpenMPKinds.h:35
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
#define true
Definition stdbool.h:25
Struct with the values to be passed to the static runtime function.
QualType getType() const
Definition CGCall.h:248
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
static Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
llvm::OpenMPIRBuilder::InsertPointTy InsertPointTy
static void EmitOMPOutlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region that will be outlined in OpenMPIRBuilder::finalize().
static Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable /p VD.
static void EmitCaptureStmt(CodeGenFunction &CGF, InsertPointTy CodeGenIP, llvm::BasicBlock &FiniBB, llvm::Function *Fn, ArrayRef< llvm::Value * > Args)
static std::string getNameWithSeparators(ArrayRef< StringRef > Parts, StringRef FirstSeparator=".", StringRef Separator=".")
Get the platform-specific name separator.
static void FinalizeOMPRegion(CodeGenFunction &CGF, InsertPointTy IP)
Emit the Finalization for an OMP region.
static void EmitOMPInlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region.
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:648
Extra information about a function prototype.
Definition TypeBase.h:5442
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule