Bug Summary

File:build/source/clang/lib/CodeGen/CGOpenMPRuntime.cpp
Warning:line 4337, column 56
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CGOpenMPRuntime.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm -resource-dir /usr/lib/llvm-17/lib/clang/17 -I tools/clang/lib/CodeGen -I /build/source/clang/lib/CodeGen -I /build/source/clang/include -I tools/clang/include -I include -I /build/source/llvm/include -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm=build-llvm -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm=build-llvm -fcoverage-prefix-map=/build/source/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm -fdebug-prefix-map=/build/source/build-llvm=build-llvm -fdebug-prefix-map=/build/source/= -fdebug-prefix-map=/build/source/build-llvm=build-llvm -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/clang/lib/CodeGen/CGOpenMPRuntime.cpp

/build/source/clang/lib/CodeGen/CGOpenMPRuntime.cpp

1//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
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 provides a class for OpenMP runtime code generation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CGOpenMPRuntime.h"
14#include "CGCXXABI.h"
15#include "CGCleanup.h"
16#include "CGRecordLayout.h"
17#include "CodeGenFunction.h"
18#include "TargetInfo.h"
19#include "clang/AST/APValue.h"
20#include "clang/AST/Attr.h"
21#include "clang/AST/Decl.h"
22#include "clang/AST/OpenMPClause.h"
23#include "clang/AST/StmtOpenMP.h"
24#include "clang/AST/StmtVisitor.h"
25#include "clang/Basic/BitmaskEnum.h"
26#include "clang/Basic/FileManager.h"
27#include "clang/Basic/OpenMPKinds.h"
28#include "clang/Basic/SourceManager.h"
29#include "clang/CodeGen/ConstantInitBuilder.h"
30#include "llvm/ADT/ArrayRef.h"
31#include "llvm/ADT/SetOperations.h"
32#include "llvm/ADT/SmallBitVector.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/Bitcode/BitcodeReader.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DerivedTypes.h"
37#include "llvm/IR/GlobalValue.h"
38#include "llvm/IR/InstrTypes.h"
39#include "llvm/IR/Value.h"
40#include "llvm/Support/AtomicOrdering.h"
41#include "llvm/Support/Format.h"
42#include "llvm/Support/raw_ostream.h"
43#include <cassert>
44#include <numeric>
45#include <optional>
46
47using namespace clang;
48using namespace CodeGen;
49using namespace llvm::omp;
50
51namespace {
52/// Base class for handling code generation inside OpenMP regions.
53class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
54public:
55 /// Kinds of OpenMP regions used in codegen.
56 enum CGOpenMPRegionKind {
57 /// Region with outlined function for standalone 'parallel'
58 /// directive.
59 ParallelOutlinedRegion,
60 /// Region with outlined function for standalone 'task' directive.
61 TaskOutlinedRegion,
62 /// Region for constructs that do not require function outlining,
63 /// like 'for', 'sections', 'atomic' etc. directives.
64 InlinedRegion,
65 /// Region with outlined function for standalone 'target' directive.
66 TargetRegion,
67 };
68
69 CGOpenMPRegionInfo(const CapturedStmt &CS,
70 const CGOpenMPRegionKind RegionKind,
71 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
72 bool HasCancel)
73 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
74 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
75
76 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
77 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
78 bool HasCancel)
79 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
80 Kind(Kind), HasCancel(HasCancel) {}
81
82 /// Get a variable or parameter for storing global thread id
83 /// inside OpenMP construct.
84 virtual const VarDecl *getThreadIDVariable() const = 0;
85
86 /// Emit the captured statement body.
87 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
88
89 /// Get an LValue for the current ThreadID variable.
90 /// \return LValue for thread id variable. This LValue always has type int32*.
91 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
92
93 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
94
95 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
96
97 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
98
99 bool hasCancel() const { return HasCancel; }
100
101 static bool classof(const CGCapturedStmtInfo *Info) {
102 return Info->getKind() == CR_OpenMP;
103 }
104
105 ~CGOpenMPRegionInfo() override = default;
106
107protected:
108 CGOpenMPRegionKind RegionKind;
109 RegionCodeGenTy CodeGen;
110 OpenMPDirectiveKind Kind;
111 bool HasCancel;
112};
113
114/// API for captured statement code generation in OpenMP constructs.
115class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
116public:
117 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
118 const RegionCodeGenTy &CodeGen,
119 OpenMPDirectiveKind Kind, bool HasCancel,
120 StringRef HelperName)
121 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
122 HasCancel),
123 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
124 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.")(static_cast <bool> (ThreadIDVar != nullptr && "No ThreadID in OpenMP region."
) ? void (0) : __assert_fail ("ThreadIDVar != nullptr && \"No ThreadID in OpenMP region.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 124, __extension__
__PRETTY_FUNCTION__))
;
125 }
126
127 /// Get a variable or parameter for storing global thread id
128 /// inside OpenMP construct.
129 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
130
131 /// Get the name of the capture helper.
132 StringRef getHelperName() const override { return HelperName; }
133
134 static bool classof(const CGCapturedStmtInfo *Info) {
135 return CGOpenMPRegionInfo::classof(Info) &&
136 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
137 ParallelOutlinedRegion;
138 }
139
140private:
141 /// A variable or parameter storing global thread id for OpenMP
142 /// constructs.
143 const VarDecl *ThreadIDVar;
144 StringRef HelperName;
145};
146
147/// API for captured statement code generation in OpenMP constructs.
148class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
149public:
150 class UntiedTaskActionTy final : public PrePostActionTy {
151 bool Untied;
152 const VarDecl *PartIDVar;
153 const RegionCodeGenTy UntiedCodeGen;
154 llvm::SwitchInst *UntiedSwitch = nullptr;
155
156 public:
157 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
158 const RegionCodeGenTy &UntiedCodeGen)
159 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
160 void Enter(CodeGenFunction &CGF) override {
161 if (Untied) {
162 // Emit task switching point.
163 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
164 CGF.GetAddrOfLocalVar(PartIDVar),
165 PartIDVar->getType()->castAs<PointerType>());
166 llvm::Value *Res =
167 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation());
168 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done.");
169 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
170 CGF.EmitBlock(DoneBB);
171 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
172 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
173 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
174 CGF.Builder.GetInsertBlock());
175 emitUntiedSwitch(CGF);
176 }
177 }
178 void emitUntiedSwitch(CodeGenFunction &CGF) const {
179 if (Untied) {
180 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
181 CGF.GetAddrOfLocalVar(PartIDVar),
182 PartIDVar->getType()->castAs<PointerType>());
183 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
184 PartIdLVal);
185 UntiedCodeGen(CGF);
186 CodeGenFunction::JumpDest CurPoint =
187 CGF.getJumpDestInCurrentScope(".untied.next.");
188 CGF.EmitBranch(CGF.ReturnBlock.getBlock());
189 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
190 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
191 CGF.Builder.GetInsertBlock());
192 CGF.EmitBranchThroughCleanup(CurPoint);
193 CGF.EmitBlock(CurPoint.getBlock());
194 }
195 }
196 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
197 };
198 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
199 const VarDecl *ThreadIDVar,
200 const RegionCodeGenTy &CodeGen,
201 OpenMPDirectiveKind Kind, bool HasCancel,
202 const UntiedTaskActionTy &Action)
203 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
204 ThreadIDVar(ThreadIDVar), Action(Action) {
205 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.")(static_cast <bool> (ThreadIDVar != nullptr && "No ThreadID in OpenMP region."
) ? void (0) : __assert_fail ("ThreadIDVar != nullptr && \"No ThreadID in OpenMP region.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 205, __extension__
__PRETTY_FUNCTION__))
;
206 }
207
208 /// Get a variable or parameter for storing global thread id
209 /// inside OpenMP construct.
210 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
211
212 /// Get an LValue for the current ThreadID variable.
213 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
214
215 /// Get the name of the capture helper.
216 StringRef getHelperName() const override { return ".omp_outlined."; }
217
218 void emitUntiedSwitch(CodeGenFunction &CGF) override {
219 Action.emitUntiedSwitch(CGF);
220 }
221
222 static bool classof(const CGCapturedStmtInfo *Info) {
223 return CGOpenMPRegionInfo::classof(Info) &&
224 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
225 TaskOutlinedRegion;
226 }
227
228private:
229 /// A variable or parameter storing global thread id for OpenMP
230 /// constructs.
231 const VarDecl *ThreadIDVar;
232 /// Action for emitting code for untied tasks.
233 const UntiedTaskActionTy &Action;
234};
235
236/// API for inlined captured statement code generation in OpenMP
237/// constructs.
238class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
239public:
240 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
241 const RegionCodeGenTy &CodeGen,
242 OpenMPDirectiveKind Kind, bool HasCancel)
243 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
244 OldCSI(OldCSI),
245 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
246
247 // Retrieve the value of the context parameter.
248 llvm::Value *getContextValue() const override {
249 if (OuterRegionInfo)
250 return OuterRegionInfo->getContextValue();
251 llvm_unreachable("No context value for inlined OpenMP region")::llvm::llvm_unreachable_internal("No context value for inlined OpenMP region"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 251)
;
252 }
253
254 void setContextValue(llvm::Value *V) override {
255 if (OuterRegionInfo) {
256 OuterRegionInfo->setContextValue(V);
257 return;
258 }
259 llvm_unreachable("No context value for inlined OpenMP region")::llvm::llvm_unreachable_internal("No context value for inlined OpenMP region"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 259)
;
260 }
261
262 /// Lookup the captured field decl for a variable.
263 const FieldDecl *lookup(const VarDecl *VD) const override {
264 if (OuterRegionInfo)
265 return OuterRegionInfo->lookup(VD);
266 // If there is no outer outlined region,no need to lookup in a list of
267 // captured variables, we can use the original one.
268 return nullptr;
269 }
270
271 FieldDecl *getThisFieldDecl() const override {
272 if (OuterRegionInfo)
273 return OuterRegionInfo->getThisFieldDecl();
274 return nullptr;
275 }
276
277 /// Get a variable or parameter for storing global thread id
278 /// inside OpenMP construct.
279 const VarDecl *getThreadIDVariable() const override {
280 if (OuterRegionInfo)
281 return OuterRegionInfo->getThreadIDVariable();
282 return nullptr;
283 }
284
285 /// Get an LValue for the current ThreadID variable.
286 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override {
287 if (OuterRegionInfo)
288 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
289 llvm_unreachable("No LValue for inlined OpenMP construct")::llvm::llvm_unreachable_internal("No LValue for inlined OpenMP construct"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 289)
;
290 }
291
292 /// Get the name of the capture helper.
293 StringRef getHelperName() const override {
294 if (auto *OuterRegionInfo = getOldCSI())
295 return OuterRegionInfo->getHelperName();
296 llvm_unreachable("No helper name for inlined OpenMP construct")::llvm::llvm_unreachable_internal("No helper name for inlined OpenMP construct"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 296)
;
297 }
298
299 void emitUntiedSwitch(CodeGenFunction &CGF) override {
300 if (OuterRegionInfo)
301 OuterRegionInfo->emitUntiedSwitch(CGF);
302 }
303
304 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
305
306 static bool classof(const CGCapturedStmtInfo *Info) {
307 return CGOpenMPRegionInfo::classof(Info) &&
308 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
309 }
310
311 ~CGOpenMPInlinedRegionInfo() override = default;
312
313private:
314 /// CodeGen info about outer OpenMP region.
315 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
316 CGOpenMPRegionInfo *OuterRegionInfo;
317};
318
319/// API for captured statement code generation in OpenMP target
320/// constructs. For this captures, implicit parameters are used instead of the
321/// captured fields. The name of the target region has to be unique in a given
322/// application so it is provided by the client, because only the client has
323/// the information to generate that.
324class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
325public:
326 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
327 const RegionCodeGenTy &CodeGen, StringRef HelperName)
328 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
329 /*HasCancel=*/false),
330 HelperName(HelperName) {}
331
332 /// This is unused for target regions because each starts executing
333 /// with a single thread.
334 const VarDecl *getThreadIDVariable() const override { return nullptr; }
335
336 /// Get the name of the capture helper.
337 StringRef getHelperName() const override { return HelperName; }
338
339 static bool classof(const CGCapturedStmtInfo *Info) {
340 return CGOpenMPRegionInfo::classof(Info) &&
341 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
342 }
343
344private:
345 StringRef HelperName;
346};
347
348static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
349 llvm_unreachable("No codegen for expressions")::llvm::llvm_unreachable_internal("No codegen for expressions"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 349)
;
350}
351/// API for generation of expressions captured in a innermost OpenMP
352/// region.
353class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
354public:
355 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
356 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
357 OMPD_unknown,
358 /*HasCancel=*/false),
359 PrivScope(CGF) {
360 // Make sure the globals captured in the provided statement are local by
361 // using the privatization logic. We assume the same variable is not
362 // captured more than once.
363 for (const auto &C : CS.captures()) {
364 if (!C.capturesVariable() && !C.capturesVariableByCopy())
365 continue;
366
367 const VarDecl *VD = C.getCapturedVar();
368 if (VD->isLocalVarDeclOrParm())
369 continue;
370
371 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
372 /*RefersToEnclosingVariableOrCapture=*/false,
373 VD->getType().getNonReferenceType(), VK_LValue,
374 C.getLocation());
375 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress(CGF));
376 }
377 (void)PrivScope.Privatize();
378 }
379
380 /// Lookup the captured field decl for a variable.
381 const FieldDecl *lookup(const VarDecl *VD) const override {
382 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
383 return FD;
384 return nullptr;
385 }
386
387 /// Emit the captured statement body.
388 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
389 llvm_unreachable("No body for expressions")::llvm::llvm_unreachable_internal("No body for expressions", "clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 389)
;
390 }
391
392 /// Get a variable or parameter for storing global thread id
393 /// inside OpenMP construct.
394 const VarDecl *getThreadIDVariable() const override {
395 llvm_unreachable("No thread id for expressions")::llvm::llvm_unreachable_internal("No thread id for expressions"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 395)
;
396 }
397
398 /// Get the name of the capture helper.
399 StringRef getHelperName() const override {
400 llvm_unreachable("No helper name for expressions")::llvm::llvm_unreachable_internal("No helper name for expressions"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 400)
;
401 }
402
403 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
404
405private:
406 /// Private scope to capture global variables.
407 CodeGenFunction::OMPPrivateScope PrivScope;
408};
409
410/// RAII for emitting code of OpenMP constructs.
411class InlinedOpenMPRegionRAII {
412 CodeGenFunction &CGF;
413 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
414 FieldDecl *LambdaThisCaptureField = nullptr;
415 const CodeGen::CGBlockInfo *BlockInfo = nullptr;
416 bool NoInheritance = false;
417
418public:
419 /// Constructs region for combined constructs.
420 /// \param CodeGen Code generation sequence for combined directives. Includes
421 /// a list of functions used for code generation of implicitly inlined
422 /// regions.
423 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
424 OpenMPDirectiveKind Kind, bool HasCancel,
425 bool NoInheritance = true)
426 : CGF(CGF), NoInheritance(NoInheritance) {
427 // Start emission for the construct.
428 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
429 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
430 if (NoInheritance) {
431 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
432 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
433 CGF.LambdaThisCaptureField = nullptr;
434 BlockInfo = CGF.BlockInfo;
435 CGF.BlockInfo = nullptr;
436 }
437 }
438
439 ~InlinedOpenMPRegionRAII() {
440 // Restore original CapturedStmtInfo only if we're done with code emission.
441 auto *OldCSI =
442 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
443 delete CGF.CapturedStmtInfo;
444 CGF.CapturedStmtInfo = OldCSI;
445 if (NoInheritance) {
446 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
447 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
448 CGF.BlockInfo = BlockInfo;
449 }
450 }
451};
452
453/// Values for bit flags used in the ident_t to describe the fields.
454/// All enumeric elements are named and described in accordance with the code
455/// from https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h
456enum OpenMPLocationFlags : unsigned {
457 /// Use trampoline for internal microtask.
458 OMP_IDENT_IMD = 0x01,
459 /// Use c-style ident structure.
460 OMP_IDENT_KMPC = 0x02,
461 /// Atomic reduction option for kmpc_reduce.
462 OMP_ATOMIC_REDUCE = 0x10,
463 /// Explicit 'barrier' directive.
464 OMP_IDENT_BARRIER_EXPL = 0x20,
465 /// Implicit barrier in code.
466 OMP_IDENT_BARRIER_IMPL = 0x40,
467 /// Implicit barrier in 'for' directive.
468 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
469 /// Implicit barrier in 'sections' directive.
470 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
471 /// Implicit barrier in 'single' directive.
472 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
473 /// Call of __kmp_for_static_init for static loop.
474 OMP_IDENT_WORK_LOOP = 0x200,
475 /// Call of __kmp_for_static_init for sections.
476 OMP_IDENT_WORK_SECTIONS = 0x400,
477 /// Call of __kmp_for_static_init for distribute.
478 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
479 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_IDENT_WORK_DISTRIBUTE
480};
481
482namespace {
483LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()using ::llvm::BitmaskEnumDetail::operator~; using ::llvm::BitmaskEnumDetail
::operator|; using ::llvm::BitmaskEnumDetail::operator&; using
::llvm::BitmaskEnumDetail::operator^; using ::llvm::BitmaskEnumDetail
::operator|=; using ::llvm::BitmaskEnumDetail::operator&=
; using ::llvm::BitmaskEnumDetail::operator^=
;
484/// Values for bit flags for marking which requires clauses have been used.
485enum OpenMPOffloadingRequiresDirFlags : int64_t {
486 /// flag undefined.
487 OMP_REQ_UNDEFINED = 0x000,
488 /// no requires clause present.
489 OMP_REQ_NONE = 0x001,
490 /// reverse_offload clause.
491 OMP_REQ_REVERSE_OFFLOAD = 0x002,
492 /// unified_address clause.
493 OMP_REQ_UNIFIED_ADDRESS = 0x004,
494 /// unified_shared_memory clause.
495 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
496 /// dynamic_allocators clause.
497 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
498 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_REQ_DYNAMIC_ALLOCATORS
499};
500
501} // anonymous namespace
502
503/// Describes ident structure that describes a source location.
504/// All descriptions are taken from
505/// https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h
506/// Original structure:
507/// typedef struct ident {
508/// kmp_int32 reserved_1; /**< might be used in Fortran;
509/// see above */
510/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
511/// KMP_IDENT_KMPC identifies this union
512/// member */
513/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
514/// see above */
515///#if USE_ITT_BUILD
516/// /* but currently used for storing
517/// region-specific ITT */
518/// /* contextual information. */
519///#endif /* USE_ITT_BUILD */
520/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
521/// C++ */
522/// char const *psource; /**< String describing the source location.
523/// The string is composed of semi-colon separated
524// fields which describe the source file,
525/// the function and a pair of line numbers that
526/// delimit the construct.
527/// */
528/// } ident_t;
529enum IdentFieldIndex {
530 /// might be used in Fortran
531 IdentField_Reserved_1,
532 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
533 IdentField_Flags,
534 /// Not really used in Fortran any more
535 IdentField_Reserved_2,
536 /// Source[4] in Fortran, do not use for C++
537 IdentField_Reserved_3,
538 /// String describing the source location. The string is composed of
539 /// semi-colon separated fields which describe the source file, the function
540 /// and a pair of line numbers that delimit the construct.
541 IdentField_PSource
542};
543
544/// Schedule types for 'omp for' loops (these enumerators are taken from
545/// the enum sched_type in kmp.h).
546enum OpenMPSchedType {
547 /// Lower bound for default (unordered) versions.
548 OMP_sch_lower = 32,
549 OMP_sch_static_chunked = 33,
550 OMP_sch_static = 34,
551 OMP_sch_dynamic_chunked = 35,
552 OMP_sch_guided_chunked = 36,
553 OMP_sch_runtime = 37,
554 OMP_sch_auto = 38,
555 /// static with chunk adjustment (e.g., simd)
556 OMP_sch_static_balanced_chunked = 45,
557 /// Lower bound for 'ordered' versions.
558 OMP_ord_lower = 64,
559 OMP_ord_static_chunked = 65,
560 OMP_ord_static = 66,
561 OMP_ord_dynamic_chunked = 67,
562 OMP_ord_guided_chunked = 68,
563 OMP_ord_runtime = 69,
564 OMP_ord_auto = 70,
565 OMP_sch_default = OMP_sch_static,
566 /// dist_schedule types
567 OMP_dist_sch_static_chunked = 91,
568 OMP_dist_sch_static = 92,
569 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
570 /// Set if the monotonic schedule modifier was present.
571 OMP_sch_modifier_monotonic = (1 << 29),
572 /// Set if the nonmonotonic schedule modifier was present.
573 OMP_sch_modifier_nonmonotonic = (1 << 30),
574};
575
576/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
577/// region.
578class CleanupTy final : public EHScopeStack::Cleanup {
579 PrePostActionTy *Action;
580
581public:
582 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
583 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
584 if (!CGF.HaveInsertPoint())
585 return;
586 Action->Exit(CGF);
587 }
588};
589
590} // anonymous namespace
591
592void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
593 CodeGenFunction::RunCleanupsScope Scope(CGF);
594 if (PrePostAction) {
595 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
596 Callback(CodeGen, CGF, *PrePostAction);
597 } else {
598 PrePostActionTy Action;
599 Callback(CodeGen, CGF, Action);
600 }
601}
602
603/// Check if the combiner is a call to UDR combiner and if it is so return the
604/// UDR decl used for reduction.
605static const OMPDeclareReductionDecl *
606getReductionInit(const Expr *ReductionOp) {
607 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
608 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
609 if (const auto *DRE =
610 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
611 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
612 return DRD;
613 return nullptr;
614}
615
616static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
617 const OMPDeclareReductionDecl *DRD,
618 const Expr *InitOp,
619 Address Private, Address Original,
620 QualType Ty) {
621 if (DRD->getInitializer()) {
622 std::pair<llvm::Function *, llvm::Function *> Reduction =
623 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
624 const auto *CE = cast<CallExpr>(InitOp);
625 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
626 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
627 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
628 const auto *LHSDRE =
629 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
630 const auto *RHSDRE =
631 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
632 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
633 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), Private);
634 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), Original);
635 (void)PrivateScope.Privatize();
636 RValue Func = RValue::get(Reduction.second);
637 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
638 CGF.EmitIgnoredExpr(InitOp);
639 } else {
640 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
641 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
642 auto *GV = new llvm::GlobalVariable(
643 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
644 llvm::GlobalValue::PrivateLinkage, Init, Name);
645 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
646 RValue InitRVal;
647 switch (CGF.getEvaluationKind(Ty)) {
648 case TEK_Scalar:
649 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
650 break;
651 case TEK_Complex:
652 InitRVal =
653 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
654 break;
655 case TEK_Aggregate: {
656 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_LValue);
657 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, LV);
658 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
659 /*IsInitializer=*/false);
660 return;
661 }
662 }
663 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_PRValue);
664 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
665 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
666 /*IsInitializer=*/false);
667 }
668}
669
670/// Emit initialization of arrays of complex types.
671/// \param DestAddr Address of the array.
672/// \param Type Type of array.
673/// \param Init Initial expression of array.
674/// \param SrcAddr Address of the original array.
675static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
676 QualType Type, bool EmitDeclareReductionInit,
677 const Expr *Init,
678 const OMPDeclareReductionDecl *DRD,
679 Address SrcAddr = Address::invalid()) {
680 // Perform element-by-element initialization.
681 QualType ElementTy;
682
683 // Drill down to the base element type on both arrays.
684 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
685 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
686 if (DRD)
687 SrcAddr =
688 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
689
690 llvm::Value *SrcBegin = nullptr;
691 if (DRD)
692 SrcBegin = SrcAddr.getPointer();
693 llvm::Value *DestBegin = DestAddr.getPointer();
694 // Cast from pointer to array type to pointer to single element.
695 llvm::Value *DestEnd =
696 CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements);
697 // The basic structure here is a while-do loop.
698 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
699 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
700 llvm::Value *IsEmpty =
701 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
702 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
703
704 // Enter the loop body, making that address the current address.
705 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
706 CGF.EmitBlock(BodyBB);
707
708 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
709
710 llvm::PHINode *SrcElementPHI = nullptr;
711 Address SrcElementCurrent = Address::invalid();
712 if (DRD) {
713 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
714 "omp.arraycpy.srcElementPast");
715 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
716 SrcElementCurrent =
717 Address(SrcElementPHI, SrcAddr.getElementType(),
718 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
719 }
720 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
721 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
722 DestElementPHI->addIncoming(DestBegin, EntryBB);
723 Address DestElementCurrent =
724 Address(DestElementPHI, DestAddr.getElementType(),
725 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
726
727 // Emit copy.
728 {
729 CodeGenFunction::RunCleanupsScope InitScope(CGF);
730 if (EmitDeclareReductionInit) {
731 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
732 SrcElementCurrent, ElementTy);
733 } else
734 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
735 /*IsInitializer=*/false);
736 }
737
738 if (DRD) {
739 // Shift the address forward by one element.
740 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
741 SrcAddr.getElementType(), SrcElementPHI, /*Idx0=*/1,
742 "omp.arraycpy.dest.element");
743 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
744 }
745
746 // Shift the address forward by one element.
747 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
748 DestAddr.getElementType(), DestElementPHI, /*Idx0=*/1,
749 "omp.arraycpy.dest.element");
750 // Check whether we've reached the end.
751 llvm::Value *Done =
752 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
753 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
754 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
755
756 // Done.
757 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
758}
759
760LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
761 return CGF.EmitOMPSharedLValue(E);
762}
763
764LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
765 const Expr *E) {
766 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
767 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
768 return LValue();
769}
770
771void ReductionCodeGen::emitAggregateInitialization(
772 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr,
773 const OMPDeclareReductionDecl *DRD) {
774 // Emit VarDecl with copy init for arrays.
775 // Get the address of the original variable captured in current
776 // captured region.
777 const auto *PrivateVD =
778 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
779 bool EmitDeclareReductionInit =
780 DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
781 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),
782 EmitDeclareReductionInit,
783 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
784 : PrivateVD->getInit(),
785 DRD, SharedAddr);
786}
787
788ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
789 ArrayRef<const Expr *> Origs,
790 ArrayRef<const Expr *> Privates,
791 ArrayRef<const Expr *> ReductionOps) {
792 ClausesData.reserve(Shareds.size());
793 SharedAddresses.reserve(Shareds.size());
794 Sizes.reserve(Shareds.size());
795 BaseDecls.reserve(Shareds.size());
796 const auto *IOrig = Origs.begin();
797 const auto *IPriv = Privates.begin();
798 const auto *IRed = ReductionOps.begin();
799 for (const Expr *Ref : Shareds) {
800 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
801 std::advance(IOrig, 1);
802 std::advance(IPriv, 1);
803 std::advance(IRed, 1);
804 }
805}
806
807void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) {
808 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&(static_cast <bool> (SharedAddresses.size() == N &&
OrigAddresses.size() == N && "Number of generated lvalues must be exactly N."
) ? void (0) : __assert_fail ("SharedAddresses.size() == N && OrigAddresses.size() == N && \"Number of generated lvalues must be exactly N.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 809, __extension__
__PRETTY_FUNCTION__))
809 "Number of generated lvalues must be exactly N.")(static_cast <bool> (SharedAddresses.size() == N &&
OrigAddresses.size() == N && "Number of generated lvalues must be exactly N."
) ? void (0) : __assert_fail ("SharedAddresses.size() == N && OrigAddresses.size() == N && \"Number of generated lvalues must be exactly N.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 809, __extension__
__PRETTY_FUNCTION__))
;
810 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
811 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
812 SharedAddresses.emplace_back(First, Second);
813 if (ClausesData[N].Shared == ClausesData[N].Ref) {
814 OrigAddresses.emplace_back(First, Second);
815 } else {
816 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
817 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
818 OrigAddresses.emplace_back(First, Second);
819 }
820}
821
822void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
823 QualType PrivateType = getPrivateType(N);
824 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
825 if (!PrivateType->isVariablyModifiedType()) {
826 Sizes.emplace_back(
827 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
828 nullptr);
829 return;
830 }
831 llvm::Value *Size;
832 llvm::Value *SizeInChars;
833 auto *ElemType = OrigAddresses[N].first.getAddress(CGF).getElementType();
834 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
835 if (AsArraySection) {
836 Size = CGF.Builder.CreatePtrDiff(ElemType,
837 OrigAddresses[N].second.getPointer(CGF),
838 OrigAddresses[N].first.getPointer(CGF));
839 Size = CGF.Builder.CreateNUWAdd(
840 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
841 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf);
842 } else {
843 SizeInChars =
844 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
845 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
846 }
847 Sizes.emplace_back(SizeInChars, Size);
848 CodeGenFunction::OpaqueValueMapping OpaqueMap(
849 CGF,
850 cast<OpaqueValueExpr>(
851 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
852 RValue::get(Size));
853 CGF.EmitVariablyModifiedType(PrivateType);
854}
855
856void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
857 llvm::Value *Size) {
858 QualType PrivateType = getPrivateType(N);
859 if (!PrivateType->isVariablyModifiedType()) {
860 assert(!Size && !Sizes[N].second &&(static_cast <bool> (!Size && !Sizes[N].second &&
"Size should be nullptr for non-variably modified reduction "
"items.") ? void (0) : __assert_fail ("!Size && !Sizes[N].second && \"Size should be nullptr for non-variably modified reduction \" \"items.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 862, __extension__
__PRETTY_FUNCTION__))
861 "Size should be nullptr for non-variably modified reduction "(static_cast <bool> (!Size && !Sizes[N].second &&
"Size should be nullptr for non-variably modified reduction "
"items.") ? void (0) : __assert_fail ("!Size && !Sizes[N].second && \"Size should be nullptr for non-variably modified reduction \" \"items.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 862, __extension__
__PRETTY_FUNCTION__))
862 "items.")(static_cast <bool> (!Size && !Sizes[N].second &&
"Size should be nullptr for non-variably modified reduction "
"items.") ? void (0) : __assert_fail ("!Size && !Sizes[N].second && \"Size should be nullptr for non-variably modified reduction \" \"items.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 862, __extension__
__PRETTY_FUNCTION__))
;
863 return;
864 }
865 CodeGenFunction::OpaqueValueMapping OpaqueMap(
866 CGF,
867 cast<OpaqueValueExpr>(
868 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
869 RValue::get(Size));
870 CGF.EmitVariablyModifiedType(PrivateType);
871}
872
873void ReductionCodeGen::emitInitialization(
874 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr,
875 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
876 assert(SharedAddresses.size() > N && "No variable was generated")(static_cast <bool> (SharedAddresses.size() > N &&
"No variable was generated") ? void (0) : __assert_fail ("SharedAddresses.size() > N && \"No variable was generated\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 876, __extension__
__PRETTY_FUNCTION__))
;
877 const auto *PrivateVD =
878 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
879 const OMPDeclareReductionDecl *DRD =
880 getReductionInit(ClausesData[N].ReductionOp);
881 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
882 if (DRD && DRD->getInitializer())
883 (void)DefaultInit(CGF);
884 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
885 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
886 (void)DefaultInit(CGF);
887 QualType SharedType = SharedAddresses[N].first.getType();
888 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
889 PrivateAddr, SharedAddr, SharedType);
890 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
891 !CGF.isTrivialInitializer(PrivateVD->getInit())) {
892 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,
893 PrivateVD->getType().getQualifiers(),
894 /*IsInitializer=*/false);
895 }
896}
897
898bool ReductionCodeGen::needCleanups(unsigned N) {
899 QualType PrivateType = getPrivateType(N);
900 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
901 return DTorKind != QualType::DK_none;
902}
903
904void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
905 Address PrivateAddr) {
906 QualType PrivateType = getPrivateType(N);
907 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
908 if (needCleanups(N)) {
909 PrivateAddr = CGF.Builder.CreateElementBitCast(
910 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
911 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);
912 }
913}
914
915static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
916 LValue BaseLV) {
917 BaseTy = BaseTy.getNonReferenceType();
918 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
919 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
920 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
921 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy);
922 } else {
923 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy);
924 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
925 }
926 BaseTy = BaseTy->getPointeeType();
927 }
928 return CGF.MakeAddrLValue(
929 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF),
930 CGF.ConvertTypeForMem(ElTy)),
931 BaseLV.getType(), BaseLV.getBaseInfo(),
932 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
933}
934
935static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
936 Address OriginalBaseAddress, llvm::Value *Addr) {
937 Address Tmp = Address::invalid();
938 Address TopTmp = Address::invalid();
939 Address MostTopTmp = Address::invalid();
940 BaseTy = BaseTy.getNonReferenceType();
941 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
942 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
943 Tmp = CGF.CreateMemTemp(BaseTy);
944 if (TopTmp.isValid())
945 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
946 else
947 MostTopTmp = Tmp;
948 TopTmp = Tmp;
949 BaseTy = BaseTy->getPointeeType();
950 }
951
952 if (Tmp.isValid()) {
953 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
954 Addr, Tmp.getElementType());
955 CGF.Builder.CreateStore(Addr, Tmp);
956 return MostTopTmp;
957 }
958
959 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
960 Addr, OriginalBaseAddress.getType());
961 return OriginalBaseAddress.withPointer(Addr, NotKnownNonNull);
962}
963
964static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
965 const VarDecl *OrigVD = nullptr;
966 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
967 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
968 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
969 Base = TempOASE->getBase()->IgnoreParenImpCasts();
970 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
971 Base = TempASE->getBase()->IgnoreParenImpCasts();
972 DE = cast<DeclRefExpr>(Base);
973 OrigVD = cast<VarDecl>(DE->getDecl());
974 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
975 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
976 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
977 Base = TempASE->getBase()->IgnoreParenImpCasts();
978 DE = cast<DeclRefExpr>(Base);
979 OrigVD = cast<VarDecl>(DE->getDecl());
980 }
981 return OrigVD;
982}
983
984Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
985 Address PrivateAddr) {
986 const DeclRefExpr *DE;
987 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
988 BaseDecls.emplace_back(OrigVD);
989 LValue OriginalBaseLValue = CGF.EmitLValue(DE);
990 LValue BaseLValue =
991 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
992 OriginalBaseLValue);
993 Address SharedAddr = SharedAddresses[N].first.getAddress(CGF);
994 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
995 SharedAddr.getElementType(), BaseLValue.getPointer(CGF),
996 SharedAddr.getPointer());
997 llvm::Value *PrivatePointer =
998 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
999 PrivateAddr.getPointer(), SharedAddr.getType());
1000 llvm::Value *Ptr = CGF.Builder.CreateGEP(
1001 SharedAddr.getElementType(), PrivatePointer, Adjustment);
1002 return castToBase(CGF, OrigVD->getType(),
1003 SharedAddresses[N].first.getType(),
1004 OriginalBaseLValue.getAddress(CGF), Ptr);
1005 }
1006 BaseDecls.emplace_back(
1007 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
1008 return PrivateAddr;
1009}
1010
1011bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
1012 const OMPDeclareReductionDecl *DRD =
1013 getReductionInit(ClausesData[N].ReductionOp);
1014 return DRD && DRD->getInitializer();
1015}
1016
1017LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
1018 return CGF.EmitLoadOfPointerLValue(
1019 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1020 getThreadIDVariable()->getType()->castAs<PointerType>());
1021}
1022
1023void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt *S) {
1024 if (!CGF.HaveInsertPoint())
1025 return;
1026 // 1.2.2 OpenMP Language Terminology
1027 // Structured block - An executable statement with a single entry at the
1028 // top and a single exit at the bottom.
1029 // The point of exit cannot be a branch out of the structured block.
1030 // longjmp() and throw() must not violate the entry/exit criteria.
1031 CGF.EHStack.pushTerminate();
1032 if (S)
1033 CGF.incrementProfileCounter(S);
1034 CodeGen(CGF);
1035 CGF.EHStack.popTerminate();
1036}
1037
1038LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1039 CodeGenFunction &CGF) {
1040 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1041 getThreadIDVariable()->getType(),
1042 AlignmentSource::Decl);
1043}
1044
1045static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1046 QualType FieldTy) {
1047 auto *Field = FieldDecl::Create(
1048 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1049 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1050 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1051 Field->setAccess(AS_public);
1052 DC->addDecl(Field);
1053 return Field;
1054}
1055
1056CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
1057 : CGM(CGM), OMPBuilder(CGM.getModule()) {
1058 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
1059 llvm::OpenMPIRBuilderConfig Config(CGM.getLangOpts().OpenMPIsDevice, false,
1060 hasRequiresUnifiedSharedMemory(),
1061 CGM.getLangOpts().OpenMPOffloadMandatory);
1062 // Initialize Types used in OpenMPIRBuilder from OMPKinds.def
1063 OMPBuilder.initialize();
1064 OMPBuilder.setConfig(Config);
1065 loadOffloadInfoMetadata();
1066}
1067
1068void CGOpenMPRuntime::clear() {
1069 InternalVars.clear();
1070 // Clean non-target variable declarations possibly used only in debug info.
1071 for (const auto &Data : EmittedNonTargetVariables) {
1072 if (!Data.getValue().pointsToAliveValue())
1073 continue;
1074 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1075 if (!GV)
1076 continue;
1077 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1078 continue;
1079 GV->eraseFromParent();
1080 }
1081}
1082
1083std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1084 return OMPBuilder.createPlatformSpecificName(Parts);
1085}
1086
1087static llvm::Function *
1088emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1089 const Expr *CombinerInitializer, const VarDecl *In,
1090 const VarDecl *Out, bool IsCombiner) {
1091 // void .omp_combiner.(Ty *in, Ty *out);
1092 ASTContext &C = CGM.getContext();
1093 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1094 FunctionArgList Args;
1095 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
1096 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
1097 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
1098 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
1099 Args.push_back(&OmpOutParm);
1100 Args.push_back(&OmpInParm);
1101 const CGFunctionInfo &FnInfo =
1102 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
1103 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
1104 std::string Name = CGM.getOpenMPRuntime().getName(
1105 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1106 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1107 Name, &CGM.getModule());
1108 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
1109 if (CGM.getLangOpts().Optimize) {
1110 Fn->removeFnAttr(llvm::Attribute::NoInline);
1111 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1112 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1113 }
1114 CodeGenFunction CGF(CGM);
1115 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1116 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
1117 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1118 Out->getLocation());
1119 CodeGenFunction::OMPPrivateScope Scope(CGF);
1120 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
1121 Scope.addPrivate(
1122 In, CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
1123 .getAddress(CGF));
1124 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
1125 Scope.addPrivate(
1126 Out, CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
1127 .getAddress(CGF));
1128 (void)Scope.Privatize();
1129 if (!IsCombiner && Out->hasInit() &&
1130 !CGF.isTrivialInitializer(Out->getInit())) {
1131 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1132 Out->getType().getQualifiers(),
1133 /*IsInitializer=*/true);
1134 }
1135 if (CombinerInitializer)
1136 CGF.EmitIgnoredExpr(CombinerInitializer);
1137 Scope.ForceCleanup();
1138 CGF.FinishFunction();
1139 return Fn;
1140}
1141
1142void CGOpenMPRuntime::emitUserDefinedReduction(
1143 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1144 if (UDRMap.count(D) > 0)
1145 return;
1146 llvm::Function *Combiner = emitCombinerOrInitializer(
1147 CGM, D->getType(), D->getCombiner(),
1148 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1149 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
1150 /*IsCombiner=*/true);
1151 llvm::Function *Initializer = nullptr;
1152 if (const Expr *Init = D->getInitializer()) {
1153 Initializer = emitCombinerOrInitializer(
1154 CGM, D->getType(),
1155 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1156 : nullptr,
1157 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1158 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
1159 /*IsCombiner=*/false);
1160 }
1161 UDRMap.try_emplace(D, Combiner, Initializer);
1162 if (CGF) {
1163 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1164 Decls.second.push_back(D);
1165 }
1166}
1167
1168std::pair<llvm::Function *, llvm::Function *>
1169CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1170 auto I = UDRMap.find(D);
1171 if (I != UDRMap.end())
1172 return I->second;
1173 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1174 return UDRMap.lookup(D);
1175}
1176
1177namespace {
1178// Temporary RAII solution to perform a push/pop stack event on the OpenMP IR
1179// Builder if one is present.
1180struct PushAndPopStackRAII {
1181 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF,
1182 bool HasCancel, llvm::omp::Directive Kind)
1183 : OMPBuilder(OMPBuilder) {
1184 if (!OMPBuilder)
1185 return;
1186
1187 // The following callback is the crucial part of clangs cleanup process.
1188 //
1189 // NOTE:
1190 // Once the OpenMPIRBuilder is used to create parallel regions (and
1191 // similar), the cancellation destination (Dest below) is determined via
1192 // IP. That means if we have variables to finalize we split the block at IP,
1193 // use the new block (=BB) as destination to build a JumpDest (via
1194 // getJumpDestInCurrentScope(BB)) which then is fed to
1195 // EmitBranchThroughCleanup. Furthermore, there will not be the need
1196 // to push & pop an FinalizationInfo object.
1197 // The FiniCB will still be needed but at the point where the
1198 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct.
1199 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1200 assert(IP.getBlock()->end() == IP.getPoint() &&(static_cast <bool> (IP.getBlock()->end() == IP.getPoint
() && "Clang CG should cause non-terminated block!") ?
void (0) : __assert_fail ("IP.getBlock()->end() == IP.getPoint() && \"Clang CG should cause non-terminated block!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1201, __extension__
__PRETTY_FUNCTION__))
1201 "Clang CG should cause non-terminated block!")(static_cast <bool> (IP.getBlock()->end() == IP.getPoint
() && "Clang CG should cause non-terminated block!") ?
void (0) : __assert_fail ("IP.getBlock()->end() == IP.getPoint() && \"Clang CG should cause non-terminated block!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1201, __extension__
__PRETTY_FUNCTION__))
;
1202 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1203 CGF.Builder.restoreIP(IP);
1204 CodeGenFunction::JumpDest Dest =
1205 CGF.getOMPCancelDestination(OMPD_parallel);
1206 CGF.EmitBranchThroughCleanup(Dest);
1207 };
1208
1209 // TODO: Remove this once we emit parallel regions through the
1210 // OpenMPIRBuilder as it can do this setup internally.
1211 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1212 OMPBuilder->pushFinalizationCB(std::move(FI));
1213 }
1214 ~PushAndPopStackRAII() {
1215 if (OMPBuilder)
1216 OMPBuilder->popFinalizationCB();
1217 }
1218 llvm::OpenMPIRBuilder *OMPBuilder;
1219};
1220} // namespace
1221
1222static llvm::Function *emitParallelOrTeamsOutlinedFunction(
1223 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1224 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1225 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
1226 assert(ThreadIDVar->getType()->isPointerType() &&(static_cast <bool> (ThreadIDVar->getType()->isPointerType
() && "thread id variable must be of type kmp_int32 *"
) ? void (0) : __assert_fail ("ThreadIDVar->getType()->isPointerType() && \"thread id variable must be of type kmp_int32 *\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1227, __extension__
__PRETTY_FUNCTION__))
1227 "thread id variable must be of type kmp_int32 *")(static_cast <bool> (ThreadIDVar->getType()->isPointerType
() && "thread id variable must be of type kmp_int32 *"
) ? void (0) : __assert_fail ("ThreadIDVar->getType()->isPointerType() && \"thread id variable must be of type kmp_int32 *\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1227, __extension__
__PRETTY_FUNCTION__))
;
1228 CodeGenFunction CGF(CGM, true);
1229 bool HasCancel = false;
1230 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1231 HasCancel = OPD->hasCancel();
1232 else if (const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1233 HasCancel = OPD->hasCancel();
1234 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1235 HasCancel = OPSD->hasCancel();
1236 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1237 HasCancel = OPFD->hasCancel();
1238 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1239 HasCancel = OPFD->hasCancel();
1240 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1241 HasCancel = OPFD->hasCancel();
1242 else if (const auto *OPFD =
1243 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1244 HasCancel = OPFD->hasCancel();
1245 else if (const auto *OPFD =
1246 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1247 HasCancel = OPFD->hasCancel();
1248
1249 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new
1250 // parallel region to make cancellation barriers work properly.
1251 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
1252 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1253 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
1254 HasCancel, OutlinedHelperName);
1255 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
1256 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc());
1257}
1258
1259std::string CGOpenMPRuntime::getOutlinedHelperName(StringRef Name) const {
1260 std::string Suffix = getName({"omp_outlined"});
1261 return (Name + Suffix).str();
1262}
1263
1264std::string CGOpenMPRuntime::getOutlinedHelperName(CodeGenFunction &CGF) const {
1265 return getOutlinedHelperName(CGF.CurFn->getName());
1266}
1267
1268std::string CGOpenMPRuntime::getReductionFuncName(StringRef Name) const {
1269 std::string Suffix = getName({"omp", "reduction", "reduction_func"});
1270 return (Name + Suffix).str();
1271}
1272
1273llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
1274 CodeGenFunction &CGF, const OMPExecutableDirective &D,
1275 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1276 const RegionCodeGenTy &CodeGen) {
1277 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1278 return emitParallelOrTeamsOutlinedFunction(
1279 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(CGF),
1280 CodeGen);
1281}
1282
1283llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
1284 CodeGenFunction &CGF, const OMPExecutableDirective &D,
1285 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1286 const RegionCodeGenTy &CodeGen) {
1287 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1288 return emitParallelOrTeamsOutlinedFunction(
1289 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(CGF),
1290 CodeGen);
1291}
1292
1293llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
1294 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1295 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1296 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1297 bool Tied, unsigned &NumberOfParts) {
1298 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1299 PrePostActionTy &) {
1300 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1301 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
1302 llvm::Value *TaskArgs[] = {
1303 UpLoc, ThreadID,
1304 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1305 TaskTVar->getType()->castAs<PointerType>())
1306 .getPointer(CGF)};
1307 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
1308 CGM.getModule(), OMPRTL___kmpc_omp_task),
1309 TaskArgs);
1310 };
1311 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1312 UntiedCodeGen);
1313 CodeGen.setAction(Action);
1314 assert(!ThreadIDVar->getType()->isPointerType() &&(static_cast <bool> (!ThreadIDVar->getType()->isPointerType
() && "thread id variable must be of type kmp_int32 for tasks"
) ? void (0) : __assert_fail ("!ThreadIDVar->getType()->isPointerType() && \"thread id variable must be of type kmp_int32 for tasks\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1315, __extension__
__PRETTY_FUNCTION__))
1315 "thread id variable must be of type kmp_int32 for tasks")(static_cast <bool> (!ThreadIDVar->getType()->isPointerType
() && "thread id variable must be of type kmp_int32 for tasks"
) ? void (0) : __assert_fail ("!ThreadIDVar->getType()->isPointerType() && \"thread id variable must be of type kmp_int32 for tasks\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1315, __extension__
__PRETTY_FUNCTION__))
;
1316 const OpenMPDirectiveKind Region =
1317 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1318 : OMPD_task;
1319 const CapturedStmt *CS = D.getCapturedStmt(Region);
1320 bool HasCancel = false;
1321 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1322 HasCancel = TD->hasCancel();
1323 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1324 HasCancel = TD->hasCancel();
1325 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1326 HasCancel = TD->hasCancel();
1327 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1328 HasCancel = TD->hasCancel();
1329
1330 CodeGenFunction CGF(CGM, true);
1331 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1332 InnermostKind, HasCancel, Action);
1333 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
1334 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1335 if (!Tied)
1336 NumberOfParts = Action.getNumberOfParts();
1337 return Res;
1338}
1339
1340void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1341 bool AtCurrentPoint) {
1342 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1343 assert(!Elem.second.ServiceInsertPt && "Insert point is set already.")(static_cast <bool> (!Elem.second.ServiceInsertPt &&
"Insert point is set already.") ? void (0) : __assert_fail (
"!Elem.second.ServiceInsertPt && \"Insert point is set already.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1343, __extension__
__PRETTY_FUNCTION__))
;
1344
1345 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1346 if (AtCurrentPoint) {
1347 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1348 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1349 } else {
1350 Elem.second.ServiceInsertPt =
1351 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1352 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1353 }
1354}
1355
1356void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1357 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1358 if (Elem.second.ServiceInsertPt) {
1359 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1360 Elem.second.ServiceInsertPt = nullptr;
1361 Ptr->eraseFromParent();
1362 }
1363}
1364
1365static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF,
1366 SourceLocation Loc,
1367 SmallString<128> &Buffer) {
1368 llvm::raw_svector_ostream OS(Buffer);
1369 // Build debug location
1370 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1371 OS << ";" << PLoc.getFilename() << ";";
1372 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
1373 OS << FD->getQualifiedNameAsString();
1374 OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1375 return OS.str();
1376}
1377
1378llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1379 SourceLocation Loc,
1380 unsigned Flags, bool EmitLoc) {
1381 uint32_t SrcLocStrSize;
1382 llvm::Constant *SrcLocStr;
1383 if ((!EmitLoc && CGM.getCodeGenOpts().getDebugInfo() ==
1384 llvm::codegenoptions::NoDebugInfo) ||
1385 Loc.isInvalid()) {
1386 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1387 } else {
1388 std::string FunctionName;
1389 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
1390 FunctionName = FD->getQualifiedNameAsString();
1391 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1392 const char *FileName = PLoc.getFilename();
1393 unsigned Line = PLoc.getLine();
1394 unsigned Column = PLoc.getColumn();
1395 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FunctionName, FileName, Line,
1396 Column, SrcLocStrSize);
1397 }
1398 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1399 return OMPBuilder.getOrCreateIdent(
1400 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1401}
1402
1403llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1404 SourceLocation Loc) {
1405 assert(CGF.CurFn && "No function in current CodeGenFunction.")(static_cast <bool> (CGF.CurFn && "No function in current CodeGenFunction."
) ? void (0) : __assert_fail ("CGF.CurFn && \"No function in current CodeGenFunction.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1405, __extension__
__PRETTY_FUNCTION__))
;
1406 // If the OpenMPIRBuilder is used we need to use it for all thread id calls as
1407 // the clang invariants used below might be broken.
1408 if (CGM.getLangOpts().OpenMPIRBuilder) {
1409 SmallString<128> Buffer;
1410 OMPBuilder.updateToLocation(CGF.Builder.saveIP());
1411 uint32_t SrcLocStrSize;
1412 auto *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(
1413 getIdentStringFromSourceLocation(CGF, Loc, Buffer), SrcLocStrSize);
1414 return OMPBuilder.getOrCreateThreadID(
1415 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1416 }
1417
1418 llvm::Value *ThreadID = nullptr;
1419 // Check whether we've already cached a load of the thread id in this
1420 // function.
1421 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1422 if (I != OpenMPLocThreadIDMap.end()) {
1423 ThreadID = I->second.ThreadID;
1424 if (ThreadID != nullptr)
1425 return ThreadID;
1426 }
1427 // If exceptions are enabled, do not use parameter to avoid possible crash.
1428 if (auto *OMPRegionInfo =
1429 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1430 if (OMPRegionInfo->getThreadIDVariable()) {
1431 // Check if this an outlined function with thread id passed as argument.
1432 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1433 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent();
1434 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1435 !CGF.getLangOpts().CXXExceptions ||
1436 CGF.Builder.GetInsertBlock() == TopBlock ||
1437 !isa<llvm::Instruction>(LVal.getPointer(CGF)) ||
1438 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1439 TopBlock ||
1440 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1441 CGF.Builder.GetInsertBlock()) {
1442 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
1443 // If value loaded in entry block, cache it and use it everywhere in
1444 // function.
1445 if (CGF.Builder.GetInsertBlock() == TopBlock) {
1446 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1447 Elem.second.ThreadID = ThreadID;
1448 }
1449 return ThreadID;
1450 }
1451 }
1452 }
1453
1454 // This is not an outlined function region - need to call __kmpc_int32
1455 // kmpc_global_thread_num(ident_t *loc).
1456 // Generate thread id value and cache this value for use across the
1457 // function.
1458 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1459 if (!Elem.second.ServiceInsertPt)
1460 setLocThreadIdInsertPt(CGF);
1461 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1462 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
1463 llvm::CallInst *Call = CGF.Builder.CreateCall(
1464 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
1465 OMPRTL___kmpc_global_thread_num),
1466 emitUpdateLocation(CGF, Loc));
1467 Call->setCallingConv(CGF.getRuntimeCC());
1468 Elem.second.ThreadID = Call;
1469 return Call;
1470}
1471
1472void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
1473 assert(CGF.CurFn && "No function in current CodeGenFunction.")(static_cast <bool> (CGF.CurFn && "No function in current CodeGenFunction."
) ? void (0) : __assert_fail ("CGF.CurFn && \"No function in current CodeGenFunction.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1473, __extension__
__PRETTY_FUNCTION__))
;
1474 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1475 clearLocThreadIdInsertPt(CGF);
1476 OpenMPLocThreadIDMap.erase(CGF.CurFn);
1477 }
1478 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
1479 for(const auto *D : FunctionUDRMap[CGF.CurFn])
1480 UDRMap.erase(D);
1481 FunctionUDRMap.erase(CGF.CurFn);
1482 }
1483 auto I = FunctionUDMMap.find(CGF.CurFn);
1484 if (I != FunctionUDMMap.end()) {
1485 for(const auto *D : I->second)
1486 UDMMap.erase(D);
1487 FunctionUDMMap.erase(I);
1488 }
1489 LastprivateConditionalToTypes.erase(CGF.CurFn);
1490 FunctionToUntiedTaskStackMap.erase(CGF.CurFn);
1491}
1492
1493llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
1494 return OMPBuilder.IdentPtr;
1495}
1496
1497llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
1498 if (!Kmpc_MicroTy) {
1499 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1500 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1501 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1502 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1503 }
1504 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1505}
1506
1507llvm::FunctionCallee
1508CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned,
1509 bool IsGPUDistribute) {
1510 assert((IVSize == 32 || IVSize == 64) &&(static_cast <bool> ((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime") ? void (0)
: __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1511, __extension__
__PRETTY_FUNCTION__))
1511 "IV size is not compatible with the omp runtime")(static_cast <bool> ((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime") ? void (0)
: __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1511, __extension__
__PRETTY_FUNCTION__))
;
1512 StringRef Name;
1513 if (IsGPUDistribute)
1514 Name = IVSize == 32 ? (IVSigned ? "__kmpc_distribute_static_init_4"
1515 : "__kmpc_distribute_static_init_4u")
1516 : (IVSigned ? "__kmpc_distribute_static_init_8"
1517 : "__kmpc_distribute_static_init_8u");
1518 else
1519 Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
1520 : "__kmpc_for_static_init_4u")
1521 : (IVSigned ? "__kmpc_for_static_init_8"
1522 : "__kmpc_for_static_init_8u");
1523
1524 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1525 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
1526 llvm::Type *TypeParams[] = {
1527 getIdentTyPointerTy(), // loc
1528 CGM.Int32Ty, // tid
1529 CGM.Int32Ty, // schedtype
1530 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1531 PtrTy, // p_lower
1532 PtrTy, // p_upper
1533 PtrTy, // p_stride
1534 ITy, // incr
1535 ITy // chunk
1536 };
1537 auto *FnTy =
1538 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1539 return CGM.CreateRuntimeFunction(FnTy, Name);
1540}
1541
1542llvm::FunctionCallee
1543CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
1544 assert((IVSize == 32 || IVSize == 64) &&(static_cast <bool> ((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime") ? void (0)
: __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1545, __extension__
__PRETTY_FUNCTION__))
1545 "IV size is not compatible with the omp runtime")(static_cast <bool> ((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime") ? void (0)
: __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1545, __extension__
__PRETTY_FUNCTION__))
;
1546 StringRef Name =
1547 IVSize == 32
1548 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
1549 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
1550 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1551 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
1552 CGM.Int32Ty, // tid
1553 CGM.Int32Ty, // schedtype
1554 ITy, // lower
1555 ITy, // upper
1556 ITy, // stride
1557 ITy // chunk
1558 };
1559 auto *FnTy =
1560 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1561 return CGM.CreateRuntimeFunction(FnTy, Name);
1562}
1563
1564llvm::FunctionCallee
1565CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
1566 assert((IVSize == 32 || IVSize == 64) &&(static_cast <bool> ((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime") ? void (0)
: __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1567, __extension__
__PRETTY_FUNCTION__))
1567 "IV size is not compatible with the omp runtime")(static_cast <bool> ((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime") ? void (0)
: __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1567, __extension__
__PRETTY_FUNCTION__))
;
1568 StringRef Name =
1569 IVSize == 32
1570 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1571 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1572 llvm::Type *TypeParams[] = {
1573 getIdentTyPointerTy(), // loc
1574 CGM.Int32Ty, // tid
1575 };
1576 auto *FnTy =
1577 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1578 return CGM.CreateRuntimeFunction(FnTy, Name);
1579}
1580
1581llvm::FunctionCallee
1582CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
1583 assert((IVSize == 32 || IVSize == 64) &&(static_cast <bool> ((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime") ? void (0)
: __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1584, __extension__
__PRETTY_FUNCTION__))
1584 "IV size is not compatible with the omp runtime")(static_cast <bool> ((IVSize == 32 || IVSize == 64) &&
"IV size is not compatible with the omp runtime") ? void (0)
: __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1584, __extension__
__PRETTY_FUNCTION__))
;
1585 StringRef Name =
1586 IVSize == 32
1587 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1588 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1589 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1590 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
1591 llvm::Type *TypeParams[] = {
1592 getIdentTyPointerTy(), // loc
1593 CGM.Int32Ty, // tid
1594 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1595 PtrTy, // p_lower
1596 PtrTy, // p_upper
1597 PtrTy // p_stride
1598 };
1599 auto *FnTy =
1600 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1601 return CGM.CreateRuntimeFunction(FnTy, Name);
1602}
1603
1604/// Obtain information that uniquely identifies a target entry. This
1605/// consists of the file and device IDs as well as line number associated with
1606/// the relevant entry source location.
1607static llvm::TargetRegionEntryInfo
1608getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
1609 StringRef ParentName = "") {
1610 SourceManager &SM = C.getSourceManager();
1611
1612 // The loc should be always valid and have a file ID (the user cannot use
1613 // #pragma directives in macros)
1614
1615 assert(Loc.isValid() && "Source location is expected to be always valid.")(static_cast <bool> (Loc.isValid() && "Source location is expected to be always valid."
) ? void (0) : __assert_fail ("Loc.isValid() && \"Source location is expected to be always valid.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1615, __extension__
__PRETTY_FUNCTION__))
;
1616
1617 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
1618 assert(PLoc.isValid() && "Source location is expected to be always valid.")(static_cast <bool> (PLoc.isValid() && "Source location is expected to be always valid."
) ? void (0) : __assert_fail ("PLoc.isValid() && \"Source location is expected to be always valid.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1618, __extension__
__PRETTY_FUNCTION__))
;
1619
1620 llvm::sys::fs::UniqueID ID;
1621 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) {
1622 PLoc = SM.getPresumedLoc(Loc, /*UseLineDirectives=*/false);
1623 assert(PLoc.isValid() && "Source location is expected to be always valid.")(static_cast <bool> (PLoc.isValid() && "Source location is expected to be always valid."
) ? void (0) : __assert_fail ("PLoc.isValid() && \"Source location is expected to be always valid.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1623, __extension__
__PRETTY_FUNCTION__))
;
1624 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
1625 SM.getDiagnostics().Report(diag::err_cannot_open_file)
1626 << PLoc.getFilename() << EC.message();
1627 }
1628
1629 return llvm::TargetRegionEntryInfo(ParentName, ID.getDevice(), ID.getFile(),
1630 PLoc.getLine());
1631}
1632
1633Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
1634 if (CGM.getLangOpts().OpenMPSimd)
1635 return Address::invalid();
1636 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
1637 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1638 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
1639 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
1640 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
1641 HasRequiresUnifiedSharedMemory))) {
1642 SmallString<64> PtrName;
1643 {
1644 llvm::raw_svector_ostream OS(PtrName);
1645 OS << CGM.getMangledName(GlobalDecl(VD));
1646 if (!VD->isExternallyVisible()) {
1647 auto EntryInfo = getTargetEntryUniqueInfo(
1648 CGM.getContext(), VD->getCanonicalDecl()->getBeginLoc());
1649 OS << llvm::format("_%x", EntryInfo.FileID);
1650 }
1651 OS << "_decl_tgt_ref_ptr";
1652 }
1653 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
1654 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
1655 llvm::Type *LlvmPtrTy = CGM.getTypes().ConvertTypeForMem(PtrTy);
1656 if (!Ptr) {
1657 Ptr = OMPBuilder.getOrCreateInternalVariable(LlvmPtrTy, PtrName);
1658
1659 auto *GV = cast<llvm::GlobalVariable>(Ptr);
1660 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
1661
1662 if (!CGM.getLangOpts().OpenMPIsDevice)
1663 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
1664 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
1665 }
1666 return Address(Ptr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD));
1667 }
1668 return Address::invalid();
1669}
1670
1671llvm::Constant *
1672CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
1673 assert(!CGM.getLangOpts().OpenMPUseTLS ||(static_cast <bool> (!CGM.getLangOpts().OpenMPUseTLS ||
!CGM.getContext().getTargetInfo().isTLSSupported()) ? void (
0) : __assert_fail ("!CGM.getLangOpts().OpenMPUseTLS || !CGM.getContext().getTargetInfo().isTLSSupported()"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1674, __extension__
__PRETTY_FUNCTION__))
1674 !CGM.getContext().getTargetInfo().isTLSSupported())(static_cast <bool> (!CGM.getLangOpts().OpenMPUseTLS ||
!CGM.getContext().getTargetInfo().isTLSSupported()) ? void (
0) : __assert_fail ("!CGM.getLangOpts().OpenMPUseTLS || !CGM.getContext().getTargetInfo().isTLSSupported()"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1674, __extension__
__PRETTY_FUNCTION__))
;
1675 // Lookup the entry, lazily creating it if necessary.
1676 std::string Suffix = getName({"cache", ""});
1677 return OMPBuilder.getOrCreateInternalVariable(
1678 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix).str());
1679}
1680
1681Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1682 const VarDecl *VD,
1683 Address VDAddr,
1684 SourceLocation Loc) {
1685 if (CGM.getLangOpts().OpenMPUseTLS &&
1686 CGM.getContext().getTargetInfo().isTLSSupported())
1687 return VDAddr;
1688
1689 llvm::Type *VarTy = VDAddr.getElementType();
1690 llvm::Value *Args[] = {
1691 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1692 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy),
1693 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1694 getOrCreateThreadPrivateCache(VD)};
1695 return Address(
1696 CGF.EmitRuntimeCall(
1697 OMPBuilder.getOrCreateRuntimeFunction(
1698 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1699 Args),
1700 CGF.Int8Ty, VDAddr.getAlignment());
1701}
1702
1703void CGOpenMPRuntime::emitThreadPrivateVarInit(
1704 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
1705 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1706 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1707 // library.
1708 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
1709 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
1710 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1711 OMPLoc);
1712 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1713 // to register constructor/destructor for variable.
1714 llvm::Value *Args[] = {
1715 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
1716 Ctor, CopyCtor, Dtor};
1717 CGF.EmitRuntimeCall(
1718 OMPBuilder.getOrCreateRuntimeFunction(
1719 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1720 Args);
1721}
1722
1723llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
1724 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
1725 bool PerformInit, CodeGenFunction *CGF) {
1726 if (CGM.getLangOpts().OpenMPUseTLS &&
1727 CGM.getContext().getTargetInfo().isTLSSupported())
1728 return nullptr;
1729
1730 VD = VD->getDefinition(CGM.getContext());
1731 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
1732 QualType ASTTy = VD->getType();
1733
1734 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1735 const Expr *Init = VD->getAnyInitializer();
1736 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1737 // Generate function that re-emits the declaration's initializer into the
1738 // threadprivate copy of the variable VD
1739 CodeGenFunction CtorCGF(CGM);
1740 FunctionArgList Args;
1741 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
1742 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
1743 ImplicitParamDecl::Other);
1744 Args.push_back(&Dst);
1745
1746 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1747 CGM.getContext().VoidPtrTy, Args);
1748 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1749 std::string Name = getName({"__kmpc_global_ctor_", ""});
1750 llvm::Function *Fn =
1751 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1752 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1753 Args, Loc, Loc);
1754 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
1755 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
1756 CGM.getContext().VoidPtrTy, Dst.getLocation());
1757 Address Arg(ArgVal, CtorCGF.Int8Ty, VDAddr.getAlignment());
1758 Arg = CtorCGF.Builder.CreateElementBitCast(
1759 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
1760 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1761 /*IsInitializer=*/true);
1762 ArgVal = CtorCGF.EmitLoadOfScalar(
1763 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
1764 CGM.getContext().VoidPtrTy, Dst.getLocation());
1765 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1766 CtorCGF.FinishFunction();
1767 Ctor = Fn;
1768 }
1769 if (VD->getType().isDestructedType() != QualType::DK_none) {
1770 // Generate function that emits destructor call for the threadprivate copy
1771 // of the variable VD
1772 CodeGenFunction DtorCGF(CGM);
1773 FunctionArgList Args;
1774 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
1775 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
1776 ImplicitParamDecl::Other);
1777 Args.push_back(&Dst);
1778
1779 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1780 CGM.getContext().VoidTy, Args);
1781 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1782 std::string Name = getName({"__kmpc_global_dtor_", ""});
1783 llvm::Function *Fn =
1784 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1785 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
1786 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1787 Loc, Loc);
1788 // Create a scope with an artificial location for the body of this function.
1789 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
1790 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
1791 DtorCGF.GetAddrOfLocalVar(&Dst),
1792 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1793 DtorCGF.emitDestroy(
1794 Address(ArgVal, DtorCGF.Int8Ty, VDAddr.getAlignment()), ASTTy,
1795 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1796 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1797 DtorCGF.FinishFunction();
1798 Dtor = Fn;
1799 }
1800 // Do not emit init function if it is not required.
1801 if (!Ctor && !Dtor)
1802 return nullptr;
1803
1804 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1805 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1806 /*isVarArg=*/false)
1807 ->getPointerTo();
1808 // Copying constructor for the threadprivate variable.
1809 // Must be NULL - reserved by runtime, but currently it requires that this
1810 // parameter is always NULL. Otherwise it fires assertion.
1811 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1812 if (Ctor == nullptr) {
1813 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1814 /*isVarArg=*/false)
1815 ->getPointerTo();
1816 Ctor = llvm::Constant::getNullValue(CtorTy);
1817 }
1818 if (Dtor == nullptr) {
1819 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1820 /*isVarArg=*/false)
1821 ->getPointerTo();
1822 Dtor = llvm::Constant::getNullValue(DtorTy);
1823 }
1824 if (!CGF) {
1825 auto *InitFunctionTy =
1826 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1827 std::string Name = getName({"__omp_threadprivate_init_", ""});
1828 llvm::Function *InitFunction = CGM.CreateGlobalInitOrCleanUpFunction(
1829 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
1830 CodeGenFunction InitCGF(CGM);
1831 FunctionArgList ArgList;
1832 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1833 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1834 Loc, Loc);
1835 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
1836 InitCGF.FinishFunction();
1837 return InitFunction;
1838 }
1839 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
1840 }
1841 return nullptr;
1842}
1843
1844bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
1845 llvm::GlobalVariable *Addr,
1846 bool PerformInit) {
1847 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
1848 !CGM.getLangOpts().OpenMPIsDevice)
1849 return false;
1850 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
1851 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1852 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
1853 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
1854 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
1855 HasRequiresUnifiedSharedMemory))
1856 return CGM.getLangOpts().OpenMPIsDevice;
1857 VD = VD->getDefinition(CGM.getContext());
1858 assert(VD && "Unknown VarDecl")(static_cast <bool> (VD && "Unknown VarDecl") ?
void (0) : __assert_fail ("VD && \"Unknown VarDecl\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 1858, __extension__
__PRETTY_FUNCTION__))
;
1859
1860 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
1861 return CGM.getLangOpts().OpenMPIsDevice;
1862
1863 QualType ASTTy = VD->getType();
1864 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
1865
1866 // Produce the unique prefix to identify the new target regions. We use
1867 // the source location of the variable declaration which we know to not
1868 // conflict with any target region.
1869 auto EntryInfo =
1870 getTargetEntryUniqueInfo(CGM.getContext(), Loc, VD->getName());
1871 SmallString<128> Buffer, Out;
1872 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Buffer, EntryInfo);
1873
1874 const Expr *Init = VD->getAnyInitializer();
1875 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1876 llvm::Constant *Ctor;
1877 llvm::Constant *ID;
1878 if (CGM.getLangOpts().OpenMPIsDevice) {
1879 // Generate function that re-emits the declaration's initializer into
1880 // the threadprivate copy of the variable VD
1881 CodeGenFunction CtorCGF(CGM);
1882
1883 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
1884 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1885 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction(
1886 FTy, Twine(Buffer, "_ctor"), FI, Loc, false,
1887 llvm::GlobalValue::WeakODRLinkage);
1888 Fn->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1889 if (CGM.getTriple().isAMDGCN())
1890 Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
1891 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
1892 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
1893 FunctionArgList(), Loc, Loc);
1894 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
1895 llvm::Constant *AddrInAS0 = Addr;
1896 if (Addr->getAddressSpace() != 0)
1897 AddrInAS0 = llvm::ConstantExpr::getAddrSpaceCast(
1898 Addr, llvm::PointerType::getWithSamePointeeType(
1899 cast<llvm::PointerType>(Addr->getType()), 0));
1900 CtorCGF.EmitAnyExprToMem(Init,
1901 Address(AddrInAS0, Addr->getValueType(),
1902 CGM.getContext().getDeclAlign(VD)),
1903 Init->getType().getQualifiers(),
1904 /*IsInitializer=*/true);
1905 CtorCGF.FinishFunction();
1906 Ctor = Fn;
1907 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
1908 } else {
1909 Ctor = new llvm::GlobalVariable(
1910 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
1911 llvm::GlobalValue::PrivateLinkage,
1912 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
1913 ID = Ctor;
1914 }
1915
1916 // Register the information for the entry associated with the constructor.
1917 Out.clear();
1918 auto CtorEntryInfo = EntryInfo;
1919 CtorEntryInfo.ParentName = Twine(Buffer, "_ctor").toStringRef(Out);
1920 OMPBuilder.OffloadInfoManager.registerTargetRegionEntryInfo(
1921 CtorEntryInfo, Ctor, ID,
1922 llvm::OffloadEntriesInfoManager::OMPTargetRegionEntryCtor);
1923 }
1924 if (VD->getType().isDestructedType() != QualType::DK_none) {
1925 llvm::Constant *Dtor;
1926 llvm::Constant *ID;
1927 if (CGM.getLangOpts().OpenMPIsDevice) {
1928 // Generate function that emits destructor call for the threadprivate
1929 // copy of the variable VD
1930 CodeGenFunction DtorCGF(CGM);
1931
1932 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
1933 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1934 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction(
1935 FTy, Twine(Buffer, "_dtor"), FI, Loc, false,
1936 llvm::GlobalValue::WeakODRLinkage);
1937 Fn->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1938 if (CGM.getTriple().isAMDGCN())
1939 Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
1940 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
1941 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
1942 FunctionArgList(), Loc, Loc);
1943 // Create a scope with an artificial location for the body of this
1944 // function.
1945 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
1946 llvm::Constant *AddrInAS0 = Addr;
1947 if (Addr->getAddressSpace() != 0)
1948 AddrInAS0 = llvm::ConstantExpr::getAddrSpaceCast(
1949 Addr, llvm::PointerType::getWithSamePointeeType(
1950 cast<llvm::PointerType>(Addr->getType()), 0));
1951 DtorCGF.emitDestroy(Address(AddrInAS0, Addr->getValueType(),
1952 CGM.getContext().getDeclAlign(VD)),
1953 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1954 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1955 DtorCGF.FinishFunction();
1956 Dtor = Fn;
1957 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
1958 } else {
1959 Dtor = new llvm::GlobalVariable(
1960 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
1961 llvm::GlobalValue::PrivateLinkage,
1962 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
1963 ID = Dtor;
1964 }
1965 // Register the information for the entry associated with the destructor.
1966 Out.clear();
1967 auto DtorEntryInfo = EntryInfo;
1968 DtorEntryInfo.ParentName = Twine(Buffer, "_dtor").toStringRef(Out);
1969 OMPBuilder.OffloadInfoManager.registerTargetRegionEntryInfo(
1970 DtorEntryInfo, Dtor, ID,
1971 llvm::OffloadEntriesInfoManager::OMPTargetRegionEntryDtor);
1972 }
1973 return CGM.getLangOpts().OpenMPIsDevice;
1974}
1975
1976Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
1977 QualType VarType,
1978 StringRef Name) {
1979 std::string Suffix = getName({"artificial", ""});
1980 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
1981 llvm::GlobalVariable *GAddr = OMPBuilder.getOrCreateInternalVariable(
1982 VarLVType, Twine(Name).concat(Suffix).str());
1983 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS &&
1984 CGM.getTarget().isTLSSupported()) {
1985 GAddr->setThreadLocal(/*Val=*/true);
1986 return Address(GAddr, GAddr->getValueType(),
1987 CGM.getContext().getTypeAlignInChars(VarType));
1988 }
1989 std::string CacheSuffix = getName({"cache", ""});
1990 llvm::Value *Args[] = {
1991 emitUpdateLocation(CGF, SourceLocation()),
1992 getThreadID(CGF, SourceLocation()),
1993 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
1994 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
1995 /*isSigned=*/false),
1996 OMPBuilder.getOrCreateInternalVariable(
1997 CGM.VoidPtrPtrTy,
1998 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1999 return Address(
2000 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2001 CGF.EmitRuntimeCall(
2002 OMPBuilder.getOrCreateRuntimeFunction(
2003 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
2004 Args),
2005 VarLVType->getPointerTo(/*AddrSpace=*/0)),
2006 VarLVType, CGM.getContext().getTypeAlignInChars(VarType));
2007}
2008
2009void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond,
2010 const RegionCodeGenTy &ThenGen,
2011 const RegionCodeGenTy &ElseGen) {
2012 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
2013
2014 // If the condition constant folds and can be elided, try to avoid emitting
2015 // the condition and the dead arm of the if/else.
2016 bool CondConstant;
2017 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
2018 if (CondConstant)
2019 ThenGen(CGF);
2020 else
2021 ElseGen(CGF);
2022 return;
2023 }
2024
2025 // Otherwise, the condition did not fold, or we couldn't elide it. Just
2026 // emit the conditional branch.
2027 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
2028 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
2029 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
2030 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
2031
2032 // Emit the 'then' code.
2033 CGF.EmitBlock(ThenBlock);
2034 ThenGen(CGF);
2035 CGF.EmitBranch(ContBlock);
2036 // Emit the 'else' code if present.
2037 // There is no need to emit line number for unconditional branch.
2038 (void)ApplyDebugLocation::CreateEmpty(CGF);
2039 CGF.EmitBlock(ElseBlock);
2040 ElseGen(CGF);
2041 // There is no need to emit line number for unconditional branch.
2042 (void)ApplyDebugLocation::CreateEmpty(CGF);
2043 CGF.EmitBranch(ContBlock);
2044 // Emit the continuation block for code after the if.
2045 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
2046}
2047
2048void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
2049 llvm::Function *OutlinedFn,
2050 ArrayRef<llvm::Value *> CapturedVars,
2051 const Expr *IfCond,
2052 llvm::Value *NumThreads) {
2053 if (!CGF.HaveInsertPoint())
2054 return;
2055 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
2056 auto &M = CGM.getModule();
2057 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
2058 this](CodeGenFunction &CGF, PrePostActionTy &) {
2059 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
2060 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
2061 llvm::Value *Args[] = {
2062 RTLoc,
2063 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
2064 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
2065 llvm::SmallVector<llvm::Value *, 16> RealArgs;
2066 RealArgs.append(std::begin(Args), std::end(Args));
2067 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2068
2069 llvm::FunctionCallee RTLFn =
2070 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
2071 CGF.EmitRuntimeCall(RTLFn, RealArgs);
2072 };
2073 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2074 this](CodeGenFunction &CGF, PrePostActionTy &) {
2075 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
2076 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
2077 // Build calls:
2078 // __kmpc_serialized_parallel(&Loc, GTid);
2079 llvm::Value *Args[] = {RTLoc, ThreadID};
2080 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2081 M, OMPRTL___kmpc_serialized_parallel),
2082 Args);
2083
2084 // OutlinedFn(&GTid, &zero_bound, CapturedStruct);
2085 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
2086 Address ZeroAddrBound =
2087 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
2088 /*Name=*/".bound.zero.addr");
2089 CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddrBound);
2090 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
2091 // ThreadId for serialized parallels is 0.
2092 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
2093 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer());
2094 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2095
2096 // Ensure we do not inline the function. This is trivially true for the ones
2097 // passed to __kmpc_fork_call but the ones called in serialized regions
2098 // could be inlined. This is not a perfect but it is closer to the invariant
2099 // we want, namely, every data environment starts with a new function.
2100 // TODO: We should pass the if condition to the runtime function and do the
2101 // handling there. Much cleaner code.
2102 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
2103 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2104 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
2105
2106 // __kmpc_end_serialized_parallel(&Loc, GTid);
2107 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
2108 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2109 M, OMPRTL___kmpc_end_serialized_parallel),
2110 EndArgs);
2111 };
2112 if (IfCond) {
2113 emitIfClause(CGF, IfCond, ThenGen, ElseGen);
2114 } else {
2115 RegionCodeGenTy ThenRCG(ThenGen);
2116 ThenRCG(CGF);
2117 }
2118}
2119
2120// If we're inside an (outlined) parallel region, use the region info's
2121// thread-ID variable (it is passed in a first argument of the outlined function
2122// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
2123// regular serial code region, get thread ID by calling kmp_int32
2124// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
2125// return the address of that temp.
2126Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
2127 SourceLocation Loc) {
2128 if (auto *OMPRegionInfo =
2129 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
2130 if (OMPRegionInfo->getThreadIDVariable())
2131 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF);
2132
2133 llvm::Value *ThreadID = getThreadID(CGF, Loc);
2134 QualType Int32Ty =
2135 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
2136 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
2137 CGF.EmitStoreOfScalar(ThreadID,
2138 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
2139
2140 return ThreadIDTemp;
2141}
2142
2143llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
2144 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
2145 std::string Name = getName({Prefix, "var"});
2146 return OMPBuilder.getOrCreateInternalVariable(KmpCriticalNameTy, Name);
2147}
2148
2149namespace {
2150/// Common pre(post)-action for different OpenMP constructs.
2151class CommonActionTy final : public PrePostActionTy {
2152 llvm::FunctionCallee EnterCallee;
2153 ArrayRef<llvm::Value *> EnterArgs;
2154 llvm::FunctionCallee ExitCallee;
2155 ArrayRef<llvm::Value *> ExitArgs;
2156 bool Conditional;
2157 llvm::BasicBlock *ContBlock = nullptr;
2158
2159public:
2160 CommonActionTy(llvm::FunctionCallee EnterCallee,
2161 ArrayRef<llvm::Value *> EnterArgs,
2162 llvm::FunctionCallee ExitCallee,
2163 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
2164 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2165 ExitArgs(ExitArgs), Conditional(Conditional) {}
2166 void Enter(CodeGenFunction &CGF) override {
2167 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
2168 if (Conditional) {
2169 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
2170 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
2171 ContBlock = CGF.createBasicBlock("omp_if.end");
2172 // Generate the branch (If-stmt)
2173 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2174 CGF.EmitBlock(ThenBlock);
2175 }
2176 }
2177 void Done(CodeGenFunction &CGF) {
2178 // Emit the rest of blocks/branches
2179 CGF.EmitBranch(ContBlock);
2180 CGF.EmitBlock(ContBlock, true);
2181 }
2182 void Exit(CodeGenFunction &CGF) override {
2183 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
2184 }
2185};
2186} // anonymous namespace
2187
2188void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
2189 StringRef CriticalName,
2190 const RegionCodeGenTy &CriticalOpGen,
2191 SourceLocation Loc, const Expr *Hint) {
2192 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
2193 // CriticalOpGen();
2194 // __kmpc_end_critical(ident_t *, gtid, Lock);
2195 // Prepare arguments and build a call to __kmpc_critical
2196 if (!CGF.HaveInsertPoint())
2197 return;
2198 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2199 getCriticalRegionLock(CriticalName)};
2200 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
2201 std::end(Args));
2202 if (Hint) {
2203 EnterArgs.push_back(CGF.Builder.CreateIntCast(
2204 CGF.EmitScalarExpr(Hint), CGM.Int32Ty, /*isSigned=*/false));
2205 }
2206 CommonActionTy Action(
2207 OMPBuilder.getOrCreateRuntimeFunction(
2208 CGM.getModule(),
2209 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical),
2210 EnterArgs,
2211 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
2212 OMPRTL___kmpc_end_critical),
2213 Args);
2214 CriticalOpGen.setAction(Action);
2215 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
2216}
2217
2218void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
2219 const RegionCodeGenTy &MasterOpGen,
2220 SourceLocation Loc) {
2221 if (!CGF.HaveInsertPoint())
2222 return;
2223 // if(__kmpc_master(ident_t *, gtid)) {
2224 // MasterOpGen();
2225 // __kmpc_end_master(ident_t *, gtid);
2226 // }
2227 // Prepare arguments and build a call to __kmpc_master
2228 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2229 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2230 CGM.getModule(), OMPRTL___kmpc_master),
2231 Args,
2232 OMPBuilder.getOrCreateRuntimeFunction(
2233 CGM.getModule(), OMPRTL___kmpc_end_master),
2234 Args,
2235 /*Conditional=*/true);
2236 MasterOpGen.setAction(Action);
2237 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
2238 Action.Done(CGF);
2239}
2240
2241void CGOpenMPRuntime::emitMaskedRegion(CodeGenFunction &CGF,
2242 const RegionCodeGenTy &MaskedOpGen,
2243 SourceLocation Loc, const Expr *Filter) {
2244 if (!CGF.HaveInsertPoint())
2245 return;
2246 // if(__kmpc_masked(ident_t *, gtid, filter)) {
2247 // MaskedOpGen();
2248 // __kmpc_end_masked(iden_t *, gtid);
2249 // }
2250 // Prepare arguments and build a call to __kmpc_masked
2251 llvm::Value *FilterVal = Filter
2252 ? CGF.EmitScalarExpr(Filter, CGF.Int32Ty)
2253 : llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/0);
2254 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2255 FilterVal};
2256 llvm::Value *ArgsEnd[] = {emitUpdateLocation(CGF, Loc),
2257 getThreadID(CGF, Loc)};
2258 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2259 CGM.getModule(), OMPRTL___kmpc_masked),
2260 Args,
2261 OMPBuilder.getOrCreateRuntimeFunction(
2262 CGM.getModule(), OMPRTL___kmpc_end_masked),
2263 ArgsEnd,
2264 /*Conditional=*/true);
2265 MaskedOpGen.setAction(Action);
2266 emitInlinedDirective(CGF, OMPD_masked, MaskedOpGen);
2267 Action.Done(CGF);
2268}
2269
2270void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
2271 SourceLocation Loc) {
2272 if (!CGF.HaveInsertPoint())
2273 return;
2274 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
2275 OMPBuilder.createTaskyield(CGF.Builder);
2276 } else {
2277 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
2278 llvm::Value *Args[] = {
2279 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2280 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
2281 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2282 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2283 Args);
2284 }
2285
2286 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
2287 Region->emitUntiedSwitch(CGF);
2288}
2289
2290void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
2291 const RegionCodeGenTy &TaskgroupOpGen,
2292 SourceLocation Loc) {
2293 if (!CGF.HaveInsertPoint())
2294 return;
2295 // __kmpc_taskgroup(ident_t *, gtid);
2296 // TaskgroupOpGen();
2297 // __kmpc_end_taskgroup(ident_t *, gtid);
2298 // Prepare arguments and build a call to __kmpc_taskgroup
2299 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2300 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2301 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2302 Args,
2303 OMPBuilder.getOrCreateRuntimeFunction(
2304 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2305 Args);
2306 TaskgroupOpGen.setAction(Action);
2307 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
2308}
2309
2310/// Given an array of pointers to variables, project the address of a
2311/// given variable.
2312static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
2313 unsigned Index, const VarDecl *Var) {
2314 // Pull out the pointer to the variable.
2315 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
2316 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
2317
2318 llvm::Type *ElemTy = CGF.ConvertTypeForMem(Var->getType());
2319 return Address(
2320 CGF.Builder.CreateBitCast(
2321 Ptr, ElemTy->getPointerTo(Ptr->getType()->getPointerAddressSpace())),
2322 ElemTy, CGF.getContext().getDeclAlign(Var));
2323}
2324
2325static llvm::Value *emitCopyprivateCopyFunction(
2326 CodeGenModule &CGM, llvm::Type *ArgsElemType,
2327 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
2328 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
2329 SourceLocation Loc) {
2330 ASTContext &C = CGM.getContext();
2331 // void copy_func(void *LHSArg, void *RHSArg);
2332 FunctionArgList Args;
2333 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
2334 ImplicitParamDecl::Other);
2335 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
2336 ImplicitParamDecl::Other);
2337 Args.push_back(&LHSArg);
2338 Args.push_back(&RHSArg);
2339 const auto &CGFI =
2340 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
2341 std::string Name =
2342 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
2343 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
2344 llvm::GlobalValue::InternalLinkage, Name,
2345 &CGM.getModule());
2346 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
2347 Fn->setDoesNotRecurse();
2348 CodeGenFunction CGF(CGM);
2349 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
2350 // Dest = (void*[n])(LHSArg);
2351 // Src = (void*[n])(RHSArg);
2352 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2353 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2354 ArgsElemType->getPointerTo()),
2355 ArgsElemType, CGF.getPointerAlign());
2356 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2357 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2358 ArgsElemType->getPointerTo()),
2359 ArgsElemType, CGF.getPointerAlign());
2360 // *(Type0*)Dst[0] = *(Type0*)Src[0];
2361 // *(Type1*)Dst[1] = *(Type1*)Src[1];
2362 // ...
2363 // *(Typen*)Dst[n] = *(Typen*)Src[n];
2364 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2365 const auto *DestVar =
2366 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2367 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
2368
2369 const auto *SrcVar =
2370 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2371 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
2372
2373 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2374 QualType Type = VD->getType();
2375 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2376 }
2377 CGF.FinishFunction();
2378 return Fn;
2379}
2380
2381void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
2382 const RegionCodeGenTy &SingleOpGen,
2383 SourceLocation Loc,
2384 ArrayRef<const Expr *> CopyprivateVars,
2385 ArrayRef<const Expr *> SrcExprs,
2386 ArrayRef<const Expr *> DstExprs,
2387 ArrayRef<const Expr *> AssignmentOps) {
2388 if (!CGF.HaveInsertPoint())
2389 return;
2390 assert(CopyprivateVars.size() == SrcExprs.size() &&(static_cast <bool> (CopyprivateVars.size() == SrcExprs
.size() && CopyprivateVars.size() == DstExprs.size() &&
CopyprivateVars.size() == AssignmentOps.size()) ? void (0) :
__assert_fail ("CopyprivateVars.size() == SrcExprs.size() && CopyprivateVars.size() == DstExprs.size() && CopyprivateVars.size() == AssignmentOps.size()"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2392, __extension__
__PRETTY_FUNCTION__))
2391 CopyprivateVars.size() == DstExprs.size() &&(static_cast <bool> (CopyprivateVars.size() == SrcExprs
.size() && CopyprivateVars.size() == DstExprs.size() &&
CopyprivateVars.size() == AssignmentOps.size()) ? void (0) :
__assert_fail ("CopyprivateVars.size() == SrcExprs.size() && CopyprivateVars.size() == DstExprs.size() && CopyprivateVars.size() == AssignmentOps.size()"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2392, __extension__
__PRETTY_FUNCTION__))
2392 CopyprivateVars.size() == AssignmentOps.size())(static_cast <bool> (CopyprivateVars.size() == SrcExprs
.size() && CopyprivateVars.size() == DstExprs.size() &&
CopyprivateVars.size() == AssignmentOps.size()) ? void (0) :
__assert_fail ("CopyprivateVars.size() == SrcExprs.size() && CopyprivateVars.size() == DstExprs.size() && CopyprivateVars.size() == AssignmentOps.size()"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2392, __extension__
__PRETTY_FUNCTION__))
;
2393 ASTContext &C = CGM.getContext();
2394 // int32 did_it = 0;
2395 // if(__kmpc_single(ident_t *, gtid)) {
2396 // SingleOpGen();
2397 // __kmpc_end_single(ident_t *, gtid);
2398 // did_it = 1;
2399 // }
2400 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2401 // <copy_func>, did_it);
2402
2403 Address DidIt = Address::invalid();
2404 if (!CopyprivateVars.empty()) {
2405 // int32 did_it = 0;
2406 QualType KmpInt32Ty =
2407 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2408 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
2409 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
2410 }
2411 // Prepare arguments and build a call to __kmpc_single
2412 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2413 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2414 CGM.getModule(), OMPRTL___kmpc_single),
2415 Args,
2416 OMPBuilder.getOrCreateRuntimeFunction(
2417 CGM.getModule(), OMPRTL___kmpc_end_single),
2418 Args,
2419 /*Conditional=*/true);
2420 SingleOpGen.setAction(Action);
2421 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
2422 if (DidIt.isValid()) {
2423 // did_it = 1;
2424 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
2425 }
2426 Action.Done(CGF);
2427 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2428 // <copy_func>, did_it);
2429 if (DidIt.isValid()) {
2430 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
2431 QualType CopyprivateArrayTy = C.getConstantArrayType(
2432 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
2433 /*IndexTypeQuals=*/0);
2434 // Create a list of all private variables for copyprivate.
2435 Address CopyprivateList =
2436 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
2437 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2438 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
2439 CGF.Builder.CreateStore(
2440 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2441 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF),
2442 CGF.VoidPtrTy),
2443 Elem);
2444 }
2445 // Build function that copies private values from single region to all other
2446 // threads in the corresponding parallel region.
2447 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
2448 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy), CopyprivateVars,
2449 SrcExprs, DstExprs, AssignmentOps, Loc);
2450 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
2451 Address CL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2452 CopyprivateList, CGF.VoidPtrTy, CGF.Int8Ty);
2453 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
2454 llvm::Value *Args[] = {
2455 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
2456 getThreadID(CGF, Loc), // i32 <gtid>
2457 BufSize, // size_t <buf_size>
2458 CL.getPointer(), // void *<copyprivate list>
2459 CpyFn, // void (*) (void *, void *) <copy_func>
2460 DidItVal // i32 did_it
2461 };
2462 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2463 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2464 Args);
2465 }
2466}
2467
2468void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
2469 const RegionCodeGenTy &OrderedOpGen,
2470 SourceLocation Loc, bool IsThreads) {
2471 if (!CGF.HaveInsertPoint())
2472 return;
2473 // __kmpc_ordered(ident_t *, gtid);
2474 // OrderedOpGen();
2475 // __kmpc_end_ordered(ident_t *, gtid);
2476 // Prepare arguments and build a call to __kmpc_ordered
2477 if (IsThreads) {
2478 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2479 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2480 CGM.getModule(), OMPRTL___kmpc_ordered),
2481 Args,
2482 OMPBuilder.getOrCreateRuntimeFunction(
2483 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2484 Args);
2485 OrderedOpGen.setAction(Action);
2486 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2487 return;
2488 }
2489 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2490}
2491
2492unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
2493 unsigned Flags;
2494 if (Kind == OMPD_for)
2495 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2496 else if (Kind == OMPD_sections)
2497 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2498 else if (Kind == OMPD_single)
2499 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2500 else if (Kind == OMPD_barrier)
2501 Flags = OMP_IDENT_BARRIER_EXPL;
2502 else
2503 Flags = OMP_IDENT_BARRIER_IMPL;
2504 return Flags;
2505}
2506
2507void CGOpenMPRuntime::getDefaultScheduleAndChunk(
2508 CodeGenFunction &CGF, const OMPLoopDirective &S,
2509 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
2510 // Check if the loop directive is actually a doacross loop directive. In this
2511 // case choose static, 1 schedule.
2512 if (llvm::any_of(
2513 S.getClausesOfKind<OMPOrderedClause>(),
2514 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
2515 ScheduleKind = OMPC_SCHEDULE_static;
2516 // Chunk size is 1 in this case.
2517 llvm::APInt ChunkSize(32, 1);
2518 ChunkExpr = IntegerLiteral::Create(
2519 CGF.getContext(), ChunkSize,
2520 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
2521 SourceLocation());
2522 }
2523}
2524
2525void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
2526 OpenMPDirectiveKind Kind, bool EmitChecks,
2527 bool ForceSimpleCall) {
2528 // Check if we should use the OMPBuilder
2529 auto *OMPRegionInfo =
2530 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
2531 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
2532 CGF.Builder.restoreIP(OMPBuilder.createBarrier(
2533 CGF.Builder, Kind, ForceSimpleCall, EmitChecks));
2534 return;
2535 }
2536
2537 if (!CGF.HaveInsertPoint())
2538 return;
2539 // Build call __kmpc_cancel_barrier(loc, thread_id);
2540 // Build call __kmpc_barrier(loc, thread_id);
2541 unsigned Flags = getDefaultFlagsForBarriers(Kind);
2542 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
2543 // thread_id);
2544 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
2545 getThreadID(CGF, Loc)};
2546 if (OMPRegionInfo) {
2547 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2548 llvm::Value *Result = CGF.EmitRuntimeCall(
2549 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
2550 OMPRTL___kmpc_cancel_barrier),
2551 Args);
2552 if (EmitChecks) {
2553 // if (__kmpc_cancel_barrier()) {
2554 // exit from construct;
2555 // }
2556 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
2557 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
2558 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
2559 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2560 CGF.EmitBlock(ExitBB);
2561 // exit from construct;
2562 CodeGenFunction::JumpDest CancelDestination =
2563 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
2564 CGF.EmitBranchThroughCleanup(CancelDestination);
2565 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2566 }
2567 return;
2568 }
2569 }
2570 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2571 CGM.getModule(), OMPRTL___kmpc_barrier),
2572 Args);
2573}
2574
2575void CGOpenMPRuntime::emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc,
2576 Expr *ME, bool IsFatal) {
2577 llvm::Value *MVL =
2578 ME ? CGF.EmitStringLiteralLValue(cast<StringLiteral>(ME)).getPointer(CGF)
2579 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2580 // Build call void __kmpc_error(ident_t *loc, int severity, const char
2581 // *message)
2582 llvm::Value *Args[] = {
2583 emitUpdateLocation(CGF, Loc, /*Flags=*/0, /*GenLoc=*/true),
2584 llvm::ConstantInt::get(CGM.Int32Ty, IsFatal ? 2 : 1),
2585 CGF.Builder.CreatePointerCast(MVL, CGM.Int8PtrTy)};
2586 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2587 CGM.getModule(), OMPRTL___kmpc_error),
2588 Args);
2589}
2590
2591/// Map the OpenMP loop schedule to the runtime enumeration.
2592static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
2593 bool Chunked, bool Ordered) {
2594 switch (ScheduleKind) {
2595 case OMPC_SCHEDULE_static:
2596 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2597 : (Ordered ? OMP_ord_static : OMP_sch_static);
2598 case OMPC_SCHEDULE_dynamic:
2599 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2600 case OMPC_SCHEDULE_guided:
2601 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2602 case OMPC_SCHEDULE_runtime:
2603 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2604 case OMPC_SCHEDULE_auto:
2605 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2606 case OMPC_SCHEDULE_unknown:
2607 assert(!Chunked && "chunk was specified but schedule kind not known")(static_cast <bool> (!Chunked && "chunk was specified but schedule kind not known"
) ? void (0) : __assert_fail ("!Chunked && \"chunk was specified but schedule kind not known\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2607, __extension__
__PRETTY_FUNCTION__))
;
2608 return Ordered ? OMP_ord_static : OMP_sch_static;
2609 }
2610 llvm_unreachable("Unexpected runtime schedule")::llvm::llvm_unreachable_internal("Unexpected runtime schedule"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2610)
;
2611}
2612
2613/// Map the OpenMP distribute schedule to the runtime enumeration.
2614static OpenMPSchedType
2615getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
2616 // only static is allowed for dist_schedule
2617 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2618}
2619
2620bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
2621 bool Chunked) const {
2622 OpenMPSchedType Schedule =
2623 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
2624 return Schedule == OMP_sch_static;
2625}
2626
2627bool CGOpenMPRuntime::isStaticNonchunked(
2628 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2629 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2630 return Schedule == OMP_dist_sch_static;
2631}
2632
2633bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
2634 bool Chunked) const {
2635 OpenMPSchedType Schedule =
2636 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
2637 return Schedule == OMP_sch_static_chunked;
2638}
2639
2640bool CGOpenMPRuntime::isStaticChunked(
2641 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2642 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2643 return Schedule == OMP_dist_sch_static_chunked;
2644}
2645
2646bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
2647 OpenMPSchedType Schedule =
2648 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
2649 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here")(static_cast <bool> (Schedule != OMP_sch_static_chunked
&& "cannot be chunked here") ? void (0) : __assert_fail
("Schedule != OMP_sch_static_chunked && \"cannot be chunked here\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2649, __extension__
__PRETTY_FUNCTION__))
;
2650 return Schedule != OMP_sch_static;
2651}
2652
2653static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
2654 OpenMPScheduleClauseModifier M1,
2655 OpenMPScheduleClauseModifier M2) {
2656 int Modifier = 0;
2657 switch (M1) {
2658 case OMPC_SCHEDULE_MODIFIER_monotonic:
2659 Modifier = OMP_sch_modifier_monotonic;
2660 break;
2661 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2662 Modifier = OMP_sch_modifier_nonmonotonic;
2663 break;
2664 case OMPC_SCHEDULE_MODIFIER_simd:
2665 if (Schedule == OMP_sch_static_chunked)
2666 Schedule = OMP_sch_static_balanced_chunked;
2667 break;
2668 case OMPC_SCHEDULE_MODIFIER_last:
2669 case OMPC_SCHEDULE_MODIFIER_unknown:
2670 break;
2671 }
2672 switch (M2) {
2673 case OMPC_SCHEDULE_MODIFIER_monotonic:
2674 Modifier = OMP_sch_modifier_monotonic;
2675 break;
2676 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2677 Modifier = OMP_sch_modifier_nonmonotonic;
2678 break;
2679 case OMPC_SCHEDULE_MODIFIER_simd:
2680 if (Schedule == OMP_sch_static_chunked)
2681 Schedule = OMP_sch_static_balanced_chunked;
2682 break;
2683 case OMPC_SCHEDULE_MODIFIER_last:
2684 case OMPC_SCHEDULE_MODIFIER_unknown:
2685 break;
2686 }
2687 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
2688 // If the static schedule kind is specified or if the ordered clause is
2689 // specified, and if the nonmonotonic modifier is not specified, the effect is
2690 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
2691 // modifier is specified, the effect is as if the nonmonotonic modifier is
2692 // specified.
2693 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
2694 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2695 Schedule == OMP_sch_static_balanced_chunked ||
2696 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2697 Schedule == OMP_dist_sch_static_chunked ||
2698 Schedule == OMP_dist_sch_static))
2699 Modifier = OMP_sch_modifier_nonmonotonic;
2700 }
2701 return Schedule | Modifier;
2702}
2703
2704void CGOpenMPRuntime::emitForDispatchInit(
2705 CodeGenFunction &CGF, SourceLocation Loc,
2706 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
2707 bool Ordered, const DispatchRTInput &DispatchValues) {
2708 if (!CGF.HaveInsertPoint())
2709 return;
2710 OpenMPSchedType Schedule = getRuntimeSchedule(
2711 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
2712 assert(Ordered ||(static_cast <bool> (Ordered || (Schedule != OMP_sch_static
&& Schedule != OMP_sch_static_chunked && Schedule
!= OMP_ord_static && Schedule != OMP_ord_static_chunked
&& Schedule != OMP_sch_static_balanced_chunked)) ? void
(0) : __assert_fail ("Ordered || (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && Schedule != OMP_sch_static_balanced_chunked)"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2715, __extension__
__PRETTY_FUNCTION__))
2713 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&(static_cast <bool> (Ordered || (Schedule != OMP_sch_static
&& Schedule != OMP_sch_static_chunked && Schedule
!= OMP_ord_static && Schedule != OMP_ord_static_chunked
&& Schedule != OMP_sch_static_balanced_chunked)) ? void
(0) : __assert_fail ("Ordered || (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && Schedule != OMP_sch_static_balanced_chunked)"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2715, __extension__
__PRETTY_FUNCTION__))
2714 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&(static_cast <bool> (Ordered || (Schedule != OMP_sch_static
&& Schedule != OMP_sch_static_chunked && Schedule
!= OMP_ord_static && Schedule != OMP_ord_static_chunked
&& Schedule != OMP_sch_static_balanced_chunked)) ? void
(0) : __assert_fail ("Ordered || (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && Schedule != OMP_sch_static_balanced_chunked)"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2715, __extension__
__PRETTY_FUNCTION__))
2715 Schedule != OMP_sch_static_balanced_chunked))(static_cast <bool> (Ordered || (Schedule != OMP_sch_static
&& Schedule != OMP_sch_static_chunked && Schedule
!= OMP_ord_static && Schedule != OMP_ord_static_chunked
&& Schedule != OMP_sch_static_balanced_chunked)) ? void
(0) : __assert_fail ("Ordered || (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && Schedule != OMP_sch_static_balanced_chunked)"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2715, __extension__
__PRETTY_FUNCTION__))
;
2716 // Call __kmpc_dispatch_init(
2717 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
2718 // kmp_int[32|64] lower, kmp_int[32|64] upper,
2719 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
2720
2721 // If the Chunk was not specified in the clause - use default value 1.
2722 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
2723 : CGF.Builder.getIntN(IVSize, 1);
2724 llvm::Value *Args[] = {
2725 emitUpdateLocation(CGF, Loc),
2726 getThreadID(CGF, Loc),
2727 CGF.Builder.getInt32(addMonoNonMonoModifier(
2728 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
2729 DispatchValues.LB, // Lower
2730 DispatchValues.UB, // Upper
2731 CGF.Builder.getIntN(IVSize, 1), // Stride
2732 Chunk // Chunk
2733 };
2734 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
2735}
2736
2737static void emitForStaticInitCall(
2738 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2739 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2740 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
2741 const CGOpenMPRuntime::StaticRTInput &Values) {
2742 if (!CGF.HaveInsertPoint())
2743 return;
2744
2745 assert(!Values.Ordered)(static_cast <bool> (!Values.Ordered) ? void (0) : __assert_fail
("!Values.Ordered", "clang/lib/CodeGen/CGOpenMPRuntime.cpp",
2745, __extension__ __PRETTY_FUNCTION__))
;
2746 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||(static_cast <bool> (Schedule == OMP_sch_static || Schedule
== OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked
|| Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked
|| Schedule == OMP_dist_sch_static || Schedule == OMP_dist_sch_static_chunked
) ? void (0) : __assert_fail ("Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked || Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || Schedule == OMP_dist_sch_static || Schedule == OMP_dist_sch_static_chunked"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2750, __extension__
__PRETTY_FUNCTION__))
2747 Schedule == OMP_sch_static_balanced_chunked ||(static_cast <bool> (Schedule == OMP_sch_static || Schedule
== OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked
|| Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked
|| Schedule == OMP_dist_sch_static || Schedule == OMP_dist_sch_static_chunked
) ? void (0) : __assert_fail ("Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked || Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || Schedule == OMP_dist_sch_static || Schedule == OMP_dist_sch_static_chunked"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2750, __extension__
__PRETTY_FUNCTION__))
2748 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||(static_cast <bool> (Schedule == OMP_sch_static || Schedule
== OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked
|| Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked
|| Schedule == OMP_dist_sch_static || Schedule == OMP_dist_sch_static_chunked
) ? void (0) : __assert_fail ("Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked || Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || Schedule == OMP_dist_sch_static || Schedule == OMP_dist_sch_static_chunked"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2750, __extension__
__PRETTY_FUNCTION__))
2749 Schedule == OMP_dist_sch_static ||(static_cast <bool> (Schedule == OMP_sch_static || Schedule
== OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked
|| Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked
|| Schedule == OMP_dist_sch_static || Schedule == OMP_dist_sch_static_chunked
) ? void (0) : __assert_fail ("Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked || Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || Schedule == OMP_dist_sch_static || Schedule == OMP_dist_sch_static_chunked"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2750, __extension__
__PRETTY_FUNCTION__))
2750 Schedule == OMP_dist_sch_static_chunked)(static_cast <bool> (Schedule == OMP_sch_static || Schedule
== OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked
|| Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked
|| Schedule == OMP_dist_sch_static || Schedule == OMP_dist_sch_static_chunked
) ? void (0) : __assert_fail ("Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked || Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || Schedule == OMP_dist_sch_static || Schedule == OMP_dist_sch_static_chunked"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2750, __extension__
__PRETTY_FUNCTION__))
;
2751
2752 // Call __kmpc_for_static_init(
2753 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
2754 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
2755 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
2756 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
2757 llvm::Value *Chunk = Values.Chunk;
2758 if (Chunk == nullptr) {
2759 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||(static_cast <bool> ((Schedule == OMP_sch_static || Schedule
== OMP_ord_static || Schedule == OMP_dist_sch_static) &&
"expected static non-chunked schedule") ? void (0) : __assert_fail
("(Schedule == OMP_sch_static || Schedule == OMP_ord_static || Schedule == OMP_dist_sch_static) && \"expected static non-chunked schedule\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2761, __extension__
__PRETTY_FUNCTION__))
2760 Schedule == OMP_dist_sch_static) &&(static_cast <bool> ((Schedule == OMP_sch_static || Schedule
== OMP_ord_static || Schedule == OMP_dist_sch_static) &&
"expected static non-chunked schedule") ? void (0) : __assert_fail
("(Schedule == OMP_sch_static || Schedule == OMP_ord_static || Schedule == OMP_dist_sch_static) && \"expected static non-chunked schedule\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2761, __extension__
__PRETTY_FUNCTION__))
2761 "expected static non-chunked schedule")(static_cast <bool> ((Schedule == OMP_sch_static || Schedule
== OMP_ord_static || Schedule == OMP_dist_sch_static) &&
"expected static non-chunked schedule") ? void (0) : __assert_fail
("(Schedule == OMP_sch_static || Schedule == OMP_ord_static || Schedule == OMP_dist_sch_static) && \"expected static non-chunked schedule\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2761, __extension__
__PRETTY_FUNCTION__))
;
2762 // If the Chunk was not specified in the clause - use default value 1.
2763 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
2764 } else {
2765 assert((Schedule == OMP_sch_static_chunked ||(static_cast <bool> ((Schedule == OMP_sch_static_chunked
|| Schedule == OMP_sch_static_balanced_chunked || Schedule ==
OMP_ord_static_chunked || Schedule == OMP_dist_sch_static_chunked
) && "expected static chunked schedule") ? void (0) :
__assert_fail ("(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked || Schedule == OMP_ord_static_chunked || Schedule == OMP_dist_sch_static_chunked) && \"expected static chunked schedule\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2769, __extension__
__PRETTY_FUNCTION__))
2766 Schedule == OMP_sch_static_balanced_chunked ||(static_cast <bool> ((Schedule == OMP_sch_static_chunked
|| Schedule == OMP_sch_static_balanced_chunked || Schedule ==
OMP_ord_static_chunked || Schedule == OMP_dist_sch_static_chunked
) && "expected static chunked schedule") ? void (0) :
__assert_fail ("(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked || Schedule == OMP_ord_static_chunked || Schedule == OMP_dist_sch_static_chunked) && \"expected static chunked schedule\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2769, __extension__
__PRETTY_FUNCTION__))
2767 Schedule == OMP_ord_static_chunked ||(static_cast <bool> ((Schedule == OMP_sch_static_chunked
|| Schedule == OMP_sch_static_balanced_chunked || Schedule ==
OMP_ord_static_chunked || Schedule == OMP_dist_sch_static_chunked
) && "expected static chunked schedule") ? void (0) :
__assert_fail ("(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked || Schedule == OMP_ord_static_chunked || Schedule == OMP_dist_sch_static_chunked) && \"expected static chunked schedule\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2769, __extension__
__PRETTY_FUNCTION__))
2768 Schedule == OMP_dist_sch_static_chunked) &&(static_cast <bool> ((Schedule == OMP_sch_static_chunked
|| Schedule == OMP_sch_static_balanced_chunked || Schedule ==
OMP_ord_static_chunked || Schedule == OMP_dist_sch_static_chunked
) && "expected static chunked schedule") ? void (0) :
__assert_fail ("(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked || Schedule == OMP_ord_static_chunked || Schedule == OMP_dist_sch_static_chunked) && \"expected static chunked schedule\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2769, __extension__
__PRETTY_FUNCTION__))
2769 "expected static chunked schedule")(static_cast <bool> ((Schedule == OMP_sch_static_chunked
|| Schedule == OMP_sch_static_balanced_chunked || Schedule ==
OMP_ord_static_chunked || Schedule == OMP_dist_sch_static_chunked
) && "expected static chunked schedule") ? void (0) :
__assert_fail ("(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static_balanced_chunked || Schedule == OMP_ord_static_chunked || Schedule == OMP_dist_sch_static_chunked) && \"expected static chunked schedule\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2769, __extension__
__PRETTY_FUNCTION__))
;
2770 }
2771 llvm::Value *Args[] = {
2772 UpdateLocation,
2773 ThreadId,
2774 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
2775 M2)), // Schedule type
2776 Values.IL.getPointer(), // &isLastIter
2777 Values.LB.getPointer(), // &LB
2778 Values.UB.getPointer(), // &UB
2779 Values.ST.getPointer(), // &Stride
2780 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
2781 Chunk // Chunk
2782 };
2783 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
2784}
2785
2786void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
2787 SourceLocation Loc,
2788 OpenMPDirectiveKind DKind,
2789 const OpenMPScheduleTy &ScheduleKind,
2790 const StaticRTInput &Values) {
2791 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
2792 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
2793 assert(isOpenMPWorksharingDirective(DKind) &&(static_cast <bool> (isOpenMPWorksharingDirective(DKind
) && "Expected loop-based or sections-based directive."
) ? void (0) : __assert_fail ("isOpenMPWorksharingDirective(DKind) && \"Expected loop-based or sections-based directive.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2794, __extension__
__PRETTY_FUNCTION__))
2794 "Expected loop-based or sections-based directive.")(static_cast <bool> (isOpenMPWorksharingDirective(DKind
) && "Expected loop-based or sections-based directive."
) ? void (0) : __assert_fail ("isOpenMPWorksharingDirective(DKind) && \"Expected loop-based or sections-based directive.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2794, __extension__
__PRETTY_FUNCTION__))
;
2795 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
2796 isOpenMPLoopDirective(DKind)
2797 ? OMP_IDENT_WORK_LOOP
2798 : OMP_IDENT_WORK_SECTIONS);
2799 llvm::Value *ThreadId = getThreadID(CGF, Loc);
2800 llvm::FunctionCallee StaticInitFunction =
2801 createForStaticInitFunction(Values.IVSize, Values.IVSigned, false);
2802 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
2803 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
2804 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
2805}
2806
2807void CGOpenMPRuntime::emitDistributeStaticInit(
2808 CodeGenFunction &CGF, SourceLocation Loc,
2809 OpenMPDistScheduleClauseKind SchedKind,
2810 const CGOpenMPRuntime::StaticRTInput &Values) {
2811 OpenMPSchedType ScheduleNum =
2812 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
2813 llvm::Value *UpdatedLocation =
2814 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
2815 llvm::Value *ThreadId = getThreadID(CGF, Loc);
2816 llvm::FunctionCallee StaticInitFunction;
2817 bool isGPUDistribute =
2818 CGM.getLangOpts().OpenMPIsDevice &&
2819 (CGM.getTriple().isAMDGCN() || CGM.getTriple().isNVPTX());
2820 StaticInitFunction = createForStaticInitFunction(
2821 Values.IVSize, Values.IVSigned, isGPUDistribute);
2822
2823 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
2824 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
2825 OMPC_SCHEDULE_MODIFIER_unknown, Values);
2826}
2827
2828void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
2829 SourceLocation Loc,
2830 OpenMPDirectiveKind DKind) {
2831 if (!CGF.HaveInsertPoint())
2832 return;
2833 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
2834 llvm::Value *Args[] = {
2835 emitUpdateLocation(CGF, Loc,
2836 isOpenMPDistributeDirective(DKind)
2837 ? OMP_IDENT_WORK_DISTRIBUTE
2838 : isOpenMPLoopDirective(DKind)
2839 ? OMP_IDENT_WORK_LOOP
2840 : OMP_IDENT_WORK_SECTIONS),
2841 getThreadID(CGF, Loc)};
2842 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
2843 if (isOpenMPDistributeDirective(DKind) && CGM.getLangOpts().OpenMPIsDevice &&
2844 (CGM.getTriple().isAMDGCN() || CGM.getTriple().isNVPTX()))
2845 CGF.EmitRuntimeCall(
2846 OMPBuilder.getOrCreateRuntimeFunction(
2847 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2848 Args);
2849 else
2850 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2851 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2852 Args);
2853}
2854
2855void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
2856 SourceLocation Loc,
2857 unsigned IVSize,
2858 bool IVSigned) {
2859 if (!CGF.HaveInsertPoint())
2860 return;
2861 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
2862 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2863 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
2864}
2865
2866llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
2867 SourceLocation Loc, unsigned IVSize,
2868 bool IVSigned, Address IL,
2869 Address LB, Address UB,
2870 Address ST) {
2871 // Call __kmpc_dispatch_next(
2872 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2873 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2874 // kmp_int[32|64] *p_stride);
2875 llvm::Value *Args[] = {
2876 emitUpdateLocation(CGF, Loc),
2877 getThreadID(CGF, Loc),
2878 IL.getPointer(), // &isLastIter
2879 LB.getPointer(), // &Lower
2880 UB.getPointer(), // &Upper
2881 ST.getPointer() // &Stride
2882 };
2883 llvm::Value *Call =
2884 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
2885 return CGF.EmitScalarConversion(
2886 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
2887 CGF.getContext().BoolTy, Loc);
2888}
2889
2890void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
2891 llvm::Value *NumThreads,
2892 SourceLocation Loc) {
2893 if (!CGF.HaveInsertPoint())
2894 return;
2895 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
2896 llvm::Value *Args[] = {
2897 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2898 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
2899 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2900 CGM.getModule(), OMPRTL___kmpc_push_num_threads),
2901 Args);
2902}
2903
2904void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
2905 ProcBindKind ProcBind,
2906 SourceLocation Loc) {
2907 if (!CGF.HaveInsertPoint())
2908 return;
2909 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value.")(static_cast <bool> (ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.") ? void (0) : __assert_fail (
"ProcBind != OMP_PROC_BIND_unknown && \"Unsupported proc_bind value.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 2909, __extension__
__PRETTY_FUNCTION__))
;
2910 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
2911 llvm::Value *Args[] = {
2912 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2913 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)};
2914 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2915 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2916 Args);
2917}
2918
2919void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
2920 SourceLocation Loc, llvm::AtomicOrdering AO) {
2921 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
2922 OMPBuilder.createFlush(CGF.Builder);
2923 } else {
2924 if (!CGF.HaveInsertPoint())
2925 return;
2926 // Build call void __kmpc_flush(ident_t *loc)
2927 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2928 CGM.getModule(), OMPRTL___kmpc_flush),
2929 emitUpdateLocation(CGF, Loc));
2930 }
2931}
2932
2933namespace {
2934/// Indexes of fields for type kmp_task_t.
2935enum KmpTaskTFields {
2936 /// List of shared variables.
2937 KmpTaskTShareds,
2938 /// Task routine.
2939 KmpTaskTRoutine,
2940 /// Partition id for the untied tasks.
2941 KmpTaskTPartId,
2942 /// Function with call of destructors for private variables.
2943 Data1,
2944 /// Task priority.
2945 Data2,
2946 /// (Taskloops only) Lower bound.
2947 KmpTaskTLowerBound,
2948 /// (Taskloops only) Upper bound.
2949 KmpTaskTUpperBound,
2950 /// (Taskloops only) Stride.
2951 KmpTaskTStride,
2952 /// (Taskloops only) Is last iteration flag.
2953 KmpTaskTLastIter,
2954 /// (Taskloops only) Reduction data.
2955 KmpTaskTReductions,
2956};
2957} // anonymous namespace
2958
2959void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
2960 // If we are in simd mode or there are no entries, we don't need to do
2961 // anything.
2962 if (CGM.getLangOpts().OpenMPSimd || OMPBuilder.OffloadInfoManager.empty())
2963 return;
2964
2965 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2966 [this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2967 const llvm::TargetRegionEntryInfo &EntryInfo) -> void {
2968 SourceLocation Loc;
2969 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2970 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
2971 E = CGM.getContext().getSourceManager().fileinfo_end();
2972 I != E; ++I) {
2973 if (I->getFirst()->getUniqueID().getDevice() == EntryInfo.DeviceID &&
2974 I->getFirst()->getUniqueID().getFile() == EntryInfo.FileID) {
2975 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
2976 I->getFirst(), EntryInfo.Line, 1);
2977 break;
2978 }
2979 }
2980 }
2981 switch (Kind) {
2982 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2983 unsigned DiagID = CGM.getDiags().getCustomDiagID(
2984 DiagnosticsEngine::Error, "Offloading entry for target region in "
2985 "%0 is incorrect: either the "
2986 "address or the ID is invalid.");
2987 CGM.getDiags().Report(Loc, DiagID) << EntryInfo.ParentName;
2988 } break;
2989 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2990 unsigned DiagID = CGM.getDiags().getCustomDiagID(
2991 DiagnosticsEngine::Error, "Offloading entry for declare target "
2992 "variable %0 is incorrect: the "
2993 "address is invalid.");
2994 CGM.getDiags().Report(Loc, DiagID) << EntryInfo.ParentName;
2995 } break;
2996 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2997 unsigned DiagID = CGM.getDiags().getCustomDiagID(
2998 DiagnosticsEngine::Error,
2999 "Offloading entry for declare target variable is incorrect: the "
3000 "address is invalid.");
3001 CGM.getDiags().Report(DiagID);
3002 } break;
3003 }
3004 };
3005
3006 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
3007}
3008
3009/// Loads all the offload entries information from the host IR
3010/// metadata.
3011void CGOpenMPRuntime::loadOffloadInfoMetadata() {
3012 // If we are in target mode, load the metadata from the host IR. This code has
3013 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
3014
3015 if (!CGM.getLangOpts().OpenMPIsDevice)
3016 return;
3017
3018 if (CGM.getLangOpts().OMPHostIRFile.empty())
3019 return;
3020
3021 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
3022 if (auto EC = Buf.getError()) {
3023 CGM.getDiags().Report(diag::err_cannot_open_file)
3024 << CGM.getLangOpts().OMPHostIRFile << EC.message();
3025 return;
3026 }
3027
3028 llvm::LLVMContext C;
3029 auto ME = expectedToErrorOrAndEmitErrors(
3030 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
3031
3032 if (auto EC = ME.getError()) {
3033 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3034 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
3035 CGM.getDiags().Report(DiagID)
3036 << CGM.getLangOpts().OMPHostIRFile << EC.message();
3037 return;
3038 }
3039
3040 OMPBuilder.loadOffloadInfoMetadata(*ME.get());
3041}
3042
3043void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
3044 if (!KmpRoutineEntryPtrTy) {
3045 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
3046 ASTContext &C = CGM.getContext();
3047 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
3048 FunctionProtoType::ExtProtoInfo EPI;
3049 KmpRoutineEntryPtrQTy = C.getPointerType(
3050 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3051 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
3052 }
3053}
3054
3055namespace {
3056struct PrivateHelpersTy {
3057 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original,
3058 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit)
3059 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3060 PrivateElemInit(PrivateElemInit) {}
3061 PrivateHelpersTy(const VarDecl *Original) : Original(Original) {}
3062 const Expr *OriginalRef = nullptr;
3063 const VarDecl *Original = nullptr;
3064 const VarDecl *PrivateCopy = nullptr;
3065 const VarDecl *PrivateElemInit = nullptr;
3066 bool isLocalPrivate() const {
3067 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3068 }
3069};
3070typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
3071} // anonymous namespace
3072
3073static bool isAllocatableDecl(const VarDecl *VD) {
3074 const VarDecl *CVD = VD->getCanonicalDecl();
3075 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
3076 return false;
3077 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
3078 // Use the default allocation.
3079 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
3080 !AA->getAllocator());
3081}
3082
3083static RecordDecl *
3084createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
3085 if (!Privates.empty()) {
3086 ASTContext &C = CGM.getContext();
3087 // Build struct .kmp_privates_t. {
3088 // /* private vars */
3089 // };
3090 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
3091 RD->startDefinition();
3092 for (const auto &Pair : Privates) {
3093 const VarDecl *VD = Pair.second.Original;
3094 QualType Type = VD->getType().getNonReferenceType();
3095 // If the private variable is a local variable with lvalue ref type,
3096 // allocate the pointer instead of the pointee type.
3097 if (Pair.second.isLocalPrivate()) {
3098 if (VD->getType()->isLValueReferenceType())
3099 Type = C.getPointerType(Type);
3100 if (isAllocatableDecl(VD))
3101 Type = C.getPointerType(Type);
3102 }
3103 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
3104 if (VD->hasAttrs()) {
3105 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
3106 E(VD->getAttrs().end());
3107 I != E; ++I)
3108 FD->addAttr(*I);
3109 }
3110 }
3111 RD->completeDefinition();
3112 return RD;
3113 }
3114 return nullptr;
3115}
3116
3117static RecordDecl *
3118createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
3119 QualType KmpInt32Ty,
3120 QualType KmpRoutineEntryPointerQTy) {
3121 ASTContext &C = CGM.getContext();
3122 // Build struct kmp_task_t {
3123 // void * shareds;
3124 // kmp_routine_entry_t routine;
3125 // kmp_int32 part_id;
3126 // kmp_cmplrdata_t data1;
3127 // kmp_cmplrdata_t data2;
3128 // For taskloops additional fields:
3129 // kmp_uint64 lb;
3130 // kmp_uint64 ub;
3131 // kmp_int64 st;
3132 // kmp_int32 liter;
3133 // void * reductions;
3134 // };
3135 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
3136 UD->startDefinition();
3137 addFieldToRecordDecl(C, UD, KmpInt32Ty);
3138 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
3139 UD->completeDefinition();
3140 QualType KmpCmplrdataTy = C.getRecordType(UD);
3141 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
3142 RD->startDefinition();
3143 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3144 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
3145 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3146 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
3147 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
3148 if (isOpenMPTaskLoopDirective(Kind)) {
3149 QualType KmpUInt64Ty =
3150 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
3151 QualType KmpInt64Ty =
3152 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
3153 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
3154 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
3155 addFieldToRecordDecl(C, RD, KmpInt64Ty);
3156 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3157 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3158 }
3159 RD->completeDefinition();
3160 return RD;
3161}
3162
3163static RecordDecl *
3164createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
3165 ArrayRef<PrivateDataTy> Privates) {
3166 ASTContext &C = CGM.getContext();
3167 // Build struct kmp_task_t_with_privates {
3168 // kmp_task_t task_data;
3169 // .kmp_privates_t. privates;
3170 // };
3171 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
3172 RD->startDefinition();
3173 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
3174 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
3175 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
3176 RD->completeDefinition();
3177 return RD;
3178}
3179
3180/// Emit a proxy function which accepts kmp_task_t as the second
3181/// argument.
3182/// \code
3183/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
3184/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
3185/// For taskloops:
3186/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
3187/// tt->reductions, tt->shareds);
3188/// return 0;
3189/// }
3190/// \endcode
3191static llvm::Function *
3192emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
3193 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
3194 QualType KmpTaskTWithPrivatesPtrQTy,
3195 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
3196 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3197 llvm::Value *TaskPrivatesMap) {
3198 ASTContext &C = CGM.getContext();
3199 FunctionArgList Args;
3200 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
3201 ImplicitParamDecl::Other);
3202 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3203 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
3204 ImplicitParamDecl::Other);
3205 Args.push_back(&GtidArg);
3206 Args.push_back(&TaskTypeArg);
3207 const auto &TaskEntryFnInfo =
3208 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
3209 llvm::FunctionType *TaskEntryTy =
3210 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
3211 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
3212 auto *TaskEntry = llvm::Function::Create(
3213 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
3214 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
3215 TaskEntry->setDoesNotRecurse();
3216 CodeGenFunction CGF(CGM);
3217 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
3218 Loc, Loc);
3219
3220 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
3221 // tt,
3222 // For taskloops:
3223 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
3224 // tt->task_data.shareds);
3225 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
3226 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
3227 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3228 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3229 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3230 const auto *KmpTaskTWithPrivatesQTyRD =
3231 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3232 LValue Base =
3233 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
3234 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
3235 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3236 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
3237 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3238
3239 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3240 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
3241 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3242 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
3243 CGF.ConvertTypeForMem(SharedsPtrTy));
3244
3245 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3246 llvm::Value *PrivatesParam;
3247 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3248 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
3249 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3250 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy);
3251 } else {
3252 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3253 }
3254
3255 llvm::Value *CommonArgs[] = {
3256 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3257 CGF.Builder
3258 .CreatePointerBitCastOrAddrSpaceCast(TDBase.getAddress(CGF),
3259 CGF.VoidPtrTy, CGF.Int8Ty)
3260 .getPointer()};
3261 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
3262 std::end(CommonArgs));
3263 if (isOpenMPTaskLoopDirective(Kind)) {
3264 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3265 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
3266 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
3267 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3268 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
3269 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
3270 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3271 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
3272 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
3273 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3274 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
3275 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
3276 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3277 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
3278 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
3279 CallArgs.push_back(LBParam);
3280 CallArgs.push_back(UBParam);
3281 CallArgs.push_back(StParam);
3282 CallArgs.push_back(LIParam);
3283 CallArgs.push_back(RParam);
3284 }
3285 CallArgs.push_back(SharedsParam);
3286
3287 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
3288 CallArgs);
3289 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
3290 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
3291 CGF.FinishFunction();
3292 return TaskEntry;
3293}
3294
3295static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
3296 SourceLocation Loc,
3297 QualType KmpInt32Ty,
3298 QualType KmpTaskTWithPrivatesPtrQTy,
3299 QualType KmpTaskTWithPrivatesQTy) {
3300 ASTContext &C = CGM.getContext();
3301 FunctionArgList Args;
3302 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
3303 ImplicitParamDecl::Other);
3304 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3305 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
3306 ImplicitParamDecl::Other);
3307 Args.push_back(&GtidArg);
3308 Args.push_back(&TaskTypeArg);
3309 const auto &DestructorFnInfo =
3310 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
3311 llvm::FunctionType *DestructorFnTy =
3312 CGM.getTypes().GetFunctionType(DestructorFnInfo);
3313 std::string Name =
3314 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
3315 auto *DestructorFn =
3316 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3317 Name, &CGM.getModule());
3318 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
3319 DestructorFnInfo);
3320 DestructorFn->setDoesNotRecurse();
3321 CodeGenFunction CGF(CGM);
3322 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
3323 Args, Loc, Loc);
3324
3325 LValue Base = CGF.EmitLoadOfPointerLValue(
3326 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3327 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3328 const auto *KmpTaskTWithPrivatesQTyRD =
3329 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3330 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3331 Base = CGF.EmitLValueForField(Base, *FI);
3332 for (const auto *Field :
3333 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3334 if (QualType::DestructionKind DtorKind =
3335 Field->getType().isDestructedType()) {
3336 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
3337 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType());
3338 }
3339 }
3340 CGF.FinishFunction();
3341 return DestructorFn;
3342}
3343
3344/// Emit a privates mapping function for correct handling of private and
3345/// firstprivate variables.
3346/// \code
3347/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
3348/// **noalias priv1,..., <tyn> **noalias privn) {
3349/// *priv1 = &.privates.priv1;
3350/// ...;
3351/// *privn = &.privates.privn;
3352/// }
3353/// \endcode
3354static llvm::Value *
3355emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
3356 const OMPTaskDataTy &Data, QualType PrivatesQTy,
3357 ArrayRef<PrivateDataTy> Privates) {
3358 ASTContext &C = CGM.getContext();
3359 FunctionArgList Args;
3360 ImplicitParamDecl TaskPrivatesArg(
3361 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3362 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3363 ImplicitParamDecl::Other);
3364 Args.push_back(&TaskPrivatesArg);
3365 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, unsigned> PrivateVarsPos;
3366 unsigned Counter = 1;
3367 for (const Expr *E : Data.PrivateVars) {
3368 Args.push_back(ImplicitParamDecl::Create(
3369 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3370 C.getPointerType(C.getPointerType(E->getType()))
3371 .withConst()
3372 .withRestrict(),
3373 ImplicitParamDecl::Other));
3374 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3375 PrivateVarsPos[VD] = Counter;
3376 ++Counter;
3377 }
3378 for (const Expr *E : Data.FirstprivateVars) {
3379 Args.push_back(ImplicitParamDecl::Create(
3380 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3381 C.getPointerType(C.getPointerType(E->getType()))
3382 .withConst()
3383 .withRestrict(),
3384 ImplicitParamDecl::Other));
3385 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3386 PrivateVarsPos[VD] = Counter;
3387 ++Counter;
3388 }
3389 for (const Expr *E : Data.LastprivateVars) {
3390 Args.push_back(ImplicitParamDecl::Create(
3391 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3392 C.getPointerType(C.getPointerType(E->getType()))
3393 .withConst()
3394 .withRestrict(),
3395 ImplicitParamDecl::Other));
3396 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3397 PrivateVarsPos[VD] = Counter;
3398 ++Counter;
3399 }
3400 for (const VarDecl *VD : Data.PrivateLocals) {
3401 QualType Ty = VD->getType().getNonReferenceType();
3402 if (VD->getType()->isLValueReferenceType())
3403 Ty = C.getPointerType(Ty);
3404 if (isAllocatableDecl(VD))
3405 Ty = C.getPointerType(Ty);
3406 Args.push_back(ImplicitParamDecl::Create(
3407 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3408 C.getPointerType(C.getPointerType(Ty)).withConst().withRestrict(),
3409 ImplicitParamDecl::Other));
3410 PrivateVarsPos[VD] = Counter;
3411 ++Counter;
3412 }
3413 const auto &TaskPrivatesMapFnInfo =
3414 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
3415 llvm::FunctionType *TaskPrivatesMapTy =
3416 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
3417 std::string Name =
3418 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
3419 auto *TaskPrivatesMap = llvm::Function::Create(
3420 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3421 &CGM.getModule());
3422 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
3423 TaskPrivatesMapFnInfo);
3424 if (CGM.getLangOpts().Optimize) {
3425 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3426 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3427 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3428 }
3429 CodeGenFunction CGF(CGM);
3430 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
3431 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3432
3433 // *privi = &.privates.privi;
3434 LValue Base = CGF.EmitLoadOfPointerLValue(
3435 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
3436 TaskPrivatesArg.getType()->castAs<PointerType>());
3437 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
3438 Counter = 0;
3439 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
3440 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
3441 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
3442 LValue RefLVal =
3443 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
3444 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
3445 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>());
3446 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal);
3447 ++Counter;
3448 }
3449 CGF.FinishFunction();
3450 return TaskPrivatesMap;
3451}
3452
3453/// Emit initialization for private variables in task-based directives.
3454static void emitPrivatesInit(CodeGenFunction &CGF,
3455 const OMPExecutableDirective &D,
3456 Address KmpTaskSharedsPtr, LValue TDBase,
3457 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
3458 QualType SharedsTy, QualType SharedsPtrTy,
3459 const OMPTaskDataTy &Data,
3460 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
3461 ASTContext &C = CGF.getContext();
3462 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3463 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
3464 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
3465 ? OMPD_taskloop
3466 : OMPD_task;
3467 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
3468 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
3469 LValue SrcBase;
3470 bool IsTargetTask =
3471 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
3472 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
3473 // For target-based directives skip 4 firstprivate arrays BasePointersArray,
3474 // PointersArray, SizesArray, and MappersArray. The original variables for
3475 // these arrays are not captured and we get their addresses explicitly.
3476 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) ||
3477 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
3478 SrcBase = CGF.MakeAddrLValue(
3479 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3480 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy),
3481 CGF.ConvertTypeForMem(SharedsTy)),
3482 SharedsTy);
3483 }
3484 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
3485 for (const PrivateDataTy &Pair : Privates) {
3486 // Do not initialize private locals.
3487 if (Pair.second.isLocalPrivate()) {
3488 ++FI;
3489 continue;
3490 }
3491 const VarDecl *VD = Pair.second.PrivateCopy;
3492 const Expr *Init = VD->getAnyInitializer();
3493 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
3494 !CGF.isTrivialInitializer(Init)))) {
3495 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
3496 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
3497 const VarDecl *OriginalVD = Pair.second.Original;
3498 // Check if the variable is the target-based BasePointersArray,
3499 // PointersArray, SizesArray, or MappersArray.
3500 LValue SharedRefLValue;
3501 QualType Type = PrivateLValue.getType();
3502 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
3503 if (IsTargetTask && !SharedField) {
3504 assert(isa<ImplicitParamDecl>(OriginalVD) &&(static_cast <bool> (isa<ImplicitParamDecl>(OriginalVD
) && isa<CapturedDecl>(OriginalVD->getDeclContext
()) && cast<CapturedDecl>(OriginalVD->getDeclContext
()) ->getNumParams() == 0 && isa<TranslationUnitDecl
>( cast<CapturedDecl>(OriginalVD->getDeclContext(
)) ->getDeclContext()) && "Expected artificial target data variable."
) ? void (0) : __assert_fail ("isa<ImplicitParamDecl>(OriginalVD) && isa<CapturedDecl>(OriginalVD->getDeclContext()) && cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getNumParams() == 0 && isa<TranslationUnitDecl>( cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getDeclContext()) && \"Expected artificial target data variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3511, __extension__
__PRETTY_FUNCTION__))
3505 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&(static_cast <bool> (isa<ImplicitParamDecl>(OriginalVD
) && isa<CapturedDecl>(OriginalVD->getDeclContext
()) && cast<CapturedDecl>(OriginalVD->getDeclContext
()) ->getNumParams() == 0 && isa<TranslationUnitDecl
>( cast<CapturedDecl>(OriginalVD->getDeclContext(
)) ->getDeclContext()) && "Expected artificial target data variable."
) ? void (0) : __assert_fail ("isa<ImplicitParamDecl>(OriginalVD) && isa<CapturedDecl>(OriginalVD->getDeclContext()) && cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getNumParams() == 0 && isa<TranslationUnitDecl>( cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getDeclContext()) && \"Expected artificial target data variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3511, __extension__
__PRETTY_FUNCTION__))
3506 cast<CapturedDecl>(OriginalVD->getDeclContext())(static_cast <bool> (isa<ImplicitParamDecl>(OriginalVD
) && isa<CapturedDecl>(OriginalVD->getDeclContext
()) && cast<CapturedDecl>(OriginalVD->getDeclContext
()) ->getNumParams() == 0 && isa<TranslationUnitDecl
>( cast<CapturedDecl>(OriginalVD->getDeclContext(
)) ->getDeclContext()) && "Expected artificial target data variable."
) ? void (0) : __assert_fail ("isa<ImplicitParamDecl>(OriginalVD) && isa<CapturedDecl>(OriginalVD->getDeclContext()) && cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getNumParams() == 0 && isa<TranslationUnitDecl>( cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getDeclContext()) && \"Expected artificial target data variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3511, __extension__
__PRETTY_FUNCTION__))
3507 ->getNumParams() == 0 &&(static_cast <bool> (isa<ImplicitParamDecl>(OriginalVD
) && isa<CapturedDecl>(OriginalVD->getDeclContext
()) && cast<CapturedDecl>(OriginalVD->getDeclContext
()) ->getNumParams() == 0 && isa<TranslationUnitDecl
>( cast<CapturedDecl>(OriginalVD->getDeclContext(
)) ->getDeclContext()) && "Expected artificial target data variable."
) ? void (0) : __assert_fail ("isa<ImplicitParamDecl>(OriginalVD) && isa<CapturedDecl>(OriginalVD->getDeclContext()) && cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getNumParams() == 0 && isa<TranslationUnitDecl>( cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getDeclContext()) && \"Expected artificial target data variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3511, __extension__
__PRETTY_FUNCTION__))
3508 isa<TranslationUnitDecl>((static_cast <bool> (isa<ImplicitParamDecl>(OriginalVD
) && isa<CapturedDecl>(OriginalVD->getDeclContext
()) && cast<CapturedDecl>(OriginalVD->getDeclContext
()) ->getNumParams() == 0 && isa<TranslationUnitDecl
>( cast<CapturedDecl>(OriginalVD->getDeclContext(
)) ->getDeclContext()) && "Expected artificial target data variable."
) ? void (0) : __assert_fail ("isa<ImplicitParamDecl>(OriginalVD) && isa<CapturedDecl>(OriginalVD->getDeclContext()) && cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getNumParams() == 0 && isa<TranslationUnitDecl>( cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getDeclContext()) && \"Expected artificial target data variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3511, __extension__
__PRETTY_FUNCTION__))
3509 cast<CapturedDecl>(OriginalVD->getDeclContext())(static_cast <bool> (isa<ImplicitParamDecl>(OriginalVD
) && isa<CapturedDecl>(OriginalVD->getDeclContext
()) && cast<CapturedDecl>(OriginalVD->getDeclContext
()) ->getNumParams() == 0 && isa<TranslationUnitDecl
>( cast<CapturedDecl>(OriginalVD->getDeclContext(
)) ->getDeclContext()) && "Expected artificial target data variable."
) ? void (0) : __assert_fail ("isa<ImplicitParamDecl>(OriginalVD) && isa<CapturedDecl>(OriginalVD->getDeclContext()) && cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getNumParams() == 0 && isa<TranslationUnitDecl>( cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getDeclContext()) && \"Expected artificial target data variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3511, __extension__
__PRETTY_FUNCTION__))
3510 ->getDeclContext()) &&(static_cast <bool> (isa<ImplicitParamDecl>(OriginalVD
) && isa<CapturedDecl>(OriginalVD->getDeclContext
()) && cast<CapturedDecl>(OriginalVD->getDeclContext
()) ->getNumParams() == 0 && isa<TranslationUnitDecl
>( cast<CapturedDecl>(OriginalVD->getDeclContext(
)) ->getDeclContext()) && "Expected artificial target data variable."
) ? void (0) : __assert_fail ("isa<ImplicitParamDecl>(OriginalVD) && isa<CapturedDecl>(OriginalVD->getDeclContext()) && cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getNumParams() == 0 && isa<TranslationUnitDecl>( cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getDeclContext()) && \"Expected artificial target data variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3511, __extension__
__PRETTY_FUNCTION__))
3511 "Expected artificial target data variable.")(static_cast <bool> (isa<ImplicitParamDecl>(OriginalVD
) && isa<CapturedDecl>(OriginalVD->getDeclContext
()) && cast<CapturedDecl>(OriginalVD->getDeclContext
()) ->getNumParams() == 0 && isa<TranslationUnitDecl
>( cast<CapturedDecl>(OriginalVD->getDeclContext(
)) ->getDeclContext()) && "Expected artificial target data variable."
) ? void (0) : __assert_fail ("isa<ImplicitParamDecl>(OriginalVD) && isa<CapturedDecl>(OriginalVD->getDeclContext()) && cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getNumParams() == 0 && isa<TranslationUnitDecl>( cast<CapturedDecl>(OriginalVD->getDeclContext()) ->getDeclContext()) && \"Expected artificial target data variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3511, __extension__
__PRETTY_FUNCTION__))
;
3512 SharedRefLValue =
3513 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
3514 } else if (ForDup) {
3515 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
3516 SharedRefLValue = CGF.MakeAddrLValue(
3517 SharedRefLValue.getAddress(CGF).withAlignment(
3518 C.getDeclAlign(OriginalVD)),
3519 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
3520 SharedRefLValue.getTBAAInfo());
3521 } else if (CGF.LambdaCaptureFields.count(
3522 Pair.second.Original->getCanonicalDecl()) > 0 ||
3523 isa_and_nonnull<BlockDecl>(CGF.CurCodeDecl)) {
3524 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef);
3525 } else {
3526 // Processing for implicitly captured variables.
3527 InlinedOpenMPRegionRAII Region(
3528 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown,
3529 /*HasCancel=*/false, /*NoInheritance=*/true);
3530 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef);
3531 }
3532 if (Type->isArrayType()) {
3533 // Initialize firstprivate array.
3534 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
3535 // Perform simple memcpy.
3536 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
3537 } else {
3538 // Initialize firstprivate array using element-by-element
3539 // initialization.
3540 CGF.EmitOMPAggregateAssign(
3541 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF),
3542 Type,
3543 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
3544 Address SrcElement) {
3545 // Clean up any temporaries needed by the initialization.
3546 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3547 InitScope.addPrivate(Elem, SrcElement);
3548 (void)InitScope.Privatize();
3549 // Emit initialization for single element.
3550 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3551 CGF, &CapturesInfo);
3552 CGF.EmitAnyExprToMem(Init, DestElement,
3553 Init->getType().getQualifiers(),
3554 /*IsInitializer=*/false);
3555 });
3556 }
3557 } else {
3558 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3559 InitScope.addPrivate(Elem, SharedRefLValue.getAddress(CGF));
3560 (void)InitScope.Privatize();
3561 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
3562 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
3563 /*capturedByInit=*/false);
3564 }
3565 } else {
3566 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
3567 }
3568 }
3569 ++FI;
3570 }
3571}
3572
3573/// Check if duplication function is required for taskloops.
3574static bool checkInitIsRequired(CodeGenFunction &CGF,
3575 ArrayRef<PrivateDataTy> Privates) {
3576 bool InitRequired = false;
3577 for (const PrivateDataTy &Pair : Privates) {
3578 if (Pair.second.isLocalPrivate())
3579 continue;
3580 const VarDecl *VD = Pair.second.PrivateCopy;
3581 const Expr *Init = VD->getAnyInitializer();
3582 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(Init) &&
3583 !CGF.isTrivialInitializer(Init));
3584 if (InitRequired)
3585 break;
3586 }
3587 return InitRequired;
3588}
3589
3590
3591/// Emit task_dup function (for initialization of
3592/// private/firstprivate/lastprivate vars and last_iter flag)
3593/// \code
3594/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
3595/// lastpriv) {
3596/// // setup lastprivate flag
3597/// task_dst->last = lastpriv;
3598/// // could be constructor calls here...
3599/// }
3600/// \endcode
3601static llvm::Value *
3602emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
3603 const OMPExecutableDirective &D,
3604 QualType KmpTaskTWithPrivatesPtrQTy,
3605 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
3606 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
3607 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
3608 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
3609 ASTContext &C = CGM.getContext();
3610 FunctionArgList Args;
3611 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3612 KmpTaskTWithPrivatesPtrQTy,
3613 ImplicitParamDecl::Other);
3614 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3615 KmpTaskTWithPrivatesPtrQTy,
3616 ImplicitParamDecl::Other);
3617 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
3618 ImplicitParamDecl::Other);
3619 Args.push_back(&DstArg);
3620 Args.push_back(&SrcArg);
3621 Args.push_back(&LastprivArg);
3622 const auto &TaskDupFnInfo =
3623 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
3624 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
3625 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
3626 auto *TaskDup = llvm::Function::Create(
3627 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
3628 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
3629 TaskDup->setDoesNotRecurse();
3630 CodeGenFunction CGF(CGM);
3631 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
3632 Loc);
3633
3634 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3635 CGF.GetAddrOfLocalVar(&DstArg),
3636 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3637 // task_dst->liter = lastpriv;
3638 if (WithLastIter) {
3639 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3640 LValue Base = CGF.EmitLValueForField(
3641 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
3642 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
3643 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
3644 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
3645 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
3646 }
3647
3648 // Emit initial values for private copies (if any).
3649 assert(!Privates.empty())(static_cast <bool> (!Privates.empty()) ? void (0) : __assert_fail
("!Privates.empty()", "clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3649, __extension__ __PRETTY_FUNCTION__))
;
3650 Address KmpTaskSharedsPtr = Address::invalid();
3651 if (!Data.FirstprivateVars.empty()) {
3652 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3653 CGF.GetAddrOfLocalVar(&SrcArg),
3654 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3655 LValue Base = CGF.EmitLValueForField(
3656 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
3657 KmpTaskSharedsPtr = Address(
3658 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
3659 Base, *std::next(KmpTaskTQTyRD->field_begin(),
3660 KmpTaskTShareds)),
3661 Loc),
3662 CGF.Int8Ty, CGM.getNaturalTypeAlignment(SharedsTy));
3663 }
3664 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3665 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
3666 CGF.FinishFunction();
3667 return TaskDup;
3668}
3669
3670/// Checks if destructor function is required to be generated.
3671/// \return true if cleanups are required, false otherwise.
3672static bool
3673checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD,
3674 ArrayRef<PrivateDataTy> Privates) {
3675 for (const PrivateDataTy &P : Privates) {
3676 if (P.second.isLocalPrivate())
3677 continue;
3678 QualType Ty = P.second.Original->getType().getNonReferenceType();
3679 if (Ty.isDestructedType())
3680 return true;
3681 }
3682 return false;
3683}
3684
3685namespace {
3686/// Loop generator for OpenMP iterator expression.
3687class OMPIteratorGeneratorScope final
3688 : public CodeGenFunction::OMPPrivateScope {
3689 CodeGenFunction &CGF;
3690 const OMPIteratorExpr *E = nullptr;
3691 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3692 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3693 OMPIteratorGeneratorScope() = delete;
3694 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete;
3695
3696public:
3697 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E)
3698 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3699 if (!E)
3700 return;
3701 SmallVector<llvm::Value *, 4> Uppers;
3702 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
3703 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3704 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3705 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3706 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3707 addPrivate(
3708 HelperData.CounterVD,
3709 CGF.CreateMemTemp(HelperData.CounterVD->getType(), "counter.addr"));
3710 }
3711 Privatize();
3712
3713 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
3714 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3715 LValue CLVal =
3716 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3717 HelperData.CounterVD->getType());
3718 // Counter = 0;
3719 CGF.EmitStoreOfScalar(
3720 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0),
3721 CLVal);
3722 CodeGenFunction::JumpDest &ContDest =
3723 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont"));
3724 CodeGenFunction::JumpDest &ExitDest =
3725 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit"));
3726 // N = <number-of_iterations>;
3727 llvm::Value *N = Uppers[I];
3728 // cont:
3729 // if (Counter < N) goto body; else goto exit;
3730 CGF.EmitBlock(ContDest.getBlock());
3731 auto *CVal =
3732 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3733 llvm::Value *Cmp =
3734 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3735 ? CGF.Builder.CreateICmpSLT(CVal, N)
3736 : CGF.Builder.CreateICmpULT(CVal, N);
3737 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body");
3738 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3739 // body:
3740 CGF.EmitBlock(BodyBB);
3741 // Iteri = Begini + Counter * Stepi;
3742 CGF.EmitIgnoredExpr(HelperData.Update);
3743 }
3744 }
3745 ~OMPIteratorGeneratorScope() {
3746 if (!E)
3747 return;
3748 for (unsigned I = E->numOfIterators(); I > 0; --I) {
3749 // Counter = Counter + 1;
3750 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1);
3751 CGF.EmitIgnoredExpr(HelperData.CounterUpdate);
3752 // goto cont;
3753 CGF.EmitBranchThroughCleanup(ContDests[I - 1]);
3754 // exit:
3755 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1);
3756 }
3757 }
3758};
3759} // namespace
3760
3761static std::pair<llvm::Value *, llvm::Value *>
3762getPointerAndSize(CodeGenFunction &CGF, const Expr *E) {
3763 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3764 llvm::Value *Addr;
3765 if (OASE) {
3766 const Expr *Base = OASE->getBase();
3767 Addr = CGF.EmitScalarExpr(Base);
3768 } else {
3769 Addr = CGF.EmitLValue(E).getPointer(CGF);
3770 }
3771 llvm::Value *SizeVal;
3772 QualType Ty = E->getType();
3773 if (OASE) {
3774 SizeVal = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType());
3775 for (const Expr *SE : OASE->getDimensions()) {
3776 llvm::Value *Sz = CGF.EmitScalarExpr(SE);
3777 Sz = CGF.EmitScalarConversion(
3778 Sz, SE->getType(), CGF.getContext().getSizeType(), SE->getExprLoc());
3779 SizeVal = CGF.Builder.CreateNUWMul(SizeVal, Sz);
3780 }
3781 } else if (const auto *ASE =
3782 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
3783 LValue UpAddrLVal =
3784 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
3785 Address UpAddrAddress = UpAddrLVal.getAddress(CGF);
3786 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32(
3787 UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1);
3788 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy);
3789 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy);
3790 SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
3791 } else {
3792 SizeVal = CGF.getTypeSize(Ty);
3793 }
3794 return std::make_pair(Addr, SizeVal);
3795}
3796
3797/// Builds kmp_depend_info, if it is not built yet, and builds flags type.
3798static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) {
3799 QualType FlagsTy = C.getIntTypeForBitwidth(32, /*Signed=*/false);
3800 if (KmpTaskAffinityInfoTy.isNull()) {
3801 RecordDecl *KmpAffinityInfoRD =
3802 C.buildImplicitRecord("kmp_task_affinity_info_t");
3803 KmpAffinityInfoRD->startDefinition();
3804 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getIntPtrType());
3805 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType());
3806 addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy);
3807 KmpAffinityInfoRD->completeDefinition();
3808 KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD);
3809 }
3810}
3811
3812CGOpenMPRuntime::TaskResultTy
3813CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
3814 const OMPExecutableDirective &D,
3815 llvm::Function *TaskFunction, QualType SharedsTy,
3816 Address Shareds, const OMPTaskDataTy &Data) {
3817 ASTContext &C = CGM.getContext();
3818 llvm::SmallVector<PrivateDataTy, 4> Privates;
3819 // Aggregate privates and sort them by the alignment.
3820 const auto *I = Data.PrivateCopies.begin();
3821 for (const Expr *E : Data.PrivateVars) {
3822 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3823 Privates.emplace_back(
3824 C.getDeclAlign(VD),
3825 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3826 /*PrivateElemInit=*/nullptr));
3827 ++I;
3828 }
3829 I = Data.FirstprivateCopies.begin();
3830 const auto *IElemInitRef = Data.FirstprivateInits.begin();
3831 for (const Expr *E : Data.FirstprivateVars) {
3832 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3833 Privates.emplace_back(
3834 C.getDeclAlign(VD),
3835 PrivateHelpersTy(
3836 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3837 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
3838 ++I;
3839 ++IElemInitRef;
3840 }
3841 I = Data.LastprivateCopies.begin();
3842 for (const Expr *E : Data.LastprivateVars) {
3843 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3844 Privates.emplace_back(
3845 C.getDeclAlign(VD),
3846 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3847 /*PrivateElemInit=*/nullptr));
3848 ++I;
3849 }
3850 for (const VarDecl *VD : Data.PrivateLocals) {
3851 if (isAllocatableDecl(VD))
3852 Privates.emplace_back(CGM.getPointerAlign(), PrivateHelpersTy(VD));
3853 else
3854 Privates.emplace_back(C.getDeclAlign(VD), PrivateHelpersTy(VD));
3855 }
3856 llvm::stable_sort(Privates,
3857 [](const PrivateDataTy &L, const PrivateDataTy &R) {
3858 return L.first > R.first;
3859 });
3860 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
3861 // Build type kmp_routine_entry_t (if not built yet).
3862 emitKmpRoutineEntryT(KmpInt32Ty);
3863 // Build type kmp_task_t (if not built yet).
3864 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
3865 if (SavedKmpTaskloopTQTy.isNull()) {
3866 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
3867 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
3868 }
3869 KmpTaskTQTy = SavedKmpTaskloopTQTy;
3870 } else {
3871 assert((D.getDirectiveKind() == OMPD_task ||(static_cast <bool> ((D.getDirectiveKind() == OMPD_task
|| isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
isOpenMPTargetDataManagementDirective(D.getDirectiveKind()))
&& "Expected taskloop, task or target directive") ? void
(0) : __assert_fail ("(D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && \"Expected taskloop, task or target directive\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3874, __extension__
__PRETTY_FUNCTION__))
3872 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||(static_cast <bool> ((D.getDirectiveKind() == OMPD_task
|| isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
isOpenMPTargetDataManagementDirective(D.getDirectiveKind()))
&& "Expected taskloop, task or target directive") ? void
(0) : __assert_fail ("(D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && \"Expected taskloop, task or target directive\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3874, __extension__
__PRETTY_FUNCTION__))
3873 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&(static_cast <bool> ((D.getDirectiveKind() == OMPD_task
|| isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
isOpenMPTargetDataManagementDirective(D.getDirectiveKind()))
&& "Expected taskloop, task or target directive") ? void
(0) : __assert_fail ("(D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && \"Expected taskloop, task or target directive\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3874, __extension__
__PRETTY_FUNCTION__))
3874 "Expected taskloop, task or target directive")(static_cast <bool> ((D.getDirectiveKind() == OMPD_task
|| isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
isOpenMPTargetDataManagementDirective(D.getDirectiveKind()))
&& "Expected taskloop, task or target directive") ? void
(0) : __assert_fail ("(D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && \"Expected taskloop, task or target directive\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 3874, __extension__
__PRETTY_FUNCTION__))
;
3875 if (SavedKmpTaskTQTy.isNull()) {
3876 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
3877 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
3878 }
3879 KmpTaskTQTy = SavedKmpTaskTQTy;
3880 }
3881 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
3882 // Build particular struct kmp_task_t for the given task.
3883 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3884 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
3885 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
3886 QualType KmpTaskTWithPrivatesPtrQTy =
3887 C.getPointerType(KmpTaskTWithPrivatesQTy);
3888 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
3889 llvm::Type *KmpTaskTWithPrivatesPtrTy =
3890 KmpTaskTWithPrivatesTy->getPointerTo();
3891 llvm::Value *KmpTaskTWithPrivatesTySize =
3892 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
3893 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
3894
3895 // Emit initial values for private copies (if any).
3896 llvm::Value *TaskPrivatesMap = nullptr;
3897 llvm::Type *TaskPrivatesMapTy =
3898 std::next(TaskFunction->arg_begin(), 3)->getType();
3899 if (!Privates.empty()) {
3900 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3901 TaskPrivatesMap =
3902 emitTaskPrivateMappingFunction(CGM, Loc, Data, FI->getType(), Privates);
3903 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3904 TaskPrivatesMap, TaskPrivatesMapTy);
3905 } else {
3906 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3907 cast<llvm::PointerType>(TaskPrivatesMapTy));
3908 }
3909 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
3910 // kmp_task_t *tt);
3911 llvm::Function *TaskEntry = emitProxyTaskFunction(
3912 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3913 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3914 TaskPrivatesMap);
3915
3916 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
3917 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
3918 // kmp_routine_entry_t *task_entry);
3919 // Task flags. Format is taken from
3920 // https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h,
3921 // description of kmp_tasking_flags struct.
3922 enum {
3923 TiedFlag = 0x1,
3924 FinalFlag = 0x2,
3925 DestructorsFlag = 0x8,
3926 PriorityFlag = 0x20,
3927 DetachableFlag = 0x40,
3928 };
3929 unsigned Flags = Data.Tied ? TiedFlag : 0;
3930 bool NeedsCleanup = false;
3931 if (!Privates.empty()) {
3932 NeedsCleanup =
3933 checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD, Privates);
3934 if (NeedsCleanup)
3935 Flags = Flags | DestructorsFlag;
3936 }
3937 if (Data.Priority.getInt())
3938 Flags = Flags | PriorityFlag;
3939 if (D.hasClausesOfKind<OMPDetachClause>())
3940 Flags = Flags | DetachableFlag;
3941 llvm::Value *TaskFlags =
3942 Data.Final.getPointer()
3943 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
3944 CGF.Builder.getInt32(FinalFlag),
3945 CGF.Builder.getInt32(/*C=*/0))
3946 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
3947 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
3948 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
3949 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
3950 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3951 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3952 TaskEntry, KmpRoutineEntryPtrTy)};
3953 llvm::Value *NewTask;
3954 if (D.hasClausesOfKind<OMPNowaitClause>()) {
3955 // Check if we have any device clause associated with the directive.
3956 const Expr *Device = nullptr;
3957 if (auto *C = D.getSingleClause<OMPDeviceClause>())
3958 Device = C->getDevice();
3959 // Emit device ID if any otherwise use default value.
3960 llvm::Value *DeviceID;
3961 if (Device)
3962 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
3963 CGF.Int64Ty, /*isSigned=*/true);
3964 else
3965 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
3966 AllocArgs.push_back(DeviceID);
3967 NewTask = CGF.EmitRuntimeCall(
3968 OMPBuilder.getOrCreateRuntimeFunction(
3969 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3970 AllocArgs);
3971 } else {
3972 NewTask =
3973 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
3974 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3975 AllocArgs);
3976 }
3977 // Emit detach clause initialization.
3978 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid,
3979 // task_descriptor);
3980 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) {
3981 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts();
3982 LValue EvtLVal = CGF.EmitLValue(Evt);
3983
3984 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref,
3985 // int gtid, kmp_task_t *task);
3986 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc());
3987 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc());
3988 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false);
3989 llvm::Value *EvtVal = CGF.EmitRuntimeCall(
3990 OMPBuilder.getOrCreateRuntimeFunction(
3991 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3992 {Loc, Tid, NewTask});
3993 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(),
3994 Evt->getExprLoc());
3995 CGF.EmitStoreOfScalar(EvtVal, EvtLVal);
3996 }
3997 // Process affinity clauses.
3998 if (D.hasClausesOfKind<OMPAffinityClause>()) {
3999 // Process list of affinity data.
4000 ASTContext &C = CGM.getContext();
4001 Address AffinitiesArray = Address::invalid();
4002 // Calculate number of elements to form the array of affinity data.
4003 llvm::Value *NumOfElements = nullptr;
4004 unsigned NumAffinities = 0;
4005 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
4006 if (const Expr *Modifier = C->getModifier()) {
4007 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts());
4008 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4009 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper);
4010 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false);
4011 NumOfElements =
4012 NumOfElements ? CGF.Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
4013 }
4014 } else {
4015 NumAffinities += C->varlist_size();
4016 }
4017 }
4018 getKmpAffinityType(CGM.getContext(), KmpTaskAffinityInfoTy);
4019 // Fields ids in kmp_task_affinity_info record.
4020 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
4021
4022 QualType KmpTaskAffinityInfoArrayTy;
4023 if (NumOfElements) {
4024 NumOfElements = CGF.Builder.CreateNUWAdd(
4025 llvm::ConstantInt::get(CGF.SizeTy, NumAffinities), NumOfElements);
4026 auto *OVE = new (C) OpaqueValueExpr(
4027 Loc,
4028 C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0),
4029 VK_PRValue);
4030 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, OVE,
4031 RValue::get(NumOfElements));
4032 KmpTaskAffinityInfoArrayTy =
4033 C.getVariableArrayType(KmpTaskAffinityInfoTy, OVE, ArrayType::Normal,
4034 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc));
4035 // Properly emit variable-sized array.
4036 auto *PD = ImplicitParamDecl::Create(C, KmpTaskAffinityInfoArrayTy,
4037 ImplicitParamDecl::Other);
4038 CGF.EmitVarDecl(*PD);
4039 AffinitiesArray = CGF.GetAddrOfLocalVar(PD);
4040 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty,
4041 /*isSigned=*/false);
4042 } else {
4043 KmpTaskAffinityInfoArrayTy = C.getConstantArrayType(
4044 KmpTaskAffinityInfoTy,
4045 llvm::APInt(C.getTypeSize(C.getSizeType()), NumAffinities), nullptr,
4046 ArrayType::Normal, /*IndexTypeQuals=*/0);
4047 AffinitiesArray =
4048 CGF.CreateMemTemp(KmpTaskAffinityInfoArrayTy, ".affs.arr.addr");
4049 AffinitiesArray = CGF.Builder.CreateConstArrayGEP(AffinitiesArray, 0);
4050 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumAffinities,
4051 /*isSigned=*/false);
4052 }
4053
4054 const auto *KmpAffinityInfoRD = KmpTaskAffinityInfoTy->getAsRecordDecl();
4055 // Fill array by elements without iterators.
4056 unsigned Pos = 0;
4057 bool HasIterator = false;
4058 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
4059 if (C->getModifier()) {
4060 HasIterator = true;
4061 continue;
4062 }
4063 for (const Expr *E : C->varlists()) {
4064 llvm::Value *Addr;
4065 llvm::Value *Size;
4066 std::tie(Addr, Size) = getPointerAndSize(CGF, E);
4067 LValue Base =
4068 CGF.MakeAddrLValue(CGF.Builder.CreateConstGEP(AffinitiesArray, Pos),
4069 KmpTaskAffinityInfoTy);
4070 // affs[i].base_addr = &<Affinities[i].second>;
4071 LValue BaseAddrLVal = CGF.EmitLValueForField(
4072 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4073 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy),
4074 BaseAddrLVal);
4075 // affs[i].len = sizeof(<Affinities[i].second>);
4076 LValue LenLVal = CGF.EmitLValueForField(
4077 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4078 CGF.EmitStoreOfScalar(Size, LenLVal);
4079 ++Pos;
4080 }
4081 }
4082 LValue PosLVal;
4083 if (HasIterator) {
4084 PosLVal = CGF.MakeAddrLValue(
4085 CGF.CreateMemTemp(C.getSizeType(), "affs.counter.addr"),
4086 C.getSizeType());
4087 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal);
4088 }
4089 // Process elements with iterators.
4090 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
4091 const Expr *Modifier = C->getModifier();
4092 if (!Modifier)
4093 continue;
4094 OMPIteratorGeneratorScope IteratorScope(
4095 CGF, cast_or_null<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts()));
4096 for (const Expr *E : C->varlists()) {
4097 llvm::Value *Addr;
4098 llvm::Value *Size;
4099 std::tie(Addr, Size) = getPointerAndSize(CGF, E);
4100 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4101 LValue Base = CGF.MakeAddrLValue(
4102 CGF.Builder.CreateGEP(AffinitiesArray, Idx), KmpTaskAffinityInfoTy);
4103 // affs[i].base_addr = &<Affinities[i].second>;
4104 LValue BaseAddrLVal = CGF.EmitLValueForField(
4105 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4106 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy),
4107 BaseAddrLVal);
4108 // affs[i].len = sizeof(<Affinities[i].second>);
4109 LValue LenLVal = CGF.EmitLValueForField(
4110 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4111 CGF.EmitStoreOfScalar(Size, LenLVal);
4112 Idx = CGF.Builder.CreateNUWAdd(
4113 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4114 CGF.EmitStoreOfScalar(Idx, PosLVal);
4115 }
4116 }
4117 // Call to kmp_int32 __kmpc_omp_reg_task_with_affinity(ident_t *loc_ref,
4118 // kmp_int32 gtid, kmp_task_t *new_task, kmp_int32
4119 // naffins, kmp_task_affinity_info_t *affin_list);
4120 llvm::Value *LocRef = emitUpdateLocation(CGF, Loc);
4121 llvm::Value *GTid = getThreadID(CGF, Loc);
4122 llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4123 AffinitiesArray.getPointer(), CGM.VoidPtrTy);
4124 // FIXME: Emit the function and ignore its result for now unless the
4125 // runtime function is properly implemented.
4126 (void)CGF.EmitRuntimeCall(
4127 OMPBuilder.getOrCreateRuntimeFunction(
4128 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4129 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4130 }
4131 llvm::Value *NewTaskNewTaskTTy =
4132 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4133 NewTask, KmpTaskTWithPrivatesPtrTy);
4134 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
4135 KmpTaskTWithPrivatesQTy);
4136 LValue TDBase =
4137 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
4138 // Fill the data in the resulting kmp_task_t record.
4139 // Copy shareds if there are any.
4140 Address KmpTaskSharedsPtr = Address::invalid();
4141 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
4142 KmpTaskSharedsPtr = Address(
4143 CGF.EmitLoadOfScalar(
4144 CGF.EmitLValueForField(
4145 TDBase,
4146 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
4147 Loc),
4148 CGF.Int8Ty, CGM.getNaturalTypeAlignment(SharedsTy));
4149 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
4150 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
4151 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
4152 }
4153 // Emit initial values for private copies (if any).
4154 TaskResultTy Result;
4155 if (!Privates.empty()) {
4156 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
4157 SharedsTy, SharedsPtrTy, Data, Privates,
4158 /*ForDup=*/false);
4159 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
4160 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
4161 Result.TaskDupFn = emitTaskDupFunction(
4162 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4163 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
4164 /*WithLastIter=*/!Data.LastprivateVars.empty());
4165 }
4166 }
4167 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
4168 enum { Priority = 0, Destructors = 1 };
4169 // Provide pointer to function with destructors for privates.
4170 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4171 const RecordDecl *KmpCmplrdataUD =
4172 (*FI)->getType()->getAsUnionType()->getDecl();
4173 if (NeedsCleanup) {
4174 llvm::Value *DestructorFn = emitDestructorsFunction(
4175 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4176 KmpTaskTWithPrivatesQTy);
4177 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
4178 LValue DestructorsLV = CGF.EmitLValueForField(
4179 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4180 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4181 DestructorFn, KmpRoutineEntryPtrTy),
4182 DestructorsLV);
4183 }
4184 // Set priority.
4185 if (Data.Priority.getInt()) {
4186 LValue Data2LV = CGF.EmitLValueForField(
4187 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4188 LValue PriorityLV = CGF.EmitLValueForField(
4189 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4190 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
4191 }
4192 Result.NewTask = NewTask;
4193 Result.TaskEntry = TaskEntry;
4194 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4195 Result.TDBase = TDBase;
4196 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4197 return Result;
4198}
4199
4200/// Translates internal dependency kind into the runtime kind.
4201static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) {
4202 RTLDependenceKindTy DepKind;
4203 switch (K) {
4204 case OMPC_DEPEND_in:
4205 DepKind = RTLDependenceKindTy::DepIn;
4206 break;
4207 // Out and InOut dependencies must use the same code.
4208 case OMPC_DEPEND_out:
4209 case OMPC_DEPEND_inout:
4210 DepKind = RTLDependenceKindTy::DepInOut;
4211 break;
4212 case OMPC_DEPEND_mutexinoutset:
4213 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4214 break;
4215 case OMPC_DEPEND_inoutset:
4216 DepKind = RTLDependenceKindTy::DepInOutSet;
4217 break;
4218 case OMPC_DEPEND_outallmemory:
4219 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4220 break;
4221 case OMPC_DEPEND_source:
4222 case OMPC_DEPEND_sink:
4223 case OMPC_DEPEND_depobj:
4224 case OMPC_DEPEND_inoutallmemory:
4225 case OMPC_DEPEND_unknown:
4226 llvm_unreachable("Unknown task dependence type")::llvm::llvm_unreachable_internal("Unknown task dependence type"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 4226)
;
4227 }
4228 return DepKind;
4229}
4230
4231/// Builds kmp_depend_info, if it is not built yet, and builds flags type.
4232static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy,
4233 QualType &FlagsTy) {
4234 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
4235 if (KmpDependInfoTy.isNull()) {
4236 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
4237 KmpDependInfoRD->startDefinition();
4238 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
4239 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
4240 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
4241 KmpDependInfoRD->completeDefinition();
4242 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
4243 }
4244}
4245
4246std::pair<llvm::Value *, LValue>
4247CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal,
4248 SourceLocation Loc) {
4249 ASTContext &C = CGM.getContext();
4250 QualType FlagsTy;
4251 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4252 RecordDecl *KmpDependInfoRD =
4253 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4254 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
4255 LValue Base = CGF.EmitLoadOfPointerLValue(
4256 CGF.Builder.CreateElementBitCast(
4257 DepobjLVal.getAddress(CGF),
4258 CGF.ConvertTypeForMem(KmpDependInfoPtrTy)),
4259 KmpDependInfoPtrTy->castAs<PointerType>());
4260 Address DepObjAddr = CGF.Builder.CreateGEP(
4261 Base.getAddress(CGF),
4262 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
4263 LValue NumDepsBase = CGF.MakeAddrLValue(
4264 DepObjAddr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo());
4265 // NumDeps = deps[i].base_addr;
4266 LValue BaseAddrLVal = CGF.EmitLValueForField(
4267 NumDepsBase,
4268 *std::next(KmpDependInfoRD->field_begin(),
4269 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4270 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc);
4271 return std::make_pair(NumDeps, Base);
4272}
4273
4274static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy,
4275 llvm::PointerUnion<unsigned *, LValue *> Pos,
4276 const OMPTaskDataTy::DependData &Data,
4277 Address DependenciesArray) {
4278 CodeGenModule &CGM = CGF.CGM;
4279 ASTContext &C = CGM.getContext();
4280 QualType FlagsTy;
4281 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4282 RecordDecl *KmpDependInfoRD =
4283 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
9
The object is a 'CastReturnType'
4284 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
4285
4286 OMPIteratorGeneratorScope IteratorScope(
4287 CGF, cast_or_null<OMPIteratorExpr>(
11
Assuming null pointer is passed into cast
4288 Data.IteratorExpr
9.1
Field 'IteratorExpr' is non-null
9.1
Field 'IteratorExpr' is non-null
9.1
Field 'IteratorExpr' is non-null
? Data.IteratorExpr->IgnoreParenImpCasts()
10
'?' condition is true
4289 : nullptr));
4290 for (const Expr *E : Data.DepExprs) {
12
Assuming '__begin1' is not equal to '__end1'
13
'E' initialized here
4291 llvm::Value *Addr;
4292 llvm::Value *Size;
4293
4294 // The expression will be a nullptr in the 'omp_all_memory' case.
4295 if (E) {
14
Assuming 'E' is null
15
Taking false branch
4296 std::tie(Addr, Size) = getPointerAndSize(CGF, E);
4297 Addr = CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy);
4298 } else {
4299 Addr = llvm::ConstantInt::get(CGF.IntPtrTy, 0);
4300 Size = llvm::ConstantInt::get(CGF.SizeTy, 0);
4301 }
4302 LValue Base;
4303 if (unsigned *P = Pos.dyn_cast<unsigned *>()) {
16
Calling 'PointerUnion::dyn_cast'
37
Returning from 'PointerUnion::dyn_cast'
38
Assuming 'P' is non-null
39
Taking true branch
4304 Base = CGF.MakeAddrLValue(
4305 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy);
4306 } else {
4307 assert(E && "Expected a non-null expression")(static_cast <bool> (E && "Expected a non-null expression"
) ? void (0) : __assert_fail ("E && \"Expected a non-null expression\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 4307, __extension__
__PRETTY_FUNCTION__))
;
4308 LValue &PosLVal = *Pos.get<LValue *>();
4309 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4310 Base = CGF.MakeAddrLValue(
4311 CGF.Builder.CreateGEP(DependenciesArray, Idx), KmpDependInfoTy);
4312 }
4313 // deps[i].base_addr = &<Dependencies[i].second>;
4314 LValue BaseAddrLVal = CGF.EmitLValueForField(
4315 Base,
4316 *std::next(KmpDependInfoRD->field_begin(),
4317 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4318 CGF.EmitStoreOfScalar(Addr, BaseAddrLVal);
4319 // deps[i].len = sizeof(<Dependencies[i].second>);
4320 LValue LenLVal = CGF.EmitLValueForField(
4321 Base, *std::next(KmpDependInfoRD->field_begin(),
4322 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4323 CGF.EmitStoreOfScalar(Size, LenLVal);
4324 // deps[i].flags = <Dependencies[i].first>;
4325 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind);
4326 LValue FlagsLVal = CGF.EmitLValueForField(
4327 Base,
4328 *std::next(KmpDependInfoRD->field_begin(),
4329 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4330 CGF.EmitStoreOfScalar(
4331 llvm::ConstantInt::get(LLVMFlagsTy, static_cast<unsigned int>(DepKind)),
4332 FlagsLVal);
4333 if (unsigned *P
53.1
'P' is null
53.1
'P' is null
53.1
'P' is null
= Pos.dyn_cast<unsigned *>()) {
40
Calling 'PointerUnion::dyn_cast'
53
Returning from 'PointerUnion::dyn_cast'
54
Taking false branch
4334 ++(*P);
4335 } else {
4336 LValue &PosLVal = *Pos.get<LValue *>();
4337 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
55
Called C++ object pointer is null
4338 Idx = CGF.Builder.CreateNUWAdd(Idx,
4339 llvm::ConstantInt::get(Idx->getType(), 1));
4340 CGF.EmitStoreOfScalar(Idx, PosLVal);
4341 }
4342 }
4343}
4344
4345SmallVector<llvm::Value *, 4> CGOpenMPRuntime::emitDepobjElementsSizes(
4346 CodeGenFunction &CGF, QualType &KmpDependInfoTy,
4347 const OMPTaskDataTy::DependData &Data) {
4348 assert(Data.DepKind == OMPC_DEPEND_depobj &&(static_cast <bool> (Data.DepKind == OMPC_DEPEND_depobj
&& "Expected depobj dependency kind.") ? void (0) : __assert_fail
("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependency kind.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 4349, __extension__
__PRETTY_FUNCTION__))
4349 "Expected depobj dependency kind.")(static_cast <bool> (Data.DepKind == OMPC_DEPEND_depobj
&& "Expected depobj dependency kind.") ? void (0) : __assert_fail
("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependency kind.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 4349, __extension__
__PRETTY_FUNCTION__))
;
4350 SmallVector<llvm::Value *, 4> Sizes;
4351 SmallVector<LValue, 4> SizeLVals;
4352 ASTContext &C = CGF.getContext();
4353 {
4354 OMPIteratorGeneratorScope IteratorScope(
4355 CGF, cast_or_null<OMPIteratorExpr>(
4356 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts()
4357 : nullptr));
4358 for (const Expr *E : Data.DepExprs) {
4359 llvm::Value *NumDeps;
4360 LValue Base;
4361 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts());
4362 std::tie(NumDeps, Base) =
4363 getDepobjElements(CGF, DepobjLVal, E->getExprLoc());
4364 LValue NumLVal = CGF.MakeAddrLValue(
4365 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"),
4366 C.getUIntPtrType());
4367 CGF.Builder.CreateStore(llvm::ConstantInt::get(CGF.IntPtrTy, 0),
4368 NumLVal.getAddress(CGF));
4369 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc());
4370 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps);
4371 CGF.EmitStoreOfScalar(Add, NumLVal);
4372 SizeLVals.push_back(NumLVal);
4373 }
4374 }
4375 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4376 llvm::Value *Size =
4377 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc());
4378 Sizes.push_back(Size);
4379 }
4380 return Sizes;
4381}
4382
4383void CGOpenMPRuntime::emitDepobjElements(CodeGenFunction &CGF,
4384 QualType &KmpDependInfoTy,
4385 LValue PosLVal,
4386 const OMPTaskDataTy::DependData &Data,
4387 Address DependenciesArray) {
4388 assert(Data.DepKind == OMPC_DEPEND_depobj &&(static_cast <bool> (Data.DepKind == OMPC_DEPEND_depobj
&& "Expected depobj dependency kind.") ? void (0) : __assert_fail
("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependency kind.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 4389, __extension__
__PRETTY_FUNCTION__))
4389 "Expected depobj dependency kind.")(static_cast <bool> (Data.DepKind == OMPC_DEPEND_depobj
&& "Expected depobj dependency kind.") ? void (0) : __assert_fail
("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependency kind.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 4389, __extension__
__PRETTY_FUNCTION__))
;
4390 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy);
4391 {
4392 OMPIteratorGeneratorScope IteratorScope(
4393 CGF, cast_or_null<OMPIteratorExpr>(
4394 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts()
4395 : nullptr));
4396 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) {
4397 const Expr *E = Data.DepExprs[I];
4398 llvm::Value *NumDeps;
4399 LValue Base;
4400 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts());
4401 std::tie(NumDeps, Base) =
4402 getDepobjElements(CGF, DepobjLVal, E->getExprLoc());
4403
4404 // memcopy dependency data.
4405 llvm::Value *Size = CGF.Builder.CreateNUWMul(
4406 ElSize,
4407 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false));
4408 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4409 Address DepAddr = CGF.Builder.CreateGEP(DependenciesArray, Pos);
4410 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size);
4411
4412 // Increase pos.
4413 // pos += size;
4414 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps);
4415 CGF.EmitStoreOfScalar(Add, PosLVal);
4416 }
4417 }
4418}
4419
4420std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause(
4421 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies,
4422 SourceLocation Loc) {
4423 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) {
4424 return D.DepExprs.empty();
4425 }))
4426 return std::make_pair(nullptr, Address::invalid());
4427 // Process list of dependencies.
4428 ASTContext &C = CGM.getContext();
4429 Address DependenciesArray = Address::invalid();
4430 llvm::Value *NumOfElements = nullptr;
4431 unsigned NumDependencies = std::accumulate(
4432 Dependencies.begin(), Dependencies.end(), 0,
4433 [](unsigned V, const OMPTaskDataTy::DependData &D) {
4434 return D.DepKind == OMPC_DEPEND_depobj
4435 ? V
4436 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4437 });
4438 QualType FlagsTy;
4439 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4440 bool HasDepobjDeps = false;
4441 bool HasRegularWithIterators = false;
4442 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0);
4443 llvm::Value *NumOfRegularWithIterators =
4444 llvm::ConstantInt::get(CGF.IntPtrTy, 0);
4445 // Calculate number of depobj dependencies and regular deps with the
4446 // iterators.
4447 for (const OMPTaskDataTy::DependData &D : Dependencies) {
4448 if (D.DepKind == OMPC_DEPEND_depobj) {
4449 SmallVector<llvm::Value *, 4> Sizes =
4450 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D);
4451 for (llvm::Value *Size : Sizes) {
4452 NumOfDepobjElements =
4453 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4454 }
4455 HasDepobjDeps = true;
4456 continue;
4457 }
4458 // Include number of iterations, if any.
4459
4460 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) {
4461 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4462 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper);
4463 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false);
4464 llvm::Value *NumClauseDeps = CGF.Builder.CreateNUWMul(
4465 Sz, llvm::ConstantInt::get(CGF.IntPtrTy, D.DepExprs.size()));
4466 NumOfRegularWithIterators =
4467 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4468 }
4469 HasRegularWithIterators = true;
4470 continue;
4471 }
4472 }
4473
4474 QualType KmpDependInfoArrayTy;
4475 if (HasDepobjDeps || HasRegularWithIterators) {
4476 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies,
4477 /*isSigned=*/false);
4478 if (HasDepobjDeps) {
4479 NumOfElements =
4480 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4481 }
4482 if (HasRegularWithIterators) {
4483 NumOfElements =
4484 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4485 }
4486 auto *OVE = new (C) OpaqueValueExpr(
4487 Loc, C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0),
4488 VK_PRValue);
4489 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, OVE,
4490 RValue::get(NumOfElements));
4491 KmpDependInfoArrayTy =
4492 C.getVariableArrayType(KmpDependInfoTy, OVE, ArrayType::Normal,
4493 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc));
4494 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy);
4495 // Properly emit variable-sized array.
4496 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy,
4497 ImplicitParamDecl::Other);
4498 CGF.EmitVarDecl(*PD);
4499 DependenciesArray = CGF.GetAddrOfLocalVar(PD);
4500 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty,
4501 /*isSigned=*/false);
4502 } else {
4503 KmpDependInfoArrayTy = C.getConstantArrayType(
4504 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr,
4505 ArrayType::Normal, /*IndexTypeQuals=*/0);
4506 DependenciesArray =
4507 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
4508 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0);
4509 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies,
4510 /*isSigned=*/false);
4511 }
4512 unsigned Pos = 0;
4513 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4514 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj ||
4515 Dependencies[I].IteratorExpr)
4516 continue;
4517 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I],
4518 DependenciesArray);
4519 }
4520 // Copy regular dependencies with iterators.
4521 LValue PosLVal = CGF.MakeAddrLValue(
4522 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType());
4523 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal);
4524 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4525 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj ||
4526 !Dependencies[I].IteratorExpr)
4527 continue;
4528 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I],
4529 DependenciesArray);
4530 }
4531 // Copy final depobj arrays without iterators.
4532 if (HasDepobjDeps) {
4533 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4534 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj)
4535 continue;
4536 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I],
4537 DependenciesArray);
4538 }
4539 }
4540 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4541 DependenciesArray, CGF.VoidPtrTy, CGF.Int8Ty);
4542 return std::make_pair(NumOfElements, DependenciesArray);
4543}
4544
4545Address CGOpenMPRuntime::emitDepobjDependClause(
4546 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies,
4547 SourceLocation Loc) {
4548 if (Dependencies.DepExprs.empty())
1
Taking false branch
4549 return Address::invalid();
4550 // Process list of dependencies.
4551 ASTContext &C = CGM.getContext();
4552 Address DependenciesArray = Address::invalid();
4553 unsigned NumDependencies = Dependencies.DepExprs.size();
4554 QualType FlagsTy;
4555 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4556 RecordDecl *KmpDependInfoRD =
4557 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
2
The object is a 'CastReturnType'
4558
4559 llvm::Value *Size;
4560 // Define type kmp_depend_info[<Dependencies.size()>];
4561 // For depobj reserve one extra element to store the number of elements.
4562 // It is required to handle depobj(x) update(in) construct.
4563 // kmp_depend_info[<Dependencies.size()>] deps;
4564 llvm::Value *NumDepsVal;
4565 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy);
4566 if (const auto *IE
3.1
'IE' is non-null
3.1
'IE' is non-null
3.1
'IE' is non-null
=
4
Taking true branch
4567 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) {
3
Assuming field 'IteratorExpr' is a 'CastReturnType'
4568 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1);
4569 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
5
Assuming 'I' is >= 'E'
6
Loop condition is false. Execution continues on line 4574
4570 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper);
4571 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false);
4572 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz);
4573 }
4574 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1),
4575 NumDepsVal);
4576 CharUnits SizeInBytes =
4577 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align);
4578 llvm::Value *RecSize = CGM.getSize(SizeInBytes);
4579 Size = CGF.Builder.CreateNUWMul(Size, RecSize);
4580 NumDepsVal =
4581 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false);
4582 } else {
4583 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
4584 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1),
4585 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
4586 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy);
4587 Size = CGM.getSize(Sz.alignTo(Align));
4588 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies);
4589 }
4590 // Need to allocate on the dynamic memory.
4591 llvm::Value *ThreadID = getThreadID(CGF, Loc);
4592 // Use default allocator.
4593 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
4594 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4595
4596 llvm::Value *Addr =
4597 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
4598 CGM.getModule(), OMPRTL___kmpc_alloc),
4599 Args, ".dep.arr.addr");
4600 llvm::Type *KmpDependInfoLlvmTy = CGF.ConvertTypeForMem(KmpDependInfoTy);
4601 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4602 Addr, KmpDependInfoLlvmTy->getPointerTo());
4603 DependenciesArray = Address(Addr, KmpDependInfoLlvmTy, Align);
4604 // Write number of elements in the first element of array for depobj.
4605 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy);
4606 // deps[i].base_addr = NumDependencies;
4607 LValue BaseAddrLVal = CGF.EmitLValueForField(
4608 Base,
4609 *std::next(KmpDependInfoRD->field_begin(),
4610 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4611 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal);
4612 llvm::PointerUnion<unsigned *, LValue *> Pos;
4613 unsigned Idx = 1;
4614 LValue PosLVal;
4615 if (Dependencies.IteratorExpr
6.1
Field 'IteratorExpr' is non-null
6.1
Field 'IteratorExpr' is non-null
6.1
Field 'IteratorExpr' is non-null
) {
7
Taking true branch
4616 PosLVal = CGF.MakeAddrLValue(
4617 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"),
4618 C.getSizeType());
4619 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal,
4620 /*IsInit=*/true);
4621 Pos = &PosLVal;
4622 } else {
4623 Pos = &Idx;
4624 }
4625 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray);
8
Calling 'emitDependData'
4626 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4627 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy,
4628 CGF.Int8Ty);
4629 return DependenciesArray;
4630}
4631
4632void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal,
4633 SourceLocation Loc) {
4634 ASTContext &C = CGM.getContext();
4635 QualType FlagsTy;
4636 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4637 LValue Base = CGF.EmitLoadOfPointerLValue(
4638 DepobjLVal.getAddress(CGF), C.VoidPtrTy.castAs<PointerType>());
4639 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
4640 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4641 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy),
4642 CGF.ConvertTypeForMem(KmpDependInfoTy));
4643 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
4644 Addr.getElementType(), Addr.getPointer(),
4645 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
4646 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr,
4647 CGF.VoidPtrTy);
4648 llvm::Value *ThreadID = getThreadID(CGF, Loc);
4649 // Use default allocator.
4650 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
4651 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4652
4653 // _kmpc_free(gtid, addr, nullptr);
4654 (void)CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
4655 CGM.getModule(), OMPRTL___kmpc_free),
4656 Args);
4657}
4658
4659void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal,
4660 OpenMPDependClauseKind NewDepKind,
4661 SourceLocation Loc) {
4662 ASTContext &C = CGM.getContext();
4663 QualType FlagsTy;
4664 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4665 RecordDecl *KmpDependInfoRD =
4666 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4667 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
4668 llvm::Value *NumDeps;
4669 LValue Base;
4670 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc);
4671
4672 Address Begin = Base.getAddress(CGF);
4673 // Cast from pointer to array type to pointer to single element.
4674 llvm::Value *End = CGF.Builder.CreateGEP(
4675 Begin.getElementType(), Begin.getPointer(), NumDeps);
4676 // The basic structure here is a while-do loop.
4677 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body");
4678 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done");
4679 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
4680 CGF.EmitBlock(BodyBB);
4681 llvm::PHINode *ElementPHI =
4682 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast");
4683 ElementPHI->addIncoming(Begin.getPointer(), EntryBB);
4684 Begin = Begin.withPointer(ElementPHI, KnownNonNull);
4685 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(),
4686 Base.getTBAAInfo());
4687 // deps[i].flags = NewDepKind;
4688 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind);
4689 LValue FlagsLVal = CGF.EmitLValueForField(
4690 Base, *std::next(KmpDependInfoRD->field_begin(),
4691 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4692 CGF.EmitStoreOfScalar(
4693 llvm::ConstantInt::get(LLVMFlagsTy, static_cast<unsigned int>(DepKind)),
4694 FlagsLVal);
4695
4696 // Shift the address forward by one element.
4697 Address ElementNext =
4698 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext");
4699 ElementPHI->addIncoming(ElementNext.getPointer(),
4700 CGF.Builder.GetInsertBlock());
4701 llvm::Value *IsEmpty =
4702 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty");
4703 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4704 // Done.
4705 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
4706}
4707
4708void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
4709 const OMPExecutableDirective &D,
4710 llvm::Function *TaskFunction,
4711 QualType SharedsTy, Address Shareds,
4712 const Expr *IfCond,
4713 const OMPTaskDataTy &Data) {
4714 if (!CGF.HaveInsertPoint())
4715 return;
4716
4717 TaskResultTy Result =
4718 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
4719 llvm::Value *NewTask = Result.NewTask;
4720 llvm::Function *TaskEntry = Result.TaskEntry;
4721 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
4722 LValue TDBase = Result.TDBase;
4723 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
4724 // Process list of dependences.
4725 Address DependenciesArray = Address::invalid();
4726 llvm::Value *NumOfElements;
4727 std::tie(NumOfElements, DependenciesArray) =
4728 emitDependClause(CGF, Data.Dependences, Loc);
4729
4730 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
4731 // libcall.
4732 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
4733 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
4734 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
4735 // list is not empty
4736 llvm::Value *ThreadID = getThreadID(CGF, Loc);
4737 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
4738 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4739 llvm::Value *DepTaskArgs[7];
4740 if (!Data.Dependences.empty()) {
4741 DepTaskArgs[0] = UpLoc;
4742 DepTaskArgs[1] = ThreadID;
4743 DepTaskArgs[2] = NewTask;
4744 DepTaskArgs[3] = NumOfElements;
4745 DepTaskArgs[4] = DependenciesArray.getPointer();
4746 DepTaskArgs[5] = CGF.Builder.getInt32(0);
4747 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
4748 }
4749 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4750 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
4751 if (!Data.Tied) {
4752 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
4753 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
4754 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
4755 }
4756 if (!Data.Dependences.empty()) {
4757 CGF.EmitRuntimeCall(
4758 OMPBuilder.getOrCreateRuntimeFunction(
4759 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4760 DepTaskArgs);
4761 } else {
4762 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
4763 CGM.getModule(), OMPRTL___kmpc_omp_task),
4764 TaskArgs);
4765 }
4766 // Check if parent region is untied and build return for untied task;
4767 if (auto *Region =
4768 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
4769 Region->emitUntiedSwitch(CGF);
4770 };
4771
4772 llvm::Value *DepWaitTaskArgs[7];
4773 if (!Data.Dependences.empty()) {
4774 DepWaitTaskArgs[0] = UpLoc;
4775 DepWaitTaskArgs[1] = ThreadID;
4776 DepWaitTaskArgs[2] = NumOfElements;
4777 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
4778 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
4779 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
4780 DepWaitTaskArgs[6] =
4781 llvm::ConstantInt::get(CGF.Int32Ty, Data.HasNowaitClause);
4782 }
4783 auto &M = CGM.getModule();
4784 auto &&ElseCodeGen = [this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4785 TaskEntry, &Data, &DepWaitTaskArgs,
4786 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
4787 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
4788 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
4789 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
4790 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
4791 // is specified.
4792 if (!Data.Dependences.empty())
4793 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
4794 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4795 DepWaitTaskArgs);
4796 // Call proxy_task_entry(gtid, new_task);
4797 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4798 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
4799 Action.Enter(CGF);
4800 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4801 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4802 OutlinedFnArgs);
4803 };
4804
4805 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
4806 // kmp_task_t *new_task);
4807 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
4808 // kmp_task_t *new_task);
4809 RegionCodeGenTy RCG(CodeGen);
4810 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
4811 M, OMPRTL___kmpc_omp_task_begin_if0),
4812 TaskArgs,
4813 OMPBuilder.getOrCreateRuntimeFunction(
4814 M, OMPRTL___kmpc_omp_task_complete_if0),
4815 TaskArgs);
4816 RCG.setAction(Action);
4817 RCG(CGF);
4818 };
4819
4820 if (IfCond) {
4821 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
4822 } else {
4823 RegionCodeGenTy ThenRCG(ThenCodeGen);
4824 ThenRCG(CGF);
4825 }
4826}
4827
4828void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
4829 const OMPLoopDirective &D,
4830 llvm::Function *TaskFunction,
4831 QualType SharedsTy, Address Shareds,
4832 const Expr *IfCond,
4833 const OMPTaskDataTy &Data) {
4834 if (!CGF.HaveInsertPoint())
4835 return;
4836 TaskResultTy Result =
4837 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
4838 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
4839 // libcall.
4840 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
4841 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
4842 // sched, kmp_uint64 grainsize, void *task_dup);
4843 llvm::Value *ThreadID = getThreadID(CGF, Loc);
4844 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
4845 llvm::Value *IfVal;
4846 if (IfCond) {
4847 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
4848 /*isSigned=*/true);
4849 } else {
4850 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
4851 }
4852
4853 LValue LBLVal = CGF.EmitLValueForField(
4854 Result.TDBase,
4855 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4856 const auto *LBVar =
4857 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
4858 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF),
4859 LBLVal.getQuals(),
4860 /*IsInitializer=*/true);
4861 LValue UBLVal = CGF.EmitLValueForField(
4862 Result.TDBase,
4863 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4864 const auto *UBVar =
4865 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
4866 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF),
4867 UBLVal.getQuals(),
4868 /*IsInitializer=*/true);
4869 LValue StLVal = CGF.EmitLValueForField(
4870 Result.TDBase,
4871 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4872 const auto *StVar =
4873 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
4874 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF),
4875 StLVal.getQuals(),
4876 /*IsInitializer=*/true);
4877 // Store reductions address.
4878 LValue RedLVal = CGF.EmitLValueForField(
4879 Result.TDBase,
4880 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4881 if (Data.Reductions) {
4882 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
4883 } else {
4884 CGF.EmitNullInitialization(RedLVal.getAddress(CGF),
4885 CGF.getContext().VoidPtrTy);
4886 }
4887 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4888 llvm::Value *TaskArgs[] = {
4889 UpLoc,
4890 ThreadID,
4891 Result.NewTask,
4892 IfVal,
4893 LBLVal.getPointer(CGF),
4894 UBLVal.getPointer(CGF),
4895 CGF.EmitLoadOfScalar(StLVal, Loc),
4896 llvm::ConstantInt::getSigned(
4897 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
4898 llvm::ConstantInt::getSigned(
4899 CGF.IntTy, Data.Schedule.getPointer()
4900 ? Data.Schedule.getInt() ? NumTasks : Grainsize
4901 : NoSchedule),
4902 Data.Schedule.getPointer()
4903 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
4904 /*isSigned=*/false)
4905 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
4906 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4907 Result.TaskDupFn, CGF.VoidPtrTy)
4908 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
4909 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
4910 CGM.getModule(), OMPRTL___kmpc_taskloop),
4911 TaskArgs);
4912}
4913
4914/// Emit reduction operation for each element of array (required for
4915/// array sections) LHS op = RHS.
4916/// \param Type Type of array.
4917/// \param LHSVar Variable on the left side of the reduction operation
4918/// (references element of array in original variable).
4919/// \param RHSVar Variable on the right side of the reduction operation
4920/// (references element of array in original variable).
4921/// \param RedOpGen Generator of reduction operation with use of LHSVar and
4922/// RHSVar.
4923static void EmitOMPAggregateReduction(
4924 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
4925 const VarDecl *RHSVar,
4926 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
4927 const Expr *, const Expr *)> &RedOpGen,
4928 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
4929 const Expr *UpExpr = nullptr) {
4930 // Perform element-by-element initialization.
4931 QualType ElementTy;
4932 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
4933 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
4934
4935 // Drill down to the base element type on both arrays.
4936 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
4937 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4938
4939 llvm::Value *RHSBegin = RHSAddr.getPointer();
4940 llvm::Value *LHSBegin = LHSAddr.getPointer();
4941 // Cast from pointer to array type to pointer to single element.
4942 llvm::Value *LHSEnd =
4943 CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements);
4944 // The basic structure here is a while-do loop.
4945 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
4946 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
4947 llvm::Value *IsEmpty =
4948 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
4949 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4950
4951 // Enter the loop body, making that address the current address.
4952 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
4953 CGF.EmitBlock(BodyBB);
4954
4955 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
4956
4957 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
4958 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
4959 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4960 Address RHSElementCurrent(
4961 RHSElementPHI, RHSAddr.getElementType(),
4962 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
4963
4964 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
4965 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
4966 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4967 Address LHSElementCurrent(
4968 LHSElementPHI, LHSAddr.getElementType(),
4969 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
4970
4971 // Emit copy.
4972 CodeGenFunction::OMPPrivateScope Scope(CGF);
4973 Scope.addPrivate(LHSVar, LHSElementCurrent);
4974 Scope.addPrivate(RHSVar, RHSElementCurrent);
4975 Scope.Privatize();
4976 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4977 Scope.ForceCleanup();
4978
4979 // Shift the address forward by one element.
4980 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
4981 LHSAddr.getElementType(), LHSElementPHI, /*Idx0=*/1,
4982 "omp.arraycpy.dest.element");
4983 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
4984 RHSAddr.getElementType(), RHSElementPHI, /*Idx0=*/1,
4985 "omp.arraycpy.src.element");
4986 // Check whether we've reached the end.
4987 llvm::Value *Done =
4988 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
4989 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
4990 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
4991 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
4992
4993 // Done.
4994 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
4995}
4996
4997/// Emit reduction combiner. If the combiner is a simple expression emit it as
4998/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
4999/// UDR combiner function.
5000static void emitReductionCombiner(CodeGenFunction &CGF,
5001 const Expr *ReductionOp) {
5002 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5003 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5004 if (const auto *DRE =
5005 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
5006 if (const auto *DRD =
5007 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
5008 std::pair<llvm::Function *, llvm::Function *> Reduction =
5009 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5010 RValue Func = RValue::get(Reduction.first);
5011 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5012 CGF.EmitIgnoredExpr(ReductionOp);
5013 return;
5014 }
5015 CGF.EmitIgnoredExpr(ReductionOp);
5016}
5017
5018llvm::Function *CGOpenMPRuntime::emitReductionFunction(
5019 StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType,
5020 ArrayRef<const Expr *> Privates, ArrayRef<const Expr *> LHSExprs,
5021 ArrayRef<const Expr *> RHSExprs, ArrayRef<const Expr *> ReductionOps) {
5022 ASTContext &C = CGM.getContext();
5023
5024 // void reduction_func(void *LHSArg, void *RHSArg);
5025 FunctionArgList Args;
5026 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5027 ImplicitParamDecl::Other);
5028 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5029 ImplicitParamDecl::Other);
5030 Args.push_back(&LHSArg);
5031 Args.push_back(&RHSArg);
5032 const auto &CGFI =
5033 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5034 std::string Name = getReductionFuncName(ReducerName);
5035 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5036 llvm::GlobalValue::InternalLinkage, Name,
5037 &CGM.getModule());
5038 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
5039 Fn->setDoesNotRecurse();
5040 CodeGenFunction CGF(CGM);
5041 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
5042
5043 // Dst = (void*[n])(LHSArg);
5044 // Src = (void*[n])(RHSArg);
5045 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5046 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5047 ArgsElemType->getPointerTo()),
5048 ArgsElemType, CGF.getPointerAlign());
5049 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5050 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5051 ArgsElemType->getPointerTo()),
5052 ArgsElemType, CGF.getPointerAlign());
5053
5054 // ...
5055 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5056 // ...
5057 CodeGenFunction::OMPPrivateScope Scope(CGF);
5058 const auto *IPriv = Privates.begin();
5059 unsigned Idx = 0;
5060 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5061 const auto *RHSVar =
5062 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5063 Scope.addPrivate(RHSVar, emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar));
5064 const auto *LHSVar =
5065 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5066 Scope.addPrivate(LHSVar, emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar));
5067 QualType PrivTy = (*IPriv)->getType();
5068 if (PrivTy->isVariablyModifiedType()) {
5069 // Get array size and emit VLA type.
5070 ++Idx;
5071 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
5072 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
5073 const VariableArrayType *VLA =
5074 CGF.getContext().getAsVariableArrayType(PrivTy);
5075 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
5076 CodeGenFunction::OpaqueValueMapping OpaqueMap(
5077 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
5078 CGF.EmitVariablyModifiedType(PrivTy);
5079 }
5080 }
5081 Scope.Privatize();
5082 IPriv = Privates.begin();
5083 const auto *ILHS = LHSExprs.begin();
5084 const auto *IRHS = RHSExprs.begin();
5085 for (const Expr *E : ReductionOps) {
5086 if ((*IPriv)->getType()->isArrayType()) {
5087 // Emit reduction for array section.
5088 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5089 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5090 EmitOMPAggregateReduction(
5091 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5092 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5093 emitReductionCombiner(CGF, E);
5094 });
5095 } else {
5096 // Emit reduction for array subscript or single variable.
5097 emitReductionCombiner(CGF, E);
5098 }
5099 ++IPriv;
5100 ++ILHS;
5101 ++IRHS;
5102 }
5103 Scope.ForceCleanup();
5104 CGF.FinishFunction();
5105 return Fn;
5106}
5107
5108void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5109 const Expr *ReductionOp,
5110 const Expr *PrivateRef,
5111 const DeclRefExpr *LHS,
5112 const DeclRefExpr *RHS) {
5113 if (PrivateRef->getType()->isArrayType()) {
5114 // Emit reduction for array section.
5115 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5116 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
5117 EmitOMPAggregateReduction(
5118 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5119 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5120 emitReductionCombiner(CGF, ReductionOp);
5121 });
5122 } else {
5123 // Emit reduction for array subscript or single variable.
5124 emitReductionCombiner(CGF, ReductionOp);
5125 }
5126}
5127
5128void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
5129 ArrayRef<const Expr *> Privates,
5130 ArrayRef<const Expr *> LHSExprs,
5131 ArrayRef<const Expr *> RHSExprs,
5132 ArrayRef<const Expr *> ReductionOps,
5133 ReductionOptionsTy Options) {
5134 if (!CGF.HaveInsertPoint())
5135 return;
5136
5137 bool WithNowait = Options.WithNowait;
5138 bool SimpleReduction = Options.SimpleReduction;
5139
5140 // Next code should be emitted for reduction:
5141 //
5142 // static kmp_critical_name lock = { 0 };
5143 //
5144 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5145 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5146 // ...
5147 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5148 // *(Type<n>-1*)rhs[<n>-1]);
5149 // }
5150 //
5151 // ...
5152 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5153 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5154 // RedList, reduce_func, &<lock>)) {
5155 // case 1:
5156 // ...
5157 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5158 // ...
5159 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5160 // break;
5161 // case 2:
5162 // ...
5163 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5164 // ...
5165 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
5166 // break;
5167 // default:;
5168 // }
5169 //
5170 // if SimpleReduction is true, only the next code is generated:
5171 // ...
5172 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5173 // ...
5174
5175 ASTContext &C = CGM.getContext();
5176
5177 if (SimpleReduction) {
5178 CodeGenFunction::RunCleanupsScope Scope(CGF);
5179 const auto *IPriv = Privates.begin();
5180 const auto *ILHS = LHSExprs.begin();
5181 const auto *IRHS = RHSExprs.begin();
5182 for (const Expr *E : ReductionOps) {
5183 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5184 cast<DeclRefExpr>(*IRHS));
5185 ++IPriv;
5186 ++ILHS;
5187 ++IRHS;
5188 }
5189 return;
5190 }
5191
5192 // 1. Build a list of reduction variables.
5193 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
5194 auto Size = RHSExprs.size();
5195 for (const Expr *E : Privates) {
5196 if (E->getType()->isVariablyModifiedType())
5197 // Reserve place for array size.
5198 ++Size;
5199 }
5200 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
5201 QualType ReductionArrayTy =
5202 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
5203 /*IndexTypeQuals=*/0);
5204 Address ReductionList =
5205 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
5206 const auto *IPriv = Privates.begin();
5207 unsigned Idx = 0;
5208 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5209 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
5210 CGF.Builder.CreateStore(
5211 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5212 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy),
5213 Elem);
5214 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5215 // Store array size.
5216 ++Idx;
5217 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
5218 llvm::Value *Size = CGF.Builder.CreateIntCast(
5219 CGF.getVLASize(
5220 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
5221 .NumElts,
5222 CGF.SizeTy, /*isSigned=*/false);
5223 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5224 Elem);
5225 }
5226 }
5227
5228 // 2. Emit reduce_func().
5229 llvm::Function *ReductionFn = emitReductionFunction(
5230 CGF.CurFn->getName(), Loc, CGF.ConvertTypeForMem(ReductionArrayTy),
5231 Privates, LHSExprs, RHSExprs, ReductionOps);
5232
5233 // 3. Create static kmp_critical_name lock = { 0 };
5234 std::string Name = getName({"reduction"});
5235 llvm::Value *Lock = getCriticalRegionLock(Name);
5236
5237 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5238 // RedList, reduce_func, &<lock>);
5239 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5240 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5241 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5242 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5243 ReductionList.getPointer(), CGF.VoidPtrTy);
5244 llvm::Value *Args[] = {
5245 IdentTLoc, // ident_t *<loc>
5246 ThreadId, // i32 <gtid>
5247 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5248 ReductionArrayTySize, // size_type sizeof(RedList)
5249 RL, // void *RedList
5250 ReductionFn, // void (*) (void *, void *) <reduce_func>
5251 Lock // kmp_critical_name *&<lock>
5252 };
5253 llvm::Value *Res = CGF.EmitRuntimeCall(
5254 OMPBuilder.getOrCreateRuntimeFunction(
5255 CGM.getModule(),
5256 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5257 Args);
5258
5259 // 5. Build switch(res)
5260 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5261 llvm::SwitchInst *SwInst =
5262 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
5263
5264 // 6. Build case 1:
5265 // ...
5266 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5267 // ...
5268 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5269 // break;
5270 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
5271 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5272 CGF.EmitBlock(Case1BB);
5273
5274 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5275 llvm::Value *EndArgs[] = {
5276 IdentTLoc, // ident_t *<loc>
5277 ThreadId, // i32 <gtid>
5278 Lock // kmp_critical_name *&<lock>
5279 };
5280 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5281 CodeGenFunction &CGF, PrePostActionTy &Action) {
5282 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
5283 const auto *IPriv = Privates.begin();
5284 const auto *ILHS = LHSExprs.begin();
5285 const auto *IRHS = RHSExprs.begin();
5286 for (const Expr *E : ReductionOps) {
5287 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5288 cast<DeclRefExpr>(*IRHS));
5289 ++IPriv;
5290 ++ILHS;
5291 ++IRHS;
5292 }
5293 };
5294 RegionCodeGenTy RCG(CodeGen);
5295 CommonActionTy Action(
5296 nullptr, std::nullopt,
5297 OMPBuilder.getOrCreateRuntimeFunction(
5298 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5299 : OMPRTL___kmpc_end_reduce),
5300 EndArgs);
5301 RCG.setAction(Action);
5302 RCG(CGF);
5303
5304 CGF.EmitBranch(DefaultBB);
5305
5306 // 7. Build case 2:
5307 // ...
5308 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5309 // ...
5310 // break;
5311 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
5312 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5313 CGF.EmitBlock(Case2BB);
5314
5315 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5316 CodeGenFunction &CGF, PrePostActionTy &Action) {
5317 const auto *ILHS = LHSExprs.begin();
5318 const auto *IRHS = RHSExprs.begin();
5319 const auto *IPriv = Privates.begin();
5320 for (const Expr *E : ReductionOps) {
5321 const Expr *XExpr = nullptr;
5322 const Expr *EExpr = nullptr;
5323 const Expr *UpExpr = nullptr;
5324 BinaryOperatorKind BO = BO_Comma;
5325 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
5326 if (BO->getOpcode() == BO_Assign) {
5327 XExpr = BO->getLHS();
5328 UpExpr = BO->getRHS();
5329 }
5330 }
5331 // Try to emit update expression as a simple atomic.
5332 const Expr *RHSExpr = UpExpr;
5333 if (RHSExpr) {
5334 // Analyze RHS part of the whole expression.
5335 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5336 RHSExpr->IgnoreParenImpCasts())) {
5337 // If this is a conditional operator, analyze its condition for
5338 // min/max reduction operator.
5339 RHSExpr = ACO->getCond();
5340 }
5341 if (const auto *BORHS =
5342 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5343 EExpr = BORHS->getRHS();
5344 BO = BORHS->getOpcode();
5345 }
5346 }
5347 if (XExpr) {
5348 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5349 auto &&AtomicRedGen = [BO, VD,
5350 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5351 const Expr *EExpr, const Expr *UpExpr) {
5352 LValue X = CGF.EmitLValue(XExpr);
5353 RValue E;
5354 if (EExpr)
5355 E = CGF.EmitAnyExpr(EExpr);
5356 CGF.EmitOMPAtomicSimpleUpdateExpr(
5357 X, E, BO, /*IsXLHSInRHSPart=*/true,
5358 llvm::AtomicOrdering::Monotonic, Loc,
5359 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
5360 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5361 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5362 CGF.emitOMPSimpleStore(
5363 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5364 VD->getType().getNonReferenceType(), Loc);
5365 PrivateScope.addPrivate(VD, LHSTemp);
5366 (void)PrivateScope.Privatize();
5367 return CGF.EmitAnyExpr(UpExpr);
5368 });
5369 };
5370 if ((*IPriv)->getType()->isArrayType()) {
5371 // Emit atomic reduction for array section.
5372 const auto *RHSVar =
5373 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5374 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5375 AtomicRedGen, XExpr, EExpr, UpExpr);
5376 } else {
5377 // Emit atomic reduction for array subscript or single variable.
5378 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5379 }
5380 } else {
5381 // Emit as a critical region.
5382 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
5383 const Expr *, const Expr *) {
5384 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
5385 std::string Name = RT.getName({"atomic_reduction"});
5386 RT.emitCriticalRegion(
5387 CGF, Name,
5388 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5389 Action.Enter(CGF);
5390 emitReductionCombiner(CGF, E);
5391 },
5392 Loc);
5393 };
5394 if ((*IPriv)->getType()->isArrayType()) {
5395 const auto *LHSVar =
5396 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5397 const auto *RHSVar =
5398 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5399 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5400 CritRedGen);
5401 } else {
5402 CritRedGen(CGF, nullptr, nullptr, nullptr);
5403 }
5404 }
5405 ++ILHS;
5406 ++IRHS;
5407 ++IPriv;
5408 }
5409 };
5410 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5411 if (!WithNowait) {
5412 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5413 llvm::Value *EndArgs[] = {
5414 IdentTLoc, // ident_t *<loc>
5415 ThreadId, // i32 <gtid>
5416 Lock // kmp_critical_name *&<lock>
5417 };
5418 CommonActionTy Action(nullptr, std::nullopt,
5419 OMPBuilder.getOrCreateRuntimeFunction(
5420 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5421 EndArgs);
5422 AtomicRCG.setAction(Action);
5423 AtomicRCG(CGF);
5424 } else {
5425 AtomicRCG(CGF);
5426 }
5427
5428 CGF.EmitBranch(DefaultBB);
5429 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5430}
5431
5432/// Generates unique name for artificial threadprivate variables.
5433/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5434static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5435 const Expr *Ref) {
5436 SmallString<256> Buffer;
5437 llvm::raw_svector_ostream Out(Buffer);
5438 const clang::DeclRefExpr *DE;
5439 const VarDecl *D = ::getBaseDecl(Ref, DE);
5440 if (!D)
5441 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5442 D = D->getCanonicalDecl();
5443 std::string Name = CGM.getOpenMPRuntime().getName(
5444 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
5445 Out << Prefix << Name << "_"
5446 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
5447 return std::string(Out.str());
5448}
5449
5450/// Emits reduction initializer function:
5451/// \code
5452/// void @.red_init(void* %arg, void* %orig) {
5453/// %0 = bitcast void* %arg to <type>*
5454/// store <type> <init>, <type>* %0
5455/// ret void
5456/// }
5457/// \endcode
5458static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
5459 SourceLocation Loc,
5460 ReductionCodeGen &RCG, unsigned N) {
5461 ASTContext &C = CGM.getContext();
5462 QualType VoidPtrTy = C.VoidPtrTy;
5463 VoidPtrTy.addRestrict();
5464 FunctionArgList Args;
5465 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy,
5466 ImplicitParamDecl::Other);
5467 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy,
5468 ImplicitParamDecl::Other);
5469 Args.emplace_back(&Param);
5470 Args.emplace_back(&ParamOrig);
5471 const auto &FnInfo =
5472 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5473 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
5474 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
5475 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5476 Name, &CGM.getModule());
5477 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
5478 Fn->setDoesNotRecurse();
5479 CodeGenFunction CGF(CGM);
5480 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
5481 QualType PrivateType = RCG.getPrivateType(N);
5482 Address PrivateAddr = CGF.EmitLoadOfPointer(
5483 CGF.Builder.CreateElementBitCast(
5484 CGF.GetAddrOfLocalVar(&Param),
5485 CGF.ConvertTypeForMem(PrivateType)->getPointerTo()),
5486 C.getPointerType(PrivateType)->castAs<PointerType>());
5487 llvm::Value *Size = nullptr;
5488 // If the size of the reduction item is non-constant, load it from global
5489 // threadprivate variable.
5490 if (RCG.getSizes(N).second) {
5491 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5492 CGF, CGM.getContext().getSizeType(),
5493 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
5494 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
5495 CGM.getContext().getSizeType(), Loc);
5496 }
5497 RCG.emitAggregateType(CGF, N, Size);
5498 Address OrigAddr = Address::invalid();
5499 // If initializer uses initializer from declare reduction construct, emit a
5500 // pointer to the address of the original reduction item (reuired by reduction
5501 // initializer)
5502 if (RCG.usesReductionInitializer(N)) {
5503 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig);
5504 OrigAddr = CGF.EmitLoadOfPointer(
5505 SharedAddr,
5506 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
5507 }
5508 // Emit the initializer:
5509 // %0 = bitcast void* %arg to <type>*
5510 // store <type> <init>, <type>* %0
5511 RCG.emitInitialization(CGF, N, PrivateAddr, OrigAddr,
5512 [](CodeGenFunction &) { return false; });
5513 CGF.FinishFunction();
5514 return Fn;
5515}
5516
5517/// Emits reduction combiner function:
5518/// \code
5519/// void @.red_comb(void* %arg0, void* %arg1) {
5520/// %lhs = bitcast void* %arg0 to <type>*
5521/// %rhs = bitcast void* %arg1 to <type>*
5522/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
5523/// store <type> %2, <type>* %lhs
5524/// ret void
5525/// }
5526/// \endcode
5527static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
5528 SourceLocation Loc,
5529 ReductionCodeGen &RCG, unsigned N,
5530 const Expr *ReductionOp,
5531 const Expr *LHS, const Expr *RHS,
5532 const Expr *PrivateRef) {
5533 ASTContext &C = CGM.getContext();
5534 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
5535 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
5536 FunctionArgList Args;
5537 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
5538 C.VoidPtrTy, ImplicitParamDecl::Other);
5539 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5540 ImplicitParamDecl::Other);
5541 Args.emplace_back(&ParamInOut);
5542 Args.emplace_back(&ParamIn);
5543 const auto &FnInfo =
5544 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5545 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
5546 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
5547 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5548 Name, &CGM.getModule());
5549 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
5550 Fn->setDoesNotRecurse();
5551 CodeGenFunction CGF(CGM);
5552 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
5553 llvm::Value *Size = nullptr;
5554 // If the size of the reduction item is non-constant, load it from global
5555 // threadprivate variable.
5556 if (RCG.getSizes(N).second) {
5557 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5558 CGF, CGM.getContext().getSizeType(),
5559 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
5560 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
5561 CGM.getContext().getSizeType(), Loc);
5562 }
5563 RCG.emitAggregateType(CGF, N, Size);
5564 // Remap lhs and rhs variables to the addresses of the function arguments.
5565 // %lhs = bitcast void* %arg0 to <type>*
5566 // %rhs = bitcast void* %arg1 to <type>*
5567 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5568 PrivateScope.addPrivate(
5569 LHSVD,
5570 // Pull out the pointer to the variable.
5571 CGF.EmitLoadOfPointer(
5572 CGF.Builder.CreateElementBitCast(
5573 CGF.GetAddrOfLocalVar(&ParamInOut),
5574 CGF.ConvertTypeForMem(LHSVD->getType())->getPointerTo()),
5575 C.getPointerType(LHSVD->getType())->castAs<PointerType>()));
5576 PrivateScope.addPrivate(
5577 RHSVD,
5578 // Pull out the pointer to the variable.
5579 CGF.EmitLoadOfPointer(
5580 CGF.Builder.CreateElementBitCast(
5581 CGF.GetAddrOfLocalVar(&ParamIn),
5582 CGF.ConvertTypeForMem(RHSVD->getType())->getPointerTo()),
5583 C.getPointerType(RHSVD->getType())->castAs<PointerType>()));
5584 PrivateScope.Privatize();
5585 // Emit the combiner body:
5586 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
5587 // store <type> %2, <type>* %lhs
5588 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
5589 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
5590 cast<DeclRefExpr>(RHS));
5591 CGF.FinishFunction();
5592 return Fn;
5593}
5594
5595/// Emits reduction finalizer function:
5596/// \code
5597/// void @.red_fini(void* %arg) {
5598/// %0 = bitcast void* %arg to <type>*
5599/// <destroy>(<type>* %0)
5600/// ret void
5601/// }
5602/// \endcode
5603static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
5604 SourceLocation Loc,
5605 ReductionCodeGen &RCG, unsigned N) {
5606 if (!RCG.needCleanups(N))
5607 return nullptr;
5608 ASTContext &C = CGM.getContext();
5609 FunctionArgList Args;
5610 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5611 ImplicitParamDecl::Other);
5612 Args.emplace_back(&Param);
5613 const auto &FnInfo =
5614 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5615 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
5616 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
5617 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5618 Name, &CGM.getModule());
5619 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
5620 Fn->setDoesNotRecurse();
5621 CodeGenFunction CGF(CGM);
5622 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
5623 Address PrivateAddr = CGF.EmitLoadOfPointer(
5624 CGF.GetAddrOfLocalVar(&Param), C.VoidPtrTy.castAs<PointerType>());
5625 llvm::Value *Size = nullptr;
5626 // If the size of the reduction item is non-constant, load it from global
5627 // threadprivate variable.
5628 if (RCG.getSizes(N).second) {
5629 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5630 CGF, CGM.getContext().getSizeType(),
5631 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
5632 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
5633 CGM.getContext().getSizeType(), Loc);
5634 }
5635 RCG.emitAggregateType(CGF, N, Size);
5636 // Emit the finalizer body:
5637 // <destroy>(<type>* %0)
5638 RCG.emitCleanups(CGF, N, PrivateAddr);
5639 CGF.FinishFunction(Loc);
5640 return Fn;
5641}
5642
5643llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
5644 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
5645 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
5646 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
5647 return nullptr;
5648
5649 // Build typedef struct:
5650 // kmp_taskred_input {
5651 // void *reduce_shar; // shared reduction item
5652 // void *reduce_orig; // original reduction item used for initialization
5653 // size_t reduce_size; // size of data item
5654 // void *reduce_init; // data initialization routine
5655 // void *reduce_fini; // data finalization routine
5656 // void *reduce_comb; // data combiner routine
5657 // kmp_task_red_flags_t flags; // flags for additional info from compiler
5658 // } kmp_taskred_input_t;
5659 ASTContext &C = CGM.getContext();
5660 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t");
5661 RD->startDefinition();
5662 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
5663 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
5664 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
5665 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
5666 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
5667 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
5668 const FieldDecl *FlagsFD = addFieldToRecordDecl(
5669 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
5670 RD->completeDefinition();
5671 QualType RDType = C.getRecordType(RD);
5672 unsigned Size = Data.ReductionVars.size();
5673 llvm::APInt ArraySize(/*numBits=*/64, Size);
5674 QualType ArrayRDType = C.getConstantArrayType(
5675 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
5676 // kmp_task_red_input_t .rd_input.[Size];
5677 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
5678 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs,
5679 Data.ReductionCopies, Data.ReductionOps);
5680 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5681 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
5682 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
5683 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
5684 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
5685 TaskRedInput.getElementType(), TaskRedInput.getPointer(), Idxs,
5686 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
5687 ".rd_input.gep.");
5688 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
5689 // ElemLVal.reduce_shar = &Shareds[Cnt];
5690 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
5691 RCG.emitSharedOrigLValue(CGF, Cnt);
5692 llvm::Value *CastedShared =
5693 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF));
5694 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
5695 // ElemLVal.reduce_orig = &Origs[Cnt];
5696 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD);
5697 llvm::Value *CastedOrig =
5698 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF));
5699 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal);
5700 RCG.emitAggregateType(CGF, Cnt);
5701 llvm::Value *SizeValInChars;
5702 llvm::Value *SizeVal;
5703 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
5704 // We use delayed creation/initialization for VLAs and array sections. It is
5705 // required because runtime does not provide the way to pass the sizes of
5706 // VLAs/array sections to initializer/combiner/finalizer functions. Instead
5707 // threadprivate global variables are used to store these values and use
5708 // them in the functions.
5709 bool DelayedCreation = !!SizeVal;
5710 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
5711 /*isSigned=*/false);
5712 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
5713 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
5714 // ElemLVal.reduce_init = init;
5715 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
5716 llvm::Value *InitAddr =
5717 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
5718 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
5719 // ElemLVal.reduce_fini = fini;
5720 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
5721 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
5722 llvm::Value *FiniAddr = Fini
5723 ? CGF.EmitCastToVoidPtr(Fini)
5724 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
5725 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
5726 // ElemLVal.reduce_comb = comb;
5727 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
5728 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
5729 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
5730 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
5731 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
5732 // ElemLVal.flags = 0;
5733 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
5734 if (DelayedCreation) {
5735 CGF.EmitStoreOfScalar(
5736 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
5737 FlagsLVal);
5738 } else
5739 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF),
5740 FlagsLVal.getType());
5741 }
5742 if (Data.IsReductionWithTaskMod) {
5743 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int
5744 // is_ws, int num, void *data);
5745 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc);
5746 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
5747 CGM.IntTy, /*isSigned=*/true);
5748 llvm::Value *Args[] = {
5749 IdentTLoc, GTid,
5750 llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0,
5751 /*isSigned=*/true),
5752 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
5753 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5754 TaskRedInput.getPointer(), CGM.VoidPtrTy)};
5755 return CGF.EmitRuntimeCall(
5756 OMPBuilder.getOrCreateRuntimeFunction(
5757 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
5758 Args);
5759 }
5760 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data);
5761 llvm::Value *Args[] = {
5762 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
5763 /*isSigned=*/true),
5764 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
5765 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
5766 CGM.VoidPtrTy)};
5767 return CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
5768 CGM.getModule(), OMPRTL___kmpc_taskred_init),
5769 Args);
5770}
5771
5772void CGOpenMPRuntime::emitTaskReductionFini(CodeGenFunction &CGF,
5773 SourceLocation Loc,
5774 bool IsWorksharingReduction) {
5775 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int
5776 // is_ws, int num, void *data);
5777 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc);
5778 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
5779 CGM.IntTy, /*isSigned=*/true);
5780 llvm::Value *Args[] = {IdentTLoc, GTid,
5781 llvm::ConstantInt::get(CGM.IntTy,
5782 IsWorksharingReduction ? 1 : 0,
5783 /*isSigned=*/true)};
5784 (void)CGF.EmitRuntimeCall(
5785 OMPBuilder.getOrCreateRuntimeFunction(
5786 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
5787 Args);
5788}
5789
5790void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
5791 SourceLocation Loc,
5792 ReductionCodeGen &RCG,
5793 unsigned N) {
5794 auto Sizes = RCG.getSizes(N);
5795 // Emit threadprivate global variable if the type is non-constant
5796 // (Sizes.second = nullptr).
5797 if (Sizes.second) {
5798 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
5799 /*isSigned=*/false);
5800 Address SizeAddr = getAddrOfArtificialThreadPrivate(
5801 CGF, CGM.getContext().getSizeType(),
5802 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
5803 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
5804 }
5805}
5806
5807Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
5808 SourceLocation Loc,
5809 llvm::Value *ReductionsPtr,
5810 LValue SharedLVal) {
5811 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
5812 // *d);
5813 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
5814 CGM.IntTy,
5815 /*isSigned=*/true),
5816 ReductionsPtr,
5817 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5818 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)};
5819 return Address(
5820 CGF.EmitRuntimeCall(
5821 OMPBuilder.getOrCreateRuntimeFunction(
5822 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
5823 Args),
5824 CGF.Int8Ty, SharedLVal.getAlignment());
5825}
5826
5827void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc,
5828 const OMPTaskDataTy &Data) {
5829 if (!CGF.HaveInsertPoint())
5830 return;
5831
5832 if (CGF.CGM.getLangOpts().OpenMPIRBuilder && Data.Dependences.empty()) {
5833 // TODO: Need to support taskwait with dependences in the OpenMPIRBuilder.
5834 OMPBuilder.createTaskwait(CGF.Builder);
5835 } else {
5836 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5837 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5838 auto &M = CGM.getModule();
5839 Address DependenciesArray = Address::invalid();
5840 llvm::Value *NumOfElements;
5841 std::tie(NumOfElements, DependenciesArray) =
5842 emitDependClause(CGF, Data.Dependences, Loc);
5843 if (!Data.Dependences.empty()) {
5844 llvm::Value *DepWaitTaskArgs[7];
5845 DepWaitTaskArgs[0] = UpLoc;
5846 DepWaitTaskArgs[1] = ThreadID;
5847 DepWaitTaskArgs[2] = NumOfElements;
5848 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5849 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5850 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5851 DepWaitTaskArgs[6] =
5852 llvm::ConstantInt::get(CGF.Int32Ty, Data.HasNowaitClause);
5853
5854 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5855
5856 // Build void __kmpc_omp_taskwait_deps_51(ident_t *, kmp_int32 gtid,
5857 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5858 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list,
5859 // kmp_int32 has_no_wait); if dependence info is specified.
5860 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
5861 M, OMPRTL___kmpc_omp_taskwait_deps_51),
5862 DepWaitTaskArgs);
5863
5864 } else {
5865
5866 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
5867 // global_tid);
5868 llvm::Value *Args[] = {UpLoc, ThreadID};
5869 // Ignore return result until untied tasks are supported.
5870 CGF.EmitRuntimeCall(
5871 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
5872 Args);
5873 }
5874 }
5875
5876 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5877 Region->emitUntiedSwitch(CGF);
5878}
5879
5880void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
5881 OpenMPDirectiveKind InnerKind,
5882 const RegionCodeGenTy &CodeGen,
5883 bool HasCancel) {
5884 if (!CGF.HaveInsertPoint())
5885 return;
5886 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel,
5887 InnerKind != OMPD_critical &&
5888 InnerKind != OMPD_master &&
5889 InnerKind != OMPD_masked);
5890 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
5891}
5892
5893namespace {
5894enum RTCancelKind {
5895 CancelNoreq = 0,
5896 CancelParallel = 1,
5897 CancelLoop = 2,
5898 CancelSections = 3,
5899 CancelTaskgroup = 4
5900};
5901} // anonymous namespace
5902
5903static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
5904 RTCancelKind CancelKind = CancelNoreq;
5905 if (CancelRegion == OMPD_parallel)
5906 CancelKind = CancelParallel;
5907 else if (CancelRegion == OMPD_for)
5908 CancelKind = CancelLoop;
5909 else if (CancelRegion == OMPD_sections)
5910 CancelKind = CancelSections;
5911 else {
5912 assert(CancelRegion == OMPD_taskgroup)(static_cast <bool> (CancelRegion == OMPD_taskgroup) ? void
(0) : __assert_fail ("CancelRegion == OMPD_taskgroup", "clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 5912, __extension__ __PRETTY_FUNCTION__))
;
5913 CancelKind = CancelTaskgroup;
5914 }
5915 return CancelKind;
5916}
5917
5918void CGOpenMPRuntime::emitCancellationPointCall(
5919 CodeGenFunction &CGF, SourceLocation Loc,
5920 OpenMPDirectiveKind CancelRegion) {
5921 if (!CGF.HaveInsertPoint())
5922 return;
5923 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
5924 // global_tid, kmp_int32 cncl_kind);
5925 if (auto *OMPRegionInfo =
5926 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
5927 // For 'cancellation point taskgroup', the task region info may not have a
5928 // cancel. This may instead happen in another adjacent task.
5929 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
5930 llvm::Value *Args[] = {
5931 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
5932 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
5933 // Ignore return result until untied tasks are supported.
5934 llvm::Value *Result = CGF.EmitRuntimeCall(
5935 OMPBuilder.getOrCreateRuntimeFunction(
5936 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
5937 Args);
5938 // if (__kmpc_cancellationpoint()) {
5939 // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only
5940 // exit from construct;
5941 // }
5942 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
5943 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
5944 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
5945 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
5946 CGF.EmitBlock(ExitBB);
5947 if (CancelRegion == OMPD_parallel)
5948 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
5949 // exit from construct;
5950 CodeGenFunction::JumpDest CancelDest =
5951 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
5952 CGF.EmitBranchThroughCleanup(CancelDest);
5953 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
5954 }
5955 }
5956}
5957
5958void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
5959 const Expr *IfCond,
5960 OpenMPDirectiveKind CancelRegion) {
5961 if (!CGF.HaveInsertPoint())
5962 return;
5963 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
5964 // kmp_int32 cncl_kind);
5965 auto &M = CGM.getModule();
5966 if (auto *OMPRegionInfo =
5967 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
5968 auto &&ThenGen = [this, &M, Loc, CancelRegion,
5969 OMPRegionInfo](CodeGenFunction &CGF, PrePostActionTy &) {
5970 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
5971 llvm::Value *Args[] = {
5972 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
5973 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
5974 // Ignore return result until untied tasks are supported.
5975 llvm::Value *Result = CGF.EmitRuntimeCall(
5976 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
5977 // if (__kmpc_cancel()) {
5978 // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only
5979 // exit from construct;
5980 // }
5981 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
5982 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
5983 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
5984 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
5985 CGF.EmitBlock(ExitBB);
5986 if (CancelRegion == OMPD_parallel)
5987 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
5988 // exit from construct;
5989 CodeGenFunction::JumpDest CancelDest =
5990 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
5991 CGF.EmitBranchThroughCleanup(CancelDest);
5992 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
5993 };
5994 if (IfCond) {
5995 emitIfClause(CGF, IfCond, ThenGen,
5996 [](CodeGenFunction &, PrePostActionTy &) {});
5997 } else {
5998 RegionCodeGenTy ThenRCG(ThenGen);
5999 ThenRCG(CGF);
6000 }
6001 }
6002}
6003
6004namespace {
6005/// Cleanup action for uses_allocators support.
6006class OMPUsesAllocatorsActionTy final : public PrePostActionTy {
6007 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators;
6008
6009public:
6010 OMPUsesAllocatorsActionTy(
6011 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6012 : Allocators(Allocators) {}
6013 void Enter(CodeGenFunction &CGF) override {
6014 if (!CGF.HaveInsertPoint())
6015 return;
6016 for (const auto &AllocatorData : Allocators) {
6017 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsInit(
6018 CGF, AllocatorData.first, AllocatorData.second);
6019 }
6020 }
6021 void Exit(CodeGenFunction &CGF) override {
6022 if (!CGF.HaveInsertPoint())
6023 return;
6024 for (const auto &AllocatorData : Allocators) {
6025 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsFini(CGF,
6026 AllocatorData.first);
6027 }
6028 }
6029};
6030} // namespace
6031
6032void CGOpenMPRuntime::emitTargetOutlinedFunction(
6033 const OMPExecutableDirective &D, StringRef ParentName,
6034 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6035 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
6036 assert(!ParentName.empty() && "Invalid target entry parent name!")(static_cast <bool> (!ParentName.empty() && "Invalid target entry parent name!"
) ? void (0) : __assert_fail ("!ParentName.empty() && \"Invalid target entry parent name!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6036, __extension__
__PRETTY_FUNCTION__))
;
6037 HasEmittedTargetRegion = true;
6038 SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators;
6039 for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) {
6040 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
6041 const OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
6042 if (!D.AllocatorTraits)
6043 continue;
6044 Allocators.emplace_back(D.Allocator, D.AllocatorTraits);
6045 }
6046 }
6047 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6048 CodeGen.setAction(UsesAllocatorAction);
6049 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6050 IsOffloadEntry, CodeGen);
6051}
6052
6053void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF,
6054 const Expr *Allocator,
6055 const Expr *AllocatorTraits) {
6056 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc());
6057 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true);
6058 // Use default memspace handle.
6059 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
6060 llvm::Value *NumTraits = llvm::ConstantInt::get(
6061 CGF.IntTy, cast<ConstantArrayType>(
6062 AllocatorTraits->getType()->getAsArrayTypeUnsafe())
6063 ->getSize()
6064 .getLimitedValue());
6065 LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits);
6066 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6067 AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy, CGF.VoidPtrTy);
6068 AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy,
6069 AllocatorTraitsLVal.getBaseInfo(),
6070 AllocatorTraitsLVal.getTBAAInfo());
6071 llvm::Value *Traits =
6072 CGF.EmitLoadOfScalar(AllocatorTraitsLVal, AllocatorTraits->getExprLoc());
6073
6074 llvm::Value *AllocatorVal =
6075 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
6076 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6077 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6078 // Store to allocator.
6079 CGF.EmitVarDecl(*cast<VarDecl>(
6080 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl()));
6081 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts());
6082 AllocatorVal =
6083 CGF.EmitScalarConversion(AllocatorVal, CGF.getContext().VoidPtrTy,
6084 Allocator->getType(), Allocator->getExprLoc());
6085 CGF.EmitStoreOfScalar(AllocatorVal, AllocatorLVal);
6086}
6087
6088void CGOpenMPRuntime::emitUsesAllocatorsFini(CodeGenFunction &CGF,
6089 const Expr *Allocator) {
6090 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc());
6091 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true);
6092 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts());
6093 llvm::Value *AllocatorVal =
6094 CGF.EmitLoadOfScalar(AllocatorLVal, Allocator->getExprLoc());
6095 AllocatorVal = CGF.EmitScalarConversion(AllocatorVal, Allocator->getType(),
6096 CGF.getContext().VoidPtrTy,
6097 Allocator->getExprLoc());
6098 (void)CGF.EmitRuntimeCall(
6099 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
6100 OMPRTL___kmpc_destroy_allocator),
6101 {ThreadId, AllocatorVal});
6102}
6103
6104void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6105 const OMPExecutableDirective &D, StringRef ParentName,
6106 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6107 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
6108
6109 auto EntryInfo =
6110 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), ParentName);
6111
6112 CodeGenFunction CGF(CGM, true);
6113 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6114 [&CGF, &D, &CodeGen](StringRef EntryFnName) {
6115 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6116
6117 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
6118 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6119 return CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc());
6120 };
6121
6122 // Get NumTeams and ThreadLimit attributes
6123 int32_t DefaultValTeams = -1;
6124 int32_t DefaultValThreads = -1;
6125 getNumTeamsExprForTargetDirective(CGF, D, DefaultValTeams);
6126 getNumThreadsExprForTargetDirective(CGF, D, DefaultValThreads);
6127
6128 OMPBuilder.emitTargetRegionFunction(EntryInfo, GenerateOutlinedFunction,
6129 DefaultValTeams, DefaultValThreads,
6130 IsOffloadEntry, OutlinedFn, OutlinedFnID);
6131
6132 if (OutlinedFn != nullptr)
6133 CGM.getTargetCodeGenInfo().setTargetAttributes(nullptr, OutlinedFn, CGM);
6134}
6135
6136/// Checks if the expression is constant or does not have non-trivial function
6137/// calls.
6138static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6139 // We can skip constant expressions.
6140 // We can skip expressions with trivial calls or simple expressions.
6141 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6142 !E->hasNonTrivialCall(Ctx)) &&
6143 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6144}
6145
6146const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6147 const Stmt *Body) {
6148 const Stmt *Child = Body->IgnoreContainers();
6149 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6150 Child = nullptr;
6151 for (const Stmt *S : C->body()) {
6152 if (const auto *E = dyn_cast<Expr>(S)) {
6153 if (isTrivial(Ctx, E))
6154 continue;
6155 }
6156 // Some of the statements can be ignored.
6157 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6158 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6159 continue;
6160 // Analyze declarations.
6161 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6162 if (llvm::all_of(DS->decls(), [](const Decl *D) {
6163 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6164 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6165 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6166 isa<UsingDirectiveDecl>(D) ||
6167 isa<OMPDeclareReductionDecl>(D) ||
6168 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6169 return true;
6170 const auto *VD = dyn_cast<VarDecl>(D);
6171 if (!VD)
6172 return false;
6173 return VD->hasGlobalStorage() || !VD->isUsed();
6174 }))
6175 continue;
6176 }
6177 // Found multiple children - cannot get the one child only.
6178 if (Child)
6179 return nullptr;
6180 Child = S;
6181 }
6182 if (Child)
6183 Child = Child->IgnoreContainers();
6184 }
6185 return Child;
6186}
6187
6188const Expr *CGOpenMPRuntime::getNumTeamsExprForTargetDirective(
6189 CodeGenFunction &CGF, const OMPExecutableDirective &D,
6190 int32_t &DefaultVal) {
6191
6192 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6193 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&(static_cast <bool> (isOpenMPTargetExecutionDirective(DirectiveKind
) && "Expected target-based executable directive.") ?
void (0) : __assert_fail ("isOpenMPTargetExecutionDirective(DirectiveKind) && \"Expected target-based executable directive.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6194, __extension__
__PRETTY_FUNCTION__))
6194 "Expected target-based executable directive.")(static_cast <bool> (isOpenMPTargetExecutionDirective(DirectiveKind
) && "Expected target-based executable directive.") ?
void (0) : __assert_fail ("isOpenMPTargetExecutionDirective(DirectiveKind) && \"Expected target-based executable directive.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6194, __extension__
__PRETTY_FUNCTION__))
;
6195 switch (DirectiveKind) {
6196 case OMPD_target: {
6197 const auto *CS = D.getInnermostCapturedStmt();
6198 const auto *Body =
6199 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6200 const Stmt *ChildStmt =
6201 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6202 if (const auto *NestedDir =
6203 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6204 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6205 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6206 const Expr *NumTeams =
6207 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6208 if (NumTeams->isIntegerConstantExpr(CGF.getContext()))
6209 if (auto Constant =
6210 NumTeams->getIntegerConstantExpr(CGF.getContext()))
6211 DefaultVal = Constant->getExtValue();
6212 return NumTeams;
6213 }
6214 DefaultVal = 0;
6215 return nullptr;
6216 }
6217 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6218 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) {
6219 DefaultVal = 1;
6220 return nullptr;
6221 }
6222 DefaultVal = 1;
6223 return nullptr;
6224 }
6225 // A value of -1 is used to check if we need to emit no teams region
6226 DefaultVal = -1;
6227 return nullptr;
6228 }
6229 case OMPD_target_teams:
6230 case OMPD_target_teams_distribute:
6231 case OMPD_target_teams_distribute_simd:
6232 case OMPD_target_teams_distribute_parallel_for:
6233 case OMPD_target_teams_distribute_parallel_for_simd: {
6234 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6235 const Expr *NumTeams =
6236 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6237 if (NumTeams->isIntegerConstantExpr(CGF.getContext()))
6238 if (auto Constant = NumTeams->getIntegerConstantExpr(CGF.getContext()))
6239 DefaultVal = Constant->getExtValue();
6240 return NumTeams;
6241 }
6242 DefaultVal = 0;
6243 return nullptr;
6244 }
6245 case OMPD_target_parallel:
6246 case OMPD_target_parallel_for:
6247 case OMPD_target_parallel_for_simd:
6248 case OMPD_target_simd:
6249 DefaultVal = 1;
6250 return nullptr;
6251 case OMPD_parallel:
6252 case OMPD_for:
6253 case OMPD_parallel_for:
6254 case OMPD_parallel_master:
6255 case OMPD_parallel_sections:
6256 case OMPD_for_simd:
6257 case OMPD_parallel_for_simd:
6258 case OMPD_cancel:
6259 case OMPD_cancellation_point:
6260 case OMPD_ordered:
6261 case OMPD_threadprivate:
6262 case OMPD_allocate:
6263 case OMPD_task:
6264 case OMPD_simd:
6265 case OMPD_tile:
6266 case OMPD_unroll:
6267 case OMPD_sections:
6268 case OMPD_section:
6269 case OMPD_single:
6270 case OMPD_master:
6271 case OMPD_critical:
6272 case OMPD_taskyield:
6273 case OMPD_barrier:
6274 case OMPD_taskwait:
6275 case OMPD_taskgroup:
6276 case OMPD_atomic:
6277 case OMPD_flush:
6278 case OMPD_depobj:
6279 case OMPD_scan:
6280 case OMPD_teams:
6281 case OMPD_target_data:
6282 case OMPD_target_exit_data:
6283 case OMPD_target_enter_data:
6284 case OMPD_distribute:
6285 case OMPD_distribute_simd:
6286 case OMPD_distribute_parallel_for:
6287 case OMPD_distribute_parallel_for_simd:
6288 case OMPD_teams_distribute:
6289 case OMPD_teams_distribute_simd:
6290 case OMPD_teams_distribute_parallel_for:
6291 case OMPD_teams_distribute_parallel_for_simd:
6292 case OMPD_target_update:
6293 case OMPD_declare_simd:
6294 case OMPD_declare_variant:
6295 case OMPD_begin_declare_variant:
6296 case OMPD_end_declare_variant:
6297 case OMPD_declare_target:
6298 case OMPD_end_declare_target:
6299 case OMPD_declare_reduction:
6300 case OMPD_declare_mapper:
6301 case OMPD_taskloop:
6302 case OMPD_taskloop_simd:
6303 case OMPD_master_taskloop:
6304 case OMPD_master_taskloop_simd:
6305 case OMPD_parallel_master_taskloop:
6306 case OMPD_parallel_master_taskloop_simd:
6307 case OMPD_requires:
6308 case OMPD_metadirective:
6309 case OMPD_unknown:
6310 break;
6311 default:
6312 break;
6313 }
6314 llvm_unreachable("Unexpected directive kind.")::llvm::llvm_unreachable_internal("Unexpected directive kind."
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6314)
;
6315}
6316
6317llvm::Value *CGOpenMPRuntime::emitNumTeamsForTargetDirective(
6318 CodeGenFunction &CGF, const OMPExecutableDirective &D) {
6319 assert(!CGF.getLangOpts().OpenMPIsDevice &&(static_cast <bool> (!CGF.getLangOpts().OpenMPIsDevice &&
"Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? void (0) : __assert_fail ("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6321, __extension__
__PRETTY_FUNCTION__))
6320 "Clauses associated with the teams directive expected to be emitted "(static_cast <bool> (!CGF.getLangOpts().OpenMPIsDevice &&
"Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? void (0) : __assert_fail ("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6321, __extension__
__PRETTY_FUNCTION__))
6321 "only for the host!")(static_cast <bool> (!CGF.getLangOpts().OpenMPIsDevice &&
"Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? void (0) : __assert_fail ("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6321, __extension__
__PRETTY_FUNCTION__))
;
6322 CGBuilderTy &Bld = CGF.Builder;
6323 int32_t DefaultNT = -1;
6324 const Expr *NumTeams = getNumTeamsExprForTargetDirective(CGF, D, DefaultNT);
6325 if (NumTeams != nullptr) {
6326 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6327
6328 switch (DirectiveKind) {
6329 case OMPD_target: {
6330 const auto *CS = D.getInnermostCapturedStmt();
6331 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6332 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6333 llvm::Value *NumTeamsVal = CGF.EmitScalarExpr(NumTeams,
6334 /*IgnoreResultAssign*/ true);
6335 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6336 /*isSigned=*/true);
6337 }
6338 case OMPD_target_teams:
6339 case OMPD_target_teams_distribute:
6340 case OMPD_target_teams_distribute_simd:
6341 case OMPD_target_teams_distribute_parallel_for:
6342 case OMPD_target_teams_distribute_parallel_for_simd: {
6343 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6344 llvm::Value *NumTeamsVal = CGF.EmitScalarExpr(NumTeams,
6345 /*IgnoreResultAssign*/ true);
6346 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6347 /*isSigned=*/true);
6348 }
6349 default:
6350 break;
6351 }
6352 }
6353
6354 return llvm::ConstantInt::get(CGF.Int32Ty, DefaultNT);
6355}
6356
6357static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6358 llvm::Value *DefaultThreadLimitVal) {
6359 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6360 CGF.getContext(), CS->getCapturedStmt());
6361 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6362 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
6363 llvm::Value *NumThreads = nullptr;
6364 llvm::Value *CondVal = nullptr;
6365 // Handle if clause. If if clause present, the number of threads is
6366 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6367 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6368 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6369 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6370 const OMPIfClause *IfClause = nullptr;
6371 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6372 if (C->getNameModifier() == OMPD_unknown ||
6373 C->getNameModifier() == OMPD_parallel) {
6374 IfClause = C;
6375 break;
6376 }
6377 }
6378 if (IfClause) {
6379 const Expr *Cond = IfClause->getCondition();
6380 bool Result;
6381 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6382 if (!Result)
6383 return CGF.Builder.getInt32(1);
6384 } else {
6385 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6386 if (const auto *PreInit =
6387 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6388 for (const auto *I : PreInit->decls()) {
6389 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6390 CGF.EmitVarDecl(cast<VarDecl>(*I));
6391 } else {
6392 CodeGenFunction::AutoVarEmission Emission =
6393 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6394 CGF.EmitAutoVarCleanups(Emission);
6395 }
6396 }
6397 }
6398 CondVal = CGF.EvaluateExprAsBool(Cond);
6399 }
6400 }
6401 }
6402 // Check the value of num_threads clause iff if clause was not specified
6403 // or is not evaluated to false.
6404 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6405 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6406 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6407 const auto *NumThreadsClause =
6408 Dir->getSingleClause<OMPNumThreadsClause>();
6409 CodeGenFunction::LexicalScope Scope(
6410 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6411 if (const auto *PreInit =
6412 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6413 for (const auto *I : PreInit->decls()) {
6414 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6415 CGF.EmitVarDecl(cast<VarDecl>(*I));
6416 } else {
6417 CodeGenFunction::AutoVarEmission Emission =
6418 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6419 CGF.EmitAutoVarCleanups(Emission);
6420 }
6421 }
6422 }
6423 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
6424 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
6425 /*isSigned=*/false);
6426 if (DefaultThreadLimitVal)
6427 NumThreads = CGF.Builder.CreateSelect(
6428 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6429 DefaultThreadLimitVal, NumThreads);
6430 } else {
6431 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6432 : CGF.Builder.getInt32(0);
6433 }
6434 // Process condition of the if clause.
6435 if (CondVal) {
6436 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6437 CGF.Builder.getInt32(1));
6438 }
6439 return NumThreads;
6440 }
6441 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6442 return CGF.Builder.getInt32(1);
6443 }
6444 return DefaultThreadLimitVal;
6445}
6446
6447const Expr *CGOpenMPRuntime::getNumThreadsExprForTargetDirective(
6448 CodeGenFunction &CGF, const OMPExecutableDirective &D,
6449 int32_t &DefaultVal) {
6450 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6451 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&(static_cast <bool> (isOpenMPTargetExecutionDirective(DirectiveKind
) && "Expected target-based executable directive.") ?
void (0) : __assert_fail ("isOpenMPTargetExecutionDirective(DirectiveKind) && \"Expected target-based executable directive.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6452, __extension__
__PRETTY_FUNCTION__))
6452 "Expected target-based executable directive.")(static_cast <bool> (isOpenMPTargetExecutionDirective(DirectiveKind
) && "Expected target-based executable directive.") ?
void (0) : __assert_fail ("isOpenMPTargetExecutionDirective(DirectiveKind) && \"Expected target-based executable directive.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6452, __extension__
__PRETTY_FUNCTION__))
;
6453
6454 switch (DirectiveKind) {
6455 case OMPD_target:
6456 // Teams have no clause thread_limit
6457 return nullptr;
6458 case OMPD_target_teams:
6459 case OMPD_target_teams_distribute:
6460 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6461 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6462 const Expr *ThreadLimit = ThreadLimitClause->getThreadLimit();
6463 if (ThreadLimit->isIntegerConstantExpr(CGF.getContext()))
6464 if (auto Constant =
6465 ThreadLimit->getIntegerConstantExpr(CGF.getContext()))
6466 DefaultVal = Constant->getExtValue();
6467 return ThreadLimit;
6468 }
6469 return nullptr;
6470 case OMPD_target_parallel:
6471 case OMPD_target_parallel_for:
6472 case OMPD_target_parallel_for_simd:
6473 case OMPD_target_teams_distribute_parallel_for:
6474 case OMPD_target_teams_distribute_parallel_for_simd: {
6475 Expr *ThreadLimit = nullptr;
6476 Expr *NumThreads = nullptr;
6477 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6478 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6479 ThreadLimit = ThreadLimitClause->getThreadLimit();
6480 if (ThreadLimit->isIntegerConstantExpr(CGF.getContext()))
6481 if (auto Constant =
6482 ThreadLimit->getIntegerConstantExpr(CGF.getContext()))
6483 DefaultVal = Constant->getExtValue();
6484 }
6485 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
6486 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6487 NumThreads = NumThreadsClause->getNumThreads();
6488 if (NumThreads->isIntegerConstantExpr(CGF.getContext())) {
6489 if (auto Constant =
6490 NumThreads->getIntegerConstantExpr(CGF.getContext())) {
6491 if (Constant->getExtValue() < DefaultVal) {
6492 DefaultVal = Constant->getExtValue();
6493 ThreadLimit = NumThreads;
6494 }
6495 }
6496 }
6497 }
6498 return ThreadLimit;
6499 }
6500 case OMPD_target_teams_distribute_simd:
6501 case OMPD_target_simd:
6502 DefaultVal = 1;
6503 return nullptr;
6504 case OMPD_parallel:
6505 case OMPD_for:
6506 case OMPD_parallel_for:
6507 case OMPD_parallel_master:
6508 case OMPD_parallel_sections:
6509 case OMPD_for_simd:
6510 case OMPD_parallel_for_simd:
6511 case OMPD_cancel:
6512 case OMPD_cancellation_point:
6513 case OMPD_ordered:
6514 case OMPD_threadprivate:
6515 case OMPD_allocate:
6516 case OMPD_task:
6517 case OMPD_simd:
6518 case OMPD_tile:
6519 case OMPD_unroll:
6520 case OMPD_sections:
6521 case OMPD_section:
6522 case OMPD_single:
6523 case OMPD_master:
6524 case OMPD_critical:
6525 case OMPD_taskyield:
6526 case OMPD_barrier:
6527 case OMPD_taskwait:
6528 case OMPD_taskgroup:
6529 case OMPD_atomic:
6530 case OMPD_flush:
6531 case OMPD_depobj:
6532 case OMPD_scan:
6533 case OMPD_teams:
6534 case OMPD_target_data:
6535 case OMPD_target_exit_data:
6536 case OMPD_target_enter_data:
6537 case OMPD_distribute:
6538 case OMPD_distribute_simd:
6539 case OMPD_distribute_parallel_for:
6540 case OMPD_distribute_parallel_for_simd:
6541 case OMPD_teams_distribute:
6542 case OMPD_teams_distribute_simd:
6543 case OMPD_teams_distribute_parallel_for:
6544 case OMPD_teams_distribute_parallel_for_simd:
6545 case OMPD_target_update:
6546 case OMPD_declare_simd:
6547 case OMPD_declare_variant:
6548 case OMPD_begin_declare_variant:
6549 case OMPD_end_declare_variant:
6550 case OMPD_declare_target:
6551 case OMPD_end_declare_target:
6552 case OMPD_declare_reduction:
6553 case OMPD_declare_mapper:
6554 case OMPD_taskloop:
6555 case OMPD_taskloop_simd:
6556 case OMPD_master_taskloop:
6557 case OMPD_master_taskloop_simd:
6558 case OMPD_parallel_master_taskloop:
6559 case OMPD_parallel_master_taskloop_simd:
6560 case OMPD_requires:
6561 case OMPD_unknown:
6562 break;
6563 default:
6564 break;
6565 }
6566 llvm_unreachable("Unsupported directive kind.")::llvm::llvm_unreachable_internal("Unsupported directive kind."
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6566)
;
6567}
6568
6569llvm::Value *CGOpenMPRuntime::emitNumThreadsForTargetDirective(
6570 CodeGenFunction &CGF, const OMPExecutableDirective &D) {
6571 assert(!CGF.getLangOpts().OpenMPIsDevice &&(static_cast <bool> (!CGF.getLangOpts().OpenMPIsDevice &&
"Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? void (0) : __assert_fail ("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6573, __extension__
__PRETTY_FUNCTION__))
6572 "Clauses associated with the teams directive expected to be emitted "(static_cast <bool> (!CGF.getLangOpts().OpenMPIsDevice &&
"Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? void (0) : __assert_fail ("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6573, __extension__
__PRETTY_FUNCTION__))
6573 "only for the host!")(static_cast <bool> (!CGF.getLangOpts().OpenMPIsDevice &&
"Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? void (0) : __assert_fail ("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6573, __extension__
__PRETTY_FUNCTION__))
;
6574 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6575 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&(static_cast <bool> (isOpenMPTargetExecutionDirective(DirectiveKind
) && "Expected target-based executable directive.") ?
void (0) : __assert_fail ("isOpenMPTargetExecutionDirective(DirectiveKind) && \"Expected target-based executable directive.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6576, __extension__
__PRETTY_FUNCTION__))
6576 "Expected target-based executable directive.")(static_cast <bool> (isOpenMPTargetExecutionDirective(DirectiveKind
) && "Expected target-based executable directive.") ?
void (0) : __assert_fail ("isOpenMPTargetExecutionDirective(DirectiveKind) && \"Expected target-based executable directive.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6576, __extension__
__PRETTY_FUNCTION__))
;
6577 CGBuilderTy &Bld = CGF.Builder;
6578 llvm::Value *ThreadLimitVal = nullptr;
6579 llvm::Value *NumThreadsVal = nullptr;
6580 switch (DirectiveKind) {
6581 case OMPD_target: {
6582 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6583 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6584 return NumThreads;
6585 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6586 CGF.getContext(), CS->getCapturedStmt());
6587 // TODO: The standard is not clear how to resolve two thread limit clauses,
6588 // let's pick the teams one if it's present, otherwise the target one.
6589 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6590 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6591 if (const auto *TLC = Dir->getSingleClause<OMPThreadLimitClause>()) {
6592 ThreadLimitClause = TLC;
6593 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6594 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6595 CodeGenFunction::LexicalScope Scope(
6596 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6597 if (const auto *PreInit =
6598 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6599 for (const auto *I : PreInit->decls()) {
6600 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6601 CGF.EmitVarDecl(cast<VarDecl>(*I));
6602 } else {
6603 CodeGenFunction::AutoVarEmission Emission =
6604 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6605 CGF.EmitAutoVarCleanups(Emission);
6606 }
6607 }
6608 }
6609 }
6610 }
6611 if (ThreadLimitClause) {
6612 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6613 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6614 ThreadLimitVal =
6615 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6616 }
6617 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6618 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6619 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6620 CS = Dir->getInnermostCapturedStmt();
6621 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6622 CGF.getContext(), CS->getCapturedStmt());
6623 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6624 }
6625 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6626 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6627 CS = Dir->getInnermostCapturedStmt();
6628 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6629 return NumThreads;
6630 }
6631 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6632 return Bld.getInt32(1);
6633 }
6634 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6635 }
6636 case OMPD_target_teams: {
6637 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6638 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6639 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6640 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6641 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6642 ThreadLimitVal =
6643 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6644 }
6645 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6646 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6647 return NumThreads;
6648 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6649 CGF.getContext(), CS->getCapturedStmt());
6650 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6651 if (Dir->getDirectiveKind() == OMPD_distribute) {
6652 CS = Dir->getInnermostCapturedStmt();
6653 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6654 return NumThreads;
6655 }
6656 }
6657 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6658 }
6659 case OMPD_target_teams_distribute:
6660 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6661 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6662 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6663 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6664 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6665 ThreadLimitVal =
6666 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6667 }
6668 if (llvm::Value *NumThreads =
6669 getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal))
6670 return NumThreads;
6671 return Bld.getInt32(0);
6672 case OMPD_target_parallel:
6673 case OMPD_target_parallel_for:
6674 case OMPD_target_parallel_for_simd:
6675 case OMPD_target_teams_distribute_parallel_for:
6676 case OMPD_target_teams_distribute_parallel_for_simd: {
6677 llvm::Value *CondVal = nullptr;
6678 // Handle if clause. If if clause present, the number of threads is
6679 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6680 if (D.hasClausesOfKind<OMPIfClause>()) {
6681 const OMPIfClause *IfClause = nullptr;
6682 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6683 if (C->getNameModifier() == OMPD_unknown ||
6684 C->getNameModifier() == OMPD_parallel) {
6685 IfClause = C;
6686 break;
6687 }
6688 }
6689 if (IfClause) {
6690 const Expr *Cond = IfClause->getCondition();
6691 bool Result;
6692 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6693 if (!Result)
6694 return Bld.getInt32(1);
6695 } else {
6696 CodeGenFunction::RunCleanupsScope Scope(CGF);
6697 CondVal = CGF.EvaluateExprAsBool(Cond);
6698 }
6699 }
6700 }
6701 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6702 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6703 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6704 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6705 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6706 ThreadLimitVal =
6707 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6708 }
6709 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
6710 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
6711 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6712 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6713 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
6714 NumThreadsVal =
6715 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
6716 ThreadLimitVal = ThreadLimitVal
6717 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
6718 ThreadLimitVal),
6719 NumThreadsVal, ThreadLimitVal)
6720 : NumThreadsVal;
6721 }
6722 if (!ThreadLimitVal)
6723 ThreadLimitVal = Bld.getInt32(0);
6724 if (CondVal)
6725 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6726 return ThreadLimitVal;
6727 }
6728 case OMPD_target_teams_distribute_simd:
6729 case OMPD_target_simd:
6730 return Bld.getInt32(1);
6731 case OMPD_parallel:
6732 case OMPD_for:
6733 case OMPD_parallel_for:
6734 case OMPD_parallel_master:
6735 case OMPD_parallel_sections:
6736 case OMPD_for_simd:
6737 case OMPD_parallel_for_simd:
6738 case OMPD_cancel:
6739 case OMPD_cancellation_point:
6740 case OMPD_ordered:
6741 case OMPD_threadprivate:
6742 case OMPD_allocate:
6743 case OMPD_task:
6744 case OMPD_simd:
6745 case OMPD_tile:
6746 case OMPD_unroll:
6747 case OMPD_sections:
6748 case OMPD_section:
6749 case OMPD_single:
6750 case OMPD_master:
6751 case OMPD_critical:
6752 case OMPD_taskyield:
6753 case OMPD_barrier:
6754 case OMPD_taskwait:
6755 case OMPD_taskgroup:
6756 case OMPD_atomic:
6757 case OMPD_flush:
6758 case OMPD_depobj:
6759 case OMPD_scan:
6760 case OMPD_teams:
6761 case OMPD_target_data:
6762 case OMPD_target_exit_data:
6763 case OMPD_target_enter_data:
6764 case OMPD_distribute:
6765 case OMPD_distribute_simd:
6766 case OMPD_distribute_parallel_for:
6767 case OMPD_distribute_parallel_for_simd:
6768 case OMPD_teams_distribute:
6769 case OMPD_teams_distribute_simd:
6770 case OMPD_teams_distribute_parallel_for:
6771 case OMPD_teams_distribute_parallel_for_simd:
6772 case OMPD_target_update:
6773 case OMPD_declare_simd:
6774 case OMPD_declare_variant:
6775 case OMPD_begin_declare_variant:
6776 case OMPD_end_declare_variant:
6777 case OMPD_declare_target:
6778 case OMPD_end_declare_target:
6779 case OMPD_declare_reduction:
6780 case OMPD_declare_mapper:
6781 case OMPD_taskloop:
6782 case OMPD_taskloop_simd:
6783 case OMPD_master_taskloop:
6784 case OMPD_master_taskloop_simd:
6785 case OMPD_parallel_master_taskloop:
6786 case OMPD_parallel_master_taskloop_simd:
6787 case OMPD_requires:
6788 case OMPD_metadirective:
6789 case OMPD_unknown:
6790 break;
6791 default:
6792 break;
6793 }
6794 llvm_unreachable("Unsupported directive kind.")::llvm::llvm_unreachable_internal("Unsupported directive kind."
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6794)
;
6795}
6796
6797namespace {
6798LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()using ::llvm::BitmaskEnumDetail::operator~; using ::llvm::BitmaskEnumDetail
::operator|; using ::llvm::BitmaskEnumDetail::operator&; using
::llvm::BitmaskEnumDetail::operator^; using ::llvm::BitmaskEnumDetail
::operator|=; using ::llvm::BitmaskEnumDetail::operator&=
; using ::llvm::BitmaskEnumDetail::operator^=
;
6799
6800// Utility to handle information from clauses associated with a given
6801// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
6802// It provides a convenient interface to obtain the information and generate
6803// code for that information.
6804class MappableExprsHandler {
6805public:
6806 /// Get the offset of the OMP_MAP_MEMBER_OF field.
6807 static unsigned getFlagMemberOffset() {
6808 unsigned Offset = 0;
6809 for (uint64_t Remain =
6810 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
6811 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
6812 !(Remain & 1); Remain = Remain >> 1)
6813 Offset++;
6814 return Offset;
6815 }
6816
6817 /// Class that holds debugging information for a data mapping to be passed to
6818 /// the runtime library.
6819 class MappingExprInfo {
6820 /// The variable declaration used for the data mapping.
6821 const ValueDecl *MapDecl = nullptr;
6822 /// The original expression used in the map clause, or null if there is
6823 /// none.
6824 const Expr *MapExpr = nullptr;
6825
6826 public:
6827 MappingExprInfo(const ValueDecl *MapDecl, const Expr *MapExpr = nullptr)
6828 : MapDecl(MapDecl), MapExpr(MapExpr) {}
6829
6830 const ValueDecl *getMapDecl() const { return MapDecl; }
6831 const Expr *getMapExpr() const { return MapExpr; }
6832 };
6833
6834 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
6835 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
6836 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
6837 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
6838 using MapNonContiguousArrayTy =
6839 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
6840 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
6841 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
6842
6843 /// This structure contains combined information generated for mappable
6844 /// clauses, including base pointers, pointers, sizes, map types, user-defined
6845 /// mappers, and non-contiguous information.
6846 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
6847 MapExprsArrayTy Exprs;
6848 MapValueDeclsArrayTy Mappers;
6849 MapValueDeclsArrayTy DevicePtrDecls;
6850
6851 /// Append arrays in \a CurInfo.
6852 void append(MapCombinedInfoTy &CurInfo) {
6853 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
6854 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
6855 CurInfo.DevicePtrDecls.end());
6856 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
6857 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
6858 }
6859 };
6860
6861 /// Map between a struct and the its lowest & highest elements which have been
6862 /// mapped.
6863 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
6864 /// HE(FieldIndex, Pointer)}
6865 struct StructRangeInfoTy {
6866 MapCombinedInfoTy PreliminaryMapData;
6867 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
6868 0, Address::invalid()};
6869 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
6870 0, Address::invalid()};
6871 Address Base = Address::invalid();
6872 Address LB = Address::invalid();
6873 bool IsArraySection = false;
6874 bool HasCompleteRecord = false;
6875 };
6876
6877private:
6878 /// Kind that defines how a device pointer has to be returned.
6879 struct MapInfo {
6880 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
6881 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
6882 ArrayRef<OpenMPMapModifierKind> MapModifiers;
6883 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
6884 bool ReturnDevicePointer = false;
6885 bool IsImplicit = false;
6886 const ValueDecl *Mapper = nullptr;
6887 const Expr *VarRef = nullptr;
6888 bool ForDeviceAddr = false;
6889
6890 MapInfo() = default;
6891 MapInfo(
6892 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
6893 OpenMPMapClauseKind MapType,
6894 ArrayRef<OpenMPMapModifierKind> MapModifiers,
6895 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
6896 bool ReturnDevicePointer, bool IsImplicit,
6897 const ValueDecl *Mapper = nullptr, const Expr *VarRef = nullptr,
6898 bool ForDeviceAddr = false)
6899 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
6900 MotionModifiers(MotionModifiers),
6901 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
6902 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {}
6903 };
6904
6905 /// If use_device_ptr or use_device_addr is used on a decl which is a struct
6906 /// member and there is no map information about it, then emission of that
6907 /// entry is deferred until the whole struct has been processed.
6908 struct DeferredDevicePtrEntryTy {
6909 const Expr *IE = nullptr;
6910 const ValueDecl *VD = nullptr;
6911 bool ForDeviceAddr = false;
6912
6913 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD,
6914 bool ForDeviceAddr)
6915 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {}
6916 };
6917
6918 /// The target directive from where the mappable clauses were extracted. It
6919 /// is either a executable directive or a user-defined mapper directive.
6920 llvm::PointerUnion<const OMPExecutableDirective *,
6921 const OMPDeclareMapperDecl *>
6922 CurDir;
6923
6924 /// Function the directive is being generated for.
6925 CodeGenFunction &CGF;
6926
6927 /// Set of all first private variables in the current directive.
6928 /// bool data is set to true if the variable is implicitly marked as
6929 /// firstprivate, false otherwise.
6930 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
6931
6932 /// Map between device pointer declarations and their expression components.
6933 /// The key value for declarations in 'this' is null.
6934 llvm::DenseMap<
6935 const ValueDecl *,
6936 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
6937 DevPointersMap;
6938
6939 /// Map between device addr declarations and their expression components.
6940 /// The key value for declarations in 'this' is null.
6941 llvm::DenseMap<
6942 const ValueDecl *,
6943 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
6944 HasDevAddrsMap;
6945
6946 /// Map between lambda declarations and their map type.
6947 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
6948
6949 llvm::Value *getExprTypeSize(const Expr *E) const {
6950 QualType ExprTy = E->getType().getCanonicalType();
6951
6952 // Calculate the size for array shaping expression.
6953 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
6954 llvm::Value *Size =
6955 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType());
6956 for (const Expr *SE : OAE->getDimensions()) {
6957 llvm::Value *Sz = CGF.EmitScalarExpr(SE);
6958 Sz = CGF.EmitScalarConversion(Sz, SE->getType(),
6959 CGF.getContext().getSizeType(),
6960 SE->getExprLoc());
6961 Size = CGF.Builder.CreateNUWMul(Size, Sz);
6962 }
6963 return Size;
6964 }
6965
6966 // Reference types are ignored for mapping purposes.
6967 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
6968 ExprTy = RefTy->getPointeeType().getCanonicalType();
6969
6970 // Given that an array section is considered a built-in type, we need to
6971 // do the calculation based on the length of the section instead of relying
6972 // on CGF.getTypeSize(E->getType()).
6973 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
6974 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
6975 OAE->getBase()->IgnoreParenImpCasts())
6976 .getCanonicalType();
6977
6978 // If there is no length associated with the expression and lower bound is
6979 // not specified too, that means we are using the whole length of the
6980 // base.
6981 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
6982 !OAE->getLowerBound())
6983 return CGF.getTypeSize(BaseTy);
6984
6985 llvm::Value *ElemSize;
6986 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
6987 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
6988 } else {
6989 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
6990 assert(ATy && "Expecting array type if not a pointer type.")(static_cast <bool> (ATy && "Expecting array type if not a pointer type."
) ? void (0) : __assert_fail ("ATy && \"Expecting array type if not a pointer type.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 6990, __extension__
__PRETTY_FUNCTION__))
;
6991 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
6992 }
6993
6994 // If we don't have a length at this point, that is because we have an
6995 // array section with a single element.
6996 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
6997 return ElemSize;
6998
6999 if (const Expr *LenExpr = OAE->getLength()) {
7000 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7001 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7002 CGF.getContext().getSizeType(),
7003 LenExpr->getExprLoc());
7004 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7005 }
7006 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&(static_cast <bool> (!OAE->getLength() && OAE
->getColonLocFirst().isValid() && OAE->getLowerBound
() && "expected array_section[lb:].") ? void (0) : __assert_fail
("!OAE->getLength() && OAE->getColonLocFirst().isValid() && OAE->getLowerBound() && \"expected array_section[lb:].\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7007, __extension__
__PRETTY_FUNCTION__))
7007 OAE->getLowerBound() && "expected array_section[lb:].")(static_cast <bool> (!OAE->getLength() && OAE
->getColonLocFirst().isValid() && OAE->getLowerBound
() && "expected array_section[lb:].") ? void (0) : __assert_fail
("!OAE->getLength() && OAE->getColonLocFirst().isValid() && OAE->getLowerBound() && \"expected array_section[lb:].\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7007, __extension__
__PRETTY_FUNCTION__))
;
7008 // Size = sizetype - lb * elemtype;
7009 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7010 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7011 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7012 CGF.getContext().getSizeType(),
7013 OAE->getLowerBound()->getExprLoc());
7014 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7015 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7016 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7017 LengthVal = CGF.Builder.CreateSelect(
7018 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7019 return LengthVal;
7020 }
7021 return CGF.getTypeSize(ExprTy);
7022 }
7023
7024 /// Return the corresponding bits for a given map clause modifier. Add
7025 /// a flag marking the map as a pointer if requested. Add a flag marking the
7026 /// map as the first one of a series of maps that relate to the same map
7027 /// expression.
7028 OpenMPOffloadMappingFlags getMapTypeBits(
7029 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7030 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit,
7031 bool AddPtrFlag, bool AddIsTargetParamFlag, bool IsNonContiguous) const {
7032 OpenMPOffloadMappingFlags Bits =
7033 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7034 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7035 switch (MapType) {
7036 case OMPC_MAP_alloc:
7037 case OMPC_MAP_release:
7038 // alloc and release is the default behavior in the runtime library, i.e.
7039 // if we don't pass any bits alloc/release that is what the runtime is
7040 // going to do. Therefore, we don't need to signal anything for these two
7041 // type modifiers.
7042 break;
7043 case OMPC_MAP_to:
7044 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7045 break;
7046 case OMPC_MAP_from:
7047 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7048 break;
7049 case OMPC_MAP_tofrom:
7050 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7051 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7052 break;
7053 case OMPC_MAP_delete:
7054 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7055 break;
7056 case OMPC_MAP_unknown:
7057 llvm_unreachable("Unexpected map type!")::llvm::llvm_unreachable_internal("Unexpected map type!", "clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7057)
;
7058 }
7059 if (AddPtrFlag)
7060 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7061 if (AddIsTargetParamFlag)
7062 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7063 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7064 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7065 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7066 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7067 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7068 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7069 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7070 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7071 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7072 if (IsNonContiguous)
7073 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7074 return Bits;
7075 }
7076
7077 /// Return true if the provided expression is a final array section. A
7078 /// final array section, is one whose length can't be proved to be one.
7079 bool isFinalArraySectionExpression(const Expr *E) const {
7080 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
7081
7082 // It is not an array section and therefore not a unity-size one.
7083 if (!OASE)
7084 return false;
7085
7086 // An array section with no colon always refer to a single element.
7087 if (OASE->getColonLocFirst().isInvalid())
7088 return false;
7089
7090 const Expr *Length = OASE->getLength();
7091
7092 // If we don't have a length we have to check if the array has size 1
7093 // for this dimension. Also, we should always expect a length if the
7094 // base type is pointer.
7095 if (!Length) {
7096 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7097 OASE->getBase()->IgnoreParenImpCasts())
7098 .getCanonicalType();
7099 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
7100 return ATy->getSize().getSExtValue() != 1;
7101 // If we don't have a constant dimension length, we have to consider
7102 // the current section as having any size, so it is not necessarily
7103 // unitary. If it happen to be unity size, that's user fault.
7104 return true;
7105 }
7106
7107 // Check if the length evaluates to 1.
7108 Expr::EvalResult Result;
7109 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
7110 return true; // Can have more that size 1.
7111
7112 llvm::APSInt ConstLength = Result.Val.getInt();
7113 return ConstLength.getSExtValue() != 1;
7114 }
7115
7116 /// Generate the base pointers, section pointers, sizes, map type bits, and
7117 /// user-defined mappers (all included in \a CombinedInfo) for the provided
7118 /// map type, map or motion modifiers, and expression components.
7119 /// \a IsFirstComponent should be set to true if the provided set of
7120 /// components is the first associated with a capture.
7121 void generateInfoForComponentList(
7122 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7123 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7124 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
7125 MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct,
7126 bool IsFirstComponentList, bool IsImplicit,
7127 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false,
7128 const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr,
7129 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7130 OverlappedElements = std::nullopt) const {
7131 // The following summarizes what has to be generated for each map and the
7132 // types below. The generated information is expressed in this order:
7133 // base pointer, section pointer, size, flags
7134 // (to add to the ones that come from the map type and modifier).
7135 //
7136 // double d;
7137 // int i[100];
7138 // float *p;
7139 // int **a = &i;
7140 //
7141 // struct S1 {
7142 // int i;
7143 // float f[50];
7144 // }
7145 // struct S2 {
7146 // int i;
7147 // float f[50];
7148 // S1 s;
7149 // double *p;
7150 // struct S2 *ps;
7151 // int &ref;
7152 // }
7153 // S2 s;
7154 // S2 *ps;
7155 //
7156 // map(d)
7157 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
7158 //
7159 // map(i)
7160 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
7161 //
7162 // map(i[1:23])
7163 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
7164 //
7165 // map(p)
7166 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
7167 //
7168 // map(p[1:24])
7169 // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ
7170 // in unified shared memory mode or for local pointers
7171 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
7172 //
7173 // map((*a)[0:3])
7174 // &(*a), &(*a), sizeof(pointer), TARGET_PARAM | TO | FROM
7175 // &(*a), &(*a)[0], 3*sizeof(int), PTR_AND_OBJ | TO | FROM
7176 //
7177 // map(**a)
7178 // &(*a), &(*a), sizeof(pointer), TARGET_PARAM | TO | FROM
7179 // &(*a), &(**a), sizeof(int), PTR_AND_OBJ | TO | FROM
7180 //
7181 // map(s)
7182 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
7183 //
7184 // map(s.i)
7185 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
7186 //
7187 // map(s.s.f)
7188 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
7189 //
7190 // map(s.p)
7191 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
7192 //
7193 // map(to: s.p[:22])
7194 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7195 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7196 // &(s.p), &(s.p[0]), 22*sizeof(double),
7197 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7198 // (*) alloc space for struct members, only this is a target parameter
7199 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7200 // optimizes this entry out, same in the examples below)
7201 // (***) map the pointee (map: to)
7202 //
7203 // map(to: s.ref)
7204 // &s, &(s.ref), sizeof(int*), TARGET_PARAM (*)
7205 // &s, &(s.ref), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7206 // (*) alloc space for struct members, only this is a target parameter
7207 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7208 // optimizes this entry out, same in the examples below)
7209 // (***) map the pointee (map: to)
7210 //
7211 // map(s.ps)
7212 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
7213 //
7214 // map(from: s.ps->s.i)
7215 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7216 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7217 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7218 //
7219 // map(to: s.ps->ps)
7220 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7221 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7222 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
7223 //
7224 // map(s.ps->ps->ps)
7225 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7226 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7227 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7228 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
7229 //
7230 // map(to: s.ps->ps->s.f[:22])
7231 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7232 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7233 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7234 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7235 //
7236 // map(ps)
7237 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
7238 //
7239 // map(ps->i)
7240 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
7241 //
7242 // map(ps->s.f)
7243 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
7244 //
7245 // map(from: ps->p)
7246 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
7247 //
7248 // map(to: ps->p[:22])
7249 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7250 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7251 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
7252 //
7253 // map(ps->ps)
7254 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
7255 //
7256 // map(from: ps->ps->s.i)
7257 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7258 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7259 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7260 //
7261 // map(from: ps->ps->ps)
7262 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7263 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7264 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7265 //
7266 // map(ps->ps->ps->ps)
7267 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7268 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7269 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7270 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
7271 //
7272 // map(to: ps->ps->ps->s.f[:22])
7273 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7274 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7275 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7276 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7277 //
7278 // map(to: s.f[:22]) map(from: s.p[:33])
7279 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7280 // sizeof(double*) (**), TARGET_PARAM
7281 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7282 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7283 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7284 // (*) allocate contiguous space needed to fit all mapped members even if
7285 // we allocate space for members not mapped (in this example,
7286 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7287 // them as well because they fall between &s.f[0] and &s.p)
7288 //
7289 // map(from: s.f[:22]) map(to: ps->p[:33])
7290 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7291 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7292 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7293 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7294 // (*) the struct this entry pertains to is the 2nd element in the list of
7295 // arguments, hence MEMBER_OF(2)
7296 //
7297 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7298 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7299 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7300 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7301 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7302 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7303 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7304 // (*) the struct this entry pertains to is the 4th element in the list
7305 // of arguments, hence MEMBER_OF(4)
7306
7307 // Track if the map information being generated is the first for a capture.
7308 bool IsCaptureFirstInfo = IsFirstComponentList;
7309 // When the variable is on a declare target link or in a to clause with
7310 // unified memory, a reference is needed to hold the host/device address
7311 // of the variable.
7312 bool RequiresReference = false;
7313
7314 // Scan the components from the base to the complete expression.
7315 auto CI = Components.rbegin();
7316 auto CE = Components.rend();
7317 auto I = CI;
7318
7319 // Track if the map information being generated is the first for a list of
7320 // components.
7321 bool IsExpressionFirstInfo = true;
7322 bool FirstPointerInComplexData = false;
7323 Address BP = Address::invalid();
7324 const Expr *AssocExpr = I->getAssociatedExpression();
7325 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7326 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
7327 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7328
7329 if (isa<MemberExpr>(AssocExpr)) {
7330 // The base is the 'this' pointer. The content of the pointer is going
7331 // to be the base of the field being mapped.
7332 BP = CGF.LoadCXXThisAddress();
7333 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7334 (OASE &&
7335 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7336 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
7337 } else if (OAShE &&
7338 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) {
7339 BP = Address(
7340 CGF.EmitScalarExpr(OAShE->getBase()),
7341 CGF.ConvertTypeForMem(OAShE->getBase()->getType()->getPointeeType()),
7342 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType()));
7343 } else {
7344 // The base is the reference to the variable.
7345 // BP = &Var.
7346 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
7347 if (const auto *VD =
7348 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7349 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7350 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7351 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7352 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7353 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7354 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7355 RequiresReference = true;
7356 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
7357 }
7358 }
7359 }
7360
7361 // If the variable is a pointer and is being dereferenced (i.e. is not
7362 // the last component), the base has to be the pointer itself, not its
7363 // reference. References are ignored for mapping purposes.
7364 QualType Ty =
7365 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7366 if (Ty->isAnyPointerType() && std::next(I) != CE) {
7367 // No need to generate individual map information for the pointer, it
7368 // can be associated with the combined storage if shared memory mode is
7369 // active or the base declaration is not global variable.
7370 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7371 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
7372 !VD || VD->hasLocalStorage())
7373 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
7374 else
7375 FirstPointerInComplexData = true;
7376 ++I;
7377 }
7378 }
7379
7380 // Track whether a component of the list should be marked as MEMBER_OF some
7381 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7382 // in a component list should be marked as MEMBER_OF, all subsequent entries
7383 // do not belong to the base struct. E.g.
7384 // struct S2 s;
7385 // s.ps->ps->ps->f[:]
7386 // (1) (2) (3) (4)
7387 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7388 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7389 // is the pointee of ps(2) which is not member of struct s, so it should not
7390 // be marked as such (it is still PTR_AND_OBJ).
7391 // The variable is initialized to false so that PTR_AND_OBJ entries which
7392 // are not struct members are not considered (e.g. array of pointers to
7393 // data).
7394 bool ShouldBeMemberOf = false;
7395
7396 // Variable keeping track of whether or not we have encountered a component
7397 // in the component list which is a member expression. Useful when we have a
7398 // pointer or a final array section, in which case it is the previous
7399 // component in the list which tells us whether we have a member expression.
7400 // E.g. X.f[:]
7401 // While processing the final array section "[:]" it is "f" which tells us
7402 // whether we are dealing with a member of a declared struct.
7403 const MemberExpr *EncounteredME = nullptr;
7404
7405 // Track for the total number of dimension. Start from one for the dummy
7406 // dimension.
7407 uint64_t DimSize = 1;
7408
7409 bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous;
7410 bool IsPrevMemberReference = false;
7411
7412 for (; I != CE; ++I) {
7413 // If the current component is member of a struct (parent struct) mark it.
7414 if (!EncounteredME) {
7415 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7416 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7417 // as MEMBER_OF the parent struct.
7418 if (EncounteredME) {
7419 ShouldBeMemberOf = true;
7420 // Do not emit as complex pointer if this is actually not array-like
7421 // expression.
7422 if (FirstPointerInComplexData) {
7423 QualType Ty = std::prev(I)
7424 ->getAssociatedDeclaration()
7425 ->getType()
7426 .getNonReferenceType();
7427 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
7428 FirstPointerInComplexData = false;
7429 }
7430 }
7431 }
7432
7433 auto Next = std::next(I);
7434
7435 // We need to generate the addresses and sizes if this is the last
7436 // component, if the component is a pointer or if it is an array section
7437 // whose length can't be proved to be one. If this is a pointer, it
7438 // becomes the base address for the following components.
7439
7440 // A final array section, is one whose length can't be proved to be one.
7441 // If the map item is non-contiguous then we don't treat any array section
7442 // as final array section.
7443 bool IsFinalArraySection =
7444 !IsNonContiguous &&
7445 isFinalArraySectionExpression(I->getAssociatedExpression());
7446
7447 // If we have a declaration for the mapping use that, otherwise use
7448 // the base declaration of the map clause.
7449 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
7450 ? I->getAssociatedDeclaration()
7451 : BaseDecl;
7452 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
7453 : MapExpr;
7454
7455 // Get information on whether the element is a pointer. Have to do a
7456 // special treatment for array sections given that they are built-in
7457 // types.
7458 const auto *OASE =
7459 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7460 const auto *OAShE =
7461 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
7462 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
7463 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7464 bool IsPointer =
7465 OAShE ||
7466 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7467 .getCanonicalType()
7468 ->isAnyPointerType()) ||
7469 I->getAssociatedExpression()->getType()->isAnyPointerType();
7470 bool IsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) &&
7471 MapDecl &&
7472 MapDecl->getType()->isLValueReferenceType();
7473 bool IsNonDerefPointer = IsPointer &&
7474 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
7475 !IsNonContiguous;
7476
7477 if (OASE)
7478 ++DimSize;
7479
7480 if (Next == CE || IsMemberReference || IsNonDerefPointer ||
7481 IsFinalArraySection) {
7482 // If this is not the last component, we expect the pointer to be
7483 // associated with an array expression or member expression.
7484 assert((Next == CE ||(static_cast <bool> ((Next == CE || isa<MemberExpr>
(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr
>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr
>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr
>(Next->getAssociatedExpression()) || isa<UnaryOperator
>(Next->getAssociatedExpression()) || isa<BinaryOperator
>(Next->getAssociatedExpression())) && "Unexpected expression"
) ? void (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7491, __extension__
__PRETTY_FUNCTION__))
7485 isa<MemberExpr>(Next->getAssociatedExpression()) ||(static_cast <bool> ((Next == CE || isa<MemberExpr>
(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr
>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr
>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr
>(Next->getAssociatedExpression()) || isa<UnaryOperator
>(Next->getAssociatedExpression()) || isa<BinaryOperator
>(Next->getAssociatedExpression())) && "Unexpected expression"
) ? void (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7491, __extension__
__PRETTY_FUNCTION__))
7486 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||(static_cast <bool> ((Next == CE || isa<MemberExpr>
(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr
>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr
>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr
>(Next->getAssociatedExpression()) || isa<UnaryOperator
>(Next->getAssociatedExpression()) || isa<BinaryOperator
>(Next->getAssociatedExpression())) && "Unexpected expression"
) ? void (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7491, __extension__
__PRETTY_FUNCTION__))
7487 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) ||(static_cast <bool> ((Next == CE || isa<MemberExpr>
(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr
>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr
>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr
>(Next->getAssociatedExpression()) || isa<UnaryOperator
>(Next->getAssociatedExpression()) || isa<BinaryOperator
>(Next->getAssociatedExpression())) && "Unexpected expression"
) ? void (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7491, __extension__
__PRETTY_FUNCTION__))
7488 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) ||(static_cast <bool> ((Next == CE || isa<MemberExpr>
(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr
>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr
>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr
>(Next->getAssociatedExpression()) || isa<UnaryOperator
>(Next->getAssociatedExpression()) || isa<BinaryOperator
>(Next->getAssociatedExpression())) && "Unexpected expression"
) ? void (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7491, __extension__
__PRETTY_FUNCTION__))
7489 isa<UnaryOperator>(Next->getAssociatedExpression()) ||(static_cast <bool> ((Next == CE || isa<MemberExpr>
(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr
>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr
>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr
>(Next->getAssociatedExpression()) || isa<UnaryOperator
>(Next->getAssociatedExpression()) || isa<BinaryOperator
>(Next->getAssociatedExpression())) && "Unexpected expression"
) ? void (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7491, __extension__
__PRETTY_FUNCTION__))
7490 isa<BinaryOperator>(Next->getAssociatedExpression())) &&(static_cast <bool> ((Next == CE || isa<MemberExpr>
(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr
>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr
>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr
>(Next->getAssociatedExpression()) || isa<UnaryOperator
>(Next->getAssociatedExpression()) || isa<BinaryOperator
>(Next->getAssociatedExpression())) && "Unexpected expression"
) ? void (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7491, __extension__
__PRETTY_FUNCTION__))
7491 "Unexpected expression")(static_cast <bool> ((Next == CE || isa<MemberExpr>
(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr
>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr
>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr
>(Next->getAssociatedExpression()) || isa<UnaryOperator
>(Next->getAssociatedExpression()) || isa<BinaryOperator
>(Next->getAssociatedExpression())) && "Unexpected expression"
) ? void (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7491, __extension__
__PRETTY_FUNCTION__))
;
7492
7493 Address LB = Address::invalid();
7494 Address LowestElem = Address::invalid();
7495 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
7496 const MemberExpr *E) {
7497 const Expr *BaseExpr = E->getBase();
7498 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a
7499 // scalar.
7500 LValue BaseLV;
7501 if (E->isArrow()) {
7502 LValueBaseInfo BaseInfo;
7503 TBAAAccessInfo TBAAInfo;
7504 Address Addr =
7505 CGF.EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo);
7506 QualType PtrTy = BaseExpr->getType()->getPointeeType();
7507 BaseLV = CGF.MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo);
7508 } else {
7509 BaseLV = CGF.EmitOMPSharedLValue(BaseExpr);
7510 }
7511 return BaseLV;
7512 };
7513 if (OAShE) {
7514 LowestElem = LB =
7515 Address(CGF.EmitScalarExpr(OAShE->getBase()),
7516 CGF.ConvertTypeForMem(
7517 OAShE->getBase()->getType()->getPointeeType()),
7518 CGF.getContext().getTypeAlignInChars(
7519 OAShE->getBase()->getType()));
7520 } else if (IsMemberReference) {
7521 const auto *ME = cast<MemberExpr>(I->getAssociatedExpression());
7522 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7523 LowestElem = CGF.EmitLValueForFieldInitialization(
7524 BaseLVal, cast<FieldDecl>(MapDecl))
7525 .getAddress(CGF);
7526 LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType())
7527 .getAddress(CGF);
7528 } else {
7529 LowestElem = LB =
7530 CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
7531 .getAddress(CGF);
7532 }
7533
7534 // If this component is a pointer inside the base struct then we don't
7535 // need to create any entry for it - it will be combined with the object
7536 // it is pointing to into a single PTR_AND_OBJ entry.
7537 bool IsMemberPointerOrAddr =
7538 EncounteredME &&
7539 (((IsPointer || ForDeviceAddr) &&
7540 I->getAssociatedExpression() == EncounteredME) ||
7541 (IsPrevMemberReference && !IsPointer) ||
7542 (IsMemberReference && Next != CE &&
7543 !Next->getAssociatedExpression()->getType()->isPointerType()));
7544 if (!OverlappedElements.empty() && Next == CE) {
7545 // Handle base element with the info for overlapped elements.
7546 assert(!PartialStruct.Base.isValid() && "The base element is set.")(static_cast <bool> (!PartialStruct.Base.isValid() &&
"The base element is set.") ? void (0) : __assert_fail ("!PartialStruct.Base.isValid() && \"The base element is set.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7546, __extension__
__PRETTY_FUNCTION__))
;
7547 assert(!IsPointer &&(static_cast <bool> (!IsPointer && "Unexpected base element with the pointer type."
) ? void (0) : __assert_fail ("!IsPointer && \"Unexpected base element with the pointer type.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7548, __extension__
__PRETTY_FUNCTION__))
7548 "Unexpected base element with the pointer type.")(static_cast <bool> (!IsPointer && "Unexpected base element with the pointer type."
) ? void (0) : __assert_fail ("!IsPointer && \"Unexpected base element with the pointer type.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7548, __extension__
__PRETTY_FUNCTION__))
;
7549 // Mark the whole struct as the struct that requires allocation on the
7550 // device.
7551 PartialStruct.LowestElem = {0, LowestElem};
7552 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7553 I->getAssociatedExpression()->getType());
7554 Address HB = CGF.Builder.CreateConstGEP(
7555 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
7556 LowestElem, CGF.VoidPtrTy, CGF.Int8Ty),
7557 TypeSize.getQuantity() - 1);
7558 PartialStruct.HighestElem = {
7559 std::numeric_limits<decltype(
7560 PartialStruct.HighestElem.first)>::max(),
7561 HB};
7562 PartialStruct.Base = BP;
7563 PartialStruct.LB = LB;
7564 assert((static_cast <bool> (PartialStruct.PreliminaryMapData.BasePointers
.empty() && "Overlapped elements must be used only once for the variable."
) ? void (0) : __assert_fail ("PartialStruct.PreliminaryMapData.BasePointers.empty() && \"Overlapped elements must be used only once for the variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7566, __extension__
__PRETTY_FUNCTION__))
7565 PartialStruct.PreliminaryMapData.BasePointers.empty() &&(static_cast <bool> (PartialStruct.PreliminaryMapData.BasePointers
.empty() && "Overlapped elements must be used only once for the variable."
) ? void (0) : __assert_fail ("PartialStruct.PreliminaryMapData.BasePointers.empty() && \"Overlapped elements must be used only once for the variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7566, __extension__
__PRETTY_FUNCTION__))
7566 "Overlapped elements must be used only once for the variable.")(static_cast <bool> (PartialStruct.PreliminaryMapData.BasePointers
.empty() && "Overlapped elements must be used only once for the variable."
) ? void (0) : __assert_fail ("PartialStruct.PreliminaryMapData.BasePointers.empty() && \"Overlapped elements must be used only once for the variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7566, __extension__
__PRETTY_FUNCTION__))
;
7567 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
7568 // Emit data for non-overlapped data.
7569 OpenMPOffloadMappingFlags Flags =
7570 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
7571 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
7572 /*AddPtrFlag=*/false,
7573 /*AddIsTargetParamFlag=*/false, IsNonContiguous);
7574 llvm::Value *Size = nullptr;
7575 // Do bitcopy of all non-overlapped structure elements.
7576 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7577 Component : OverlappedElements) {
7578 Address ComponentLB = Address::invalid();
7579 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7580 Component) {
7581 if (const ValueDecl *VD = MC.getAssociatedDeclaration()) {
7582 const auto *FD = dyn_cast<FieldDecl>(VD);
7583 if (FD && FD->getType()->isLValueReferenceType()) {
7584 const auto *ME =
7585 cast<MemberExpr>(MC.getAssociatedExpression());
7586 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7587 ComponentLB =
7588 CGF.EmitLValueForFieldInitialization(BaseLVal, FD)
7589 .getAddress(CGF);
7590 } else {
7591 ComponentLB =
7592 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7593 .getAddress(CGF);
7594 }
7595 Size = CGF.Builder.CreatePtrDiff(
7596 CGF.Int8Ty, CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7597 CGF.EmitCastToVoidPtr(LB.getPointer()));
7598 break;
7599 }
7600 }
7601 assert(Size && "Failed to determine structure size")(static_cast <bool> (Size && "Failed to determine structure size"
) ? void (0) : __assert_fail ("Size && \"Failed to determine structure size\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7601, __extension__
__PRETTY_FUNCTION__))
;
7602 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7603 CombinedInfo.BasePointers.push_back(BP.getPointer());
7604 CombinedInfo.DevicePtrDecls.push_back(nullptr);
7605 CombinedInfo.Pointers.push_back(LB.getPointer());
7606 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
7607 Size, CGF.Int64Ty, /*isSigned=*/true));
7608 CombinedInfo.Types.push_back(Flags);
7609 CombinedInfo.Mappers.push_back(nullptr);
7610 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7611 : 1);
7612 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
7613 }
7614 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7615 CombinedInfo.BasePointers.push_back(BP.getPointer());
7616 CombinedInfo.DevicePtrDecls.push_back(nullptr);
7617 CombinedInfo.Pointers.push_back(LB.getPointer());
7618 Size = CGF.Builder.CreatePtrDiff(
7619 CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).getPointer(),
7620 CGF.EmitCastToVoidPtr(LB.getPointer()));
7621 CombinedInfo.Sizes.push_back(
7622 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
7623 CombinedInfo.Types.push_back(Flags);
7624 CombinedInfo.Mappers.push_back(nullptr);
7625 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7626 : 1);
7627 break;
7628 }
7629 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
7630 if (!IsMemberPointerOrAddr ||
7631 (Next == CE && MapType != OMPC_MAP_unknown)) {
7632 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7633 CombinedInfo.BasePointers.push_back(BP.getPointer());
7634 CombinedInfo.DevicePtrDecls.push_back(nullptr);
7635 CombinedInfo.Pointers.push_back(LB.getPointer());
7636 CombinedInfo.Sizes.push_back(
7637 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
7638 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7639 : 1);
7640
7641 // If Mapper is valid, the last component inherits the mapper.
7642 bool HasMapper = Mapper && Next == CE;
7643 CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr);
7644
7645 // We need to add a pointer flag for each map that comes from the
7646 // same expression except for the first one. We also need to signal
7647 // this map is the first one that relates with the current capture
7648 // (there is a set of entries for each capture).
7649 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
7650 MapType, MapModifiers, MotionModifiers, IsImplicit,
7651 !IsExpressionFirstInfo || RequiresReference ||
7652 FirstPointerInComplexData || IsMemberReference,
7653 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
7654
7655 if (!IsExpressionFirstInfo || IsMemberReference) {
7656 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
7657 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
7658 if (IsPointer || (IsMemberReference && Next != CE))
7659 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
7660 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
7661 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
7662 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
7663 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
7664
7665 if (ShouldBeMemberOf) {
7666 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7667 // should be later updated with the correct value of MEMBER_OF.
7668 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
7669 // From now on, all subsequent PTR_AND_OBJ entries should not be
7670 // marked as MEMBER_OF.
7671 ShouldBeMemberOf = false;
7672 }
7673 }
7674
7675 CombinedInfo.Types.push_back(Flags);
7676 }
7677
7678 // If we have encountered a member expression so far, keep track of the
7679 // mapped member. If the parent is "*this", then the value declaration
7680 // is nullptr.
7681 if (EncounteredME) {
7682 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl());
7683 unsigned FieldIndex = FD->getFieldIndex();
7684
7685 // Update info about the lowest and highest elements for this struct
7686 if (!PartialStruct.Base.isValid()) {
7687 PartialStruct.LowestElem = {FieldIndex, LowestElem};
7688 if (IsFinalArraySection) {
7689 Address HB =
7690 CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false)
7691 .getAddress(CGF);
7692 PartialStruct.HighestElem = {FieldIndex, HB};
7693 } else {
7694 PartialStruct.HighestElem = {FieldIndex, LowestElem};
7695 }
7696 PartialStruct.Base = BP;
7697 PartialStruct.LB = BP;
7698 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7699 PartialStruct.LowestElem = {FieldIndex, LowestElem};
7700 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7701 PartialStruct.HighestElem = {FieldIndex, LowestElem};
7702 }
7703 }
7704
7705 // Need to emit combined struct for array sections.
7706 if (IsFinalArraySection || IsNonContiguous)
7707 PartialStruct.IsArraySection = true;
7708
7709 // If we have a final array section, we are done with this expression.
7710 if (IsFinalArraySection)
7711 break;
7712
7713 // The pointer becomes the base for the next element.
7714 if (Next != CE)
7715 BP = IsMemberReference ? LowestElem : LB;
7716
7717 IsExpressionFirstInfo = false;
7718 IsCaptureFirstInfo = false;
7719 FirstPointerInComplexData = false;
7720 IsPrevMemberReference = IsMemberReference;
7721 } else if (FirstPointerInComplexData) {
7722 QualType Ty = Components.rbegin()
7723 ->getAssociatedDeclaration()
7724 ->getType()
7725 .getNonReferenceType();
7726 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
7727 FirstPointerInComplexData = false;
7728 }
7729 }
7730 // If ran into the whole component - allocate the space for the whole
7731 // record.
7732 if (!EncounteredME)
7733 PartialStruct.HasCompleteRecord = true;
7734
7735 if (!IsNonContiguous)
7736 return;
7737
7738 const ASTContext &Context = CGF.getContext();
7739
7740 // For supporting stride in array section, we need to initialize the first
7741 // dimension size as 1, first offset as 0, and first count as 1
7742 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 0)};
7743 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)};
7744 MapValuesArrayTy CurStrides;
7745 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)};
7746 uint64_t ElementTypeSize;
7747
7748 // Collect Size information for each dimension and get the element size as
7749 // the first Stride. For example, for `int arr[10][10]`, the DimSizes
7750 // should be [10, 10] and the first stride is 4 btyes.
7751 for (const OMPClauseMappableExprCommon::MappableComponent &Component :
7752 Components) {
7753 const Expr *AssocExpr = Component.getAssociatedExpression();
7754 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
7755
7756 if (!OASE)
7757 continue;
7758
7759 QualType Ty = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
7760 auto *CAT = Context.getAsConstantArrayType(Ty);
7761 auto *VAT = Context.getAsVariableArrayType(Ty);
7762
7763 // We need all the dimension size except for the last dimension.
7764 assert((VAT || CAT || &Component == &*Components.begin()) &&(static_cast <bool> ((VAT || CAT || &Component == &
*Components.begin()) && "Should be either ConstantArray or VariableArray if not the "
"first Component") ? void (0) : __assert_fail ("(VAT || CAT || &Component == &*Components.begin()) && \"Should be either ConstantArray or VariableArray if not the \" \"first Component\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7766, __extension__
__PRETTY_FUNCTION__))
7765 "Should be either ConstantArray or VariableArray if not the "(static_cast <bool> ((VAT || CAT || &Component == &
*Components.begin()) && "Should be either ConstantArray or VariableArray if not the "
"first Component") ? void (0) : __assert_fail ("(VAT || CAT || &Component == &*Components.begin()) && \"Should be either ConstantArray or VariableArray if not the \" \"first Component\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7766, __extension__
__PRETTY_FUNCTION__))
7766 "first Component")(static_cast <bool> ((VAT || CAT || &Component == &
*Components.begin()) && "Should be either ConstantArray or VariableArray if not the "
"first Component") ? void (0) : __assert_fail ("(VAT || CAT || &Component == &*Components.begin()) && \"Should be either ConstantArray or VariableArray if not the \" \"first Component\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7766, __extension__
__PRETTY_FUNCTION__))
;
7767
7768 // Get element size if CurStrides is empty.
7769 if (CurStrides.empty()) {
7770 const Type *ElementType = nullptr;
7771 if (CAT)
7772 ElementType = CAT->getElementType().getTypePtr();
7773 else if (VAT)
7774 ElementType = VAT->getElementType().getTypePtr();
7775 else
7776 assert(&Component == &*Components.begin() &&(static_cast <bool> (&Component == &*Components
.begin() && "Only expect pointer (non CAT or VAT) when this is the "
"first Component") ? void (0) : __assert_fail ("&Component == &*Components.begin() && \"Only expect pointer (non CAT or VAT) when this is the \" \"first Component\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7778, __extension__
__PRETTY_FUNCTION__))
7777 "Only expect pointer (non CAT or VAT) when this is the "(static_cast <bool> (&Component == &*Components
.begin() && "Only expect pointer (non CAT or VAT) when this is the "
"first Component") ? void (0) : __assert_fail ("&Component == &*Components.begin() && \"Only expect pointer (non CAT or VAT) when this is the \" \"first Component\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7778, __extension__
__PRETTY_FUNCTION__))
7778 "first Component")(static_cast <bool> (&Component == &*Components
.begin() && "Only expect pointer (non CAT or VAT) when this is the "
"first Component") ? void (0) : __assert_fail ("&Component == &*Components.begin() && \"Only expect pointer (non CAT or VAT) when this is the \" \"first Component\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7778, __extension__
__PRETTY_FUNCTION__))
;
7779 // If ElementType is null, then it means the base is a pointer
7780 // (neither CAT nor VAT) and we'll attempt to get ElementType again
7781 // for next iteration.
7782 if (ElementType) {
7783 // For the case that having pointer as base, we need to remove one
7784 // level of indirection.
7785 if (&Component != &*Components.begin())
7786 ElementType = ElementType->getPointeeOrArrayElementType();
7787 ElementTypeSize =
7788 Context.getTypeSizeInChars(ElementType).getQuantity();
7789 CurStrides.push_back(
7790 llvm::ConstantInt::get(CGF.Int64Ty, ElementTypeSize));
7791 }
7792 }
7793 // Get dimension value except for the last dimension since we don't need
7794 // it.
7795 if (DimSizes.size() < Components.size() - 1) {
7796 if (CAT)
7797 DimSizes.push_back(llvm::ConstantInt::get(
7798 CGF.Int64Ty, CAT->getSize().getZExtValue()));
7799 else if (VAT)
7800 DimSizes.push_back(CGF.Builder.CreateIntCast(
7801 CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty,
7802 /*IsSigned=*/false));
7803 }
7804 }
7805
7806 // Skip the dummy dimension since we have already have its information.
7807 auto *DI = DimSizes.begin() + 1;
7808 // Product of dimension.
7809 llvm::Value *DimProd =
7810 llvm::ConstantInt::get(CGF.CGM.Int64Ty, ElementTypeSize);
7811
7812 // Collect info for non-contiguous. Notice that offset, count, and stride
7813 // are only meaningful for array-section, so we insert a null for anything
7814 // other than array-section.
7815 // Also, the size of offset, count, and stride are not the same as
7816 // pointers, base_pointers, sizes, or dims. Instead, the size of offset,
7817 // count, and stride are the same as the number of non-contiguous
7818 // declaration in target update to/from clause.
7819 for (const OMPClauseMappableExprCommon::MappableComponent &Component :
7820 Components) {
7821 const Expr *AssocExpr = Component.getAssociatedExpression();
7822
7823 if (const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
7824 llvm::Value *Offset = CGF.Builder.CreateIntCast(
7825 CGF.EmitScalarExpr(AE->getIdx()), CGF.Int64Ty,
7826 /*isSigned=*/false);
7827 CurOffsets.push_back(Offset);
7828 CurCounts.push_back(llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/1));
7829 CurStrides.push_back(CurStrides.back());
7830 continue;
7831 }
7832
7833 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
7834
7835 if (!OASE)
7836 continue;
7837
7838 // Offset
7839 const Expr *OffsetExpr = OASE->getLowerBound();
7840 llvm::Value *Offset = nullptr;
7841 if (!OffsetExpr) {
7842 // If offset is absent, then we just set it to zero.
7843 Offset = llvm::ConstantInt::get(CGF.Int64Ty, 0);
7844 } else {
7845 Offset = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(OffsetExpr),
7846 CGF.Int64Ty,
7847 /*isSigned=*/false);
7848 }
7849 CurOffsets.push_back(Offset);
7850
7851 // Count
7852 const Expr *CountExpr = OASE->getLength();
7853 llvm::Value *Count = nullptr;
7854 if (!CountExpr) {
7855 // In Clang, once a high dimension is an array section, we construct all
7856 // the lower dimension as array section, however, for case like
7857 // arr[0:2][2], Clang construct the inner dimension as an array section
7858 // but it actually is not in an array section form according to spec.
7859 if (!OASE->getColonLocFirst().isValid() &&
7860 !OASE->getColonLocSecond().isValid()) {
7861 Count = llvm::ConstantInt::get(CGF.Int64Ty, 1);
7862 } else {
7863 // OpenMP 5.0, 2.1.5 Array Sections, Description.
7864 // When the length is absent it defaults to ⌈(size −
7865 // lower-bound)/stride⌉, where size is the size of the array
7866 // dimension.
7867 const Expr *StrideExpr = OASE->getStride();
7868 llvm::Value *Stride =
7869 StrideExpr
7870 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr),
7871 CGF.Int64Ty, /*isSigned=*/false)
7872 : nullptr;
7873 if (Stride)
7874 Count = CGF.Builder.CreateUDiv(
7875 CGF.Builder.CreateNUWSub(*DI, Offset), Stride);
7876 else
7877 Count = CGF.Builder.CreateNUWSub(*DI, Offset);
7878 }
7879 } else {
7880 Count = CGF.EmitScalarExpr(CountExpr);
7881 }
7882 Count = CGF.Builder.CreateIntCast(Count, CGF.Int64Ty, /*isSigned=*/false);
7883 CurCounts.push_back(Count);
7884
7885 // Stride_n' = Stride_n * (D_0 * D_1 ... * D_n-1) * Unit size
7886 // Take `int arr[5][5][5]` and `arr[0:2:2][1:2:1][0:2:2]` as an example:
7887 // Offset Count Stride
7888 // D0 0 1 4 (int) <- dummy dimension
7889 // D1 0 2 8 (2 * (1) * 4)
7890 // D2 1 2 20 (1 * (1 * 5) * 4)
7891 // D3 0 2 200 (2 * (1 * 5 * 4) * 4)
7892 const Expr *StrideExpr = OASE->getStride();
7893 llvm::Value *Stride =
7894 StrideExpr
7895 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr),
7896 CGF.Int64Ty, /*isSigned=*/false)
7897 : nullptr;
7898 DimProd = CGF.Builder.CreateNUWMul(DimProd, *(DI - 1));
7899 if (Stride)
7900 CurStrides.push_back(CGF.Builder.CreateNUWMul(DimProd, Stride));
7901 else
7902 CurStrides.push_back(DimProd);
7903 if (DI != DimSizes.end())
7904 ++DI;
7905 }
7906
7907 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
7908 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
7909 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
7910 }
7911
7912 /// Return the adjusted map modifiers if the declaration a capture refers to
7913 /// appears in a first-private clause. This is expected to be used only with
7914 /// directives that start with 'target'.
7915 OpenMPOffloadMappingFlags
7916 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7917 assert(Cap.capturesVariable() && "Expected capture by reference only!")(static_cast <bool> (Cap.capturesVariable() && "Expected capture by reference only!"
) ? void (0) : __assert_fail ("Cap.capturesVariable() && \"Expected capture by reference only!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 7917, __extension__
__PRETTY_FUNCTION__))
;
7918
7919 // A first private variable captured by reference will use only the
7920 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7921 // declaration is known as first-private in this handler.
7922 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7923 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7924 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
7925 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7926 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
7927 OpenMPOffloadMappingFlags::OMP_MAP_TO;
7928 }
7929 auto I = LambdasMap.find(Cap.getCapturedVar()->getCanonicalDecl());
7930 if (I != LambdasMap.end())
7931 // for map(to: lambda): using user specified map type.
7932 return getMapTypeBits(
7933 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
7934 /*MotionModifiers=*/std::nullopt, I->getSecond()->isImplicit(),
7935 /*AddPtrFlag=*/false,
7936 /*AddIsTargetParamFlag=*/false,
7937 /*isNonContiguous=*/false);
7938 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
7939 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7940 }
7941
7942 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
7943 // Rotate by getFlagMemberOffset() bits.
7944 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
7945 << getFlagMemberOffset());
7946 }
7947
7948 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7949 OpenMPOffloadMappingFlags MemberOfFlag) {
7950 // If the entry is PTR_AND_OBJ but has not been marked with the special
7951 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7952 // marked as MEMBER_OF.
7953 if (static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
7954 Flags & OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ) &&
7955 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
7956 (Flags & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
7957 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF))
7958 return;
7959
7960 // Reset the placeholder value to prepare the flag for the assignment of the
7961 // proper MEMBER_OF value.
7962 Flags &= ~OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
7963 Flags |= MemberOfFlag;
7964 }
7965
7966 void getPlainLayout(const CXXRecordDecl *RD,
7967 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7968 bool AsBase) const {
7969 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7970
7971 llvm::StructType *St =
7972 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7973
7974 unsigned NumElements = St->getNumElements();
7975 llvm::SmallVector<
7976 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7977 RecordLayout(NumElements);
7978
7979 // Fill bases.
7980 for (const auto &I : RD->bases()) {
7981 if (I.isVirtual())
7982 continue;
7983 const auto *Base = I.getType()->getAsCXXRecordDecl();
7984 // Ignore empty bases.
7985 if (Base->isEmpty() || CGF.getContext()
7986 .getASTRecordLayout(Base)
7987 .getNonVirtualSize()
7988 .isZero())
7989 continue;
7990
7991 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7992 RecordLayout[FieldIndex] = Base;
7993 }
7994 // Fill in virtual bases.
7995 for (const auto &I : RD->vbases()) {
7996 const auto *Base = I.getType()->getAsCXXRecordDecl();
7997 // Ignore empty bases.
7998 if (Base->isEmpty())
7999 continue;
8000 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
8001 if (RecordLayout[FieldIndex])
8002 continue;
8003 RecordLayout[FieldIndex] = Base;
8004 }
8005 // Fill in all the fields.
8006 assert(!RD->isUnion() && "Unexpected union.")(static_cast <bool> (!RD->isUnion() && "Unexpected union."
) ? void (0) : __assert_fail ("!RD->isUnion() && \"Unexpected union.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8006, __extension__
__PRETTY_FUNCTION__))
;
8007 for (const auto *Field : RD->fields()) {
8008 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
8009 // will fill in later.)
8010 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
8011 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
8012 RecordLayout[FieldIndex] = Field;
8013 }
8014 }
8015 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8016 &Data : RecordLayout) {
8017 if (Data.isNull())
8018 continue;
8019 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
8020 getPlainLayout(Base, Layout, /*AsBase=*/true);
8021 else
8022 Layout.push_back(Data.get<const FieldDecl *>());
8023 }
8024 }
8025
8026 /// Generate all the base pointers, section pointers, sizes, map types, and
8027 /// mappers for the extracted mappable expressions (all included in \a
8028 /// CombinedInfo). Also, for each item that relates with a device pointer, a
8029 /// pair of the relevant declaration and index where it occurs is appended to
8030 /// the device pointers info array.
8031 void generateAllInfoForClauses(
8032 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8033 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8034 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const {
8035 // We have to process the component lists that relate with the same
8036 // declaration in a single chunk so that we can generate the map flags
8037 // correctly. Therefore, we organize all lists in a map.
8038 enum MapKind { Present, Allocs, Other, Total };
8039 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8040 SmallVector<SmallVector<MapInfo, 8>, 4>>
8041 Info;
8042
8043 // Helper function to fill the information map for the different supported
8044 // clauses.
8045 auto &&InfoGen =
8046 [&Info, &SkipVarSet](
8047 const ValueDecl *D, MapKind Kind,
8048 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8049 OpenMPMapClauseKind MapType,
8050 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8051 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8052 bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper,
8053 const Expr *VarRef = nullptr, bool ForDeviceAddr = false) {
8054 if (SkipVarSet.contains(D))
8055 return;
8056 auto It = Info.find(D);
8057 if (It == Info.end())
8058 It = Info
8059 .insert(std::make_pair(
8060 D, SmallVector<SmallVector<MapInfo, 8>, 4>(Total)))
8061 .first;
8062 It->second[Kind].emplace_back(
8063 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8064 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8065 };
8066
8067 for (const auto *Cl : Clauses) {
8068 const auto *C = dyn_cast<OMPMapClause>(Cl);
8069 if (!C)
8070 continue;
8071 MapKind Kind = Other;
8072 if (llvm::is_contained(C->getMapTypeModifiers(),
8073 OMPC_MAP_MODIFIER_present))
8074 Kind = Present;
8075 else if (C->getMapType() == OMPC_MAP_alloc)
8076 Kind = Allocs;
8077 const auto *EI = C->getVarRefs().begin();
8078 for (const auto L : C->component_lists()) {
8079 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr;
8080 InfoGen(std::get<0>(L), Kind, std::get<1>(L), C->getMapType(),
8081 C->getMapTypeModifiers(), std::nullopt,
8082 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L),
8083 E);
8084 ++EI;
8085 }
8086 }
8087 for (const auto *Cl : Clauses) {
8088 const auto *C = dyn_cast<OMPToClause>(Cl);
8089 if (!C)
8090 continue;
8091 MapKind Kind = Other;
8092 if (llvm::is_contained(C->getMotionModifiers(),
8093 OMPC_MOTION_MODIFIER_present))
8094 Kind = Present;
8095 const auto *EI = C->getVarRefs().begin();
8096 for (const auto L : C->component_lists()) {
8097 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, std::nullopt,
8098 C->getMotionModifiers(), /*ReturnDevicePointer=*/false,
8099 C->isImplicit(), std::get<2>(L), *EI);
8100 ++EI;
8101 }
8102 }
8103 for (const auto *Cl : Clauses) {
8104 const auto *C = dyn_cast<OMPFromClause>(Cl);
8105 if (!C)
8106 continue;
8107 MapKind Kind = Other;
8108 if (llvm::is_contained(C->getMotionModifiers(),
8109 OMPC_MOTION_MODIFIER_present))
8110 Kind = Present;
8111 const auto *EI = C->getVarRefs().begin();
8112 for (const auto L : C->component_lists()) {
8113 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from,
8114 std::nullopt, C->getMotionModifiers(),
8115 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L),
8116 *EI);
8117 ++EI;
8118 }
8119 }
8120
8121 // Look at the use_device_ptr and use_device_addr clauses information and
8122 // mark the existing map entries as such. If there is no map information for
8123 // an entry in the use_device_ptr and use_device_addr list, we create one
8124 // with map type 'alloc' and zero size section. It is the user fault if that
8125 // was not mapped before. If there is no map information and the pointer is
8126 // a struct member, then we defer the emission of that entry until the whole
8127 // struct has been processed.
8128 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8129 SmallVector<DeferredDevicePtrEntryTy, 4>>
8130 DeferredInfo;
8131 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8132
8133 auto &&UseDeviceDataCombinedInfoGen =
8134 [&UseDeviceDataCombinedInfo](const ValueDecl *VD, llvm::Value *Ptr,
8135 CodeGenFunction &CGF) {
8136 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8137 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8138 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8139 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8140 UseDeviceDataCombinedInfo.Sizes.push_back(
8141 llvm::Constant::getNullValue(CGF.Int64Ty));
8142 UseDeviceDataCombinedInfo.Types.push_back(
8143 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
8144 UseDeviceDataCombinedInfo.Mappers.push_back(nullptr);
8145 };
8146
8147 auto &&MapInfoGen =
8148 [&DeferredInfo, &UseDeviceDataCombinedInfoGen,
8149 &InfoGen](CodeGenFunction &CGF, const Expr *IE, const ValueDecl *VD,
8150 OMPClauseMappableExprCommon::MappableExprComponentListRef
8151 Components,
8152 bool IsImplicit, bool IsDevAddr) {
8153 // We didn't find any match in our map information - generate a zero
8154 // size array section - if the pointer is a struct member we defer
8155 // this action until the whole struct has been processed.
8156 if (isa<MemberExpr>(IE)) {
8157 // Insert the pointer into Info to be processed by
8158 // generateInfoForComponentList. Because it is a member pointer
8159 // without a pointee, no entry will be generated for it, therefore
8160 // we need to generate one after the whole struct has been
8161 // processed. Nonetheless, generateInfoForComponentList must be
8162 // called to take the pointer into account for the calculation of
8163 // the range of the partial struct.
8164 InfoGen(nullptr, Other, Components, OMPC_MAP_unknown, std::nullopt,
8165 std::nullopt, /*ReturnDevicePointer=*/false, IsImplicit,
8166 nullptr, nullptr, IsDevAddr);
8167 DeferredInfo[nullptr].emplace_back(IE, VD, IsDevAddr);
8168 } else {
8169 llvm::Value *Ptr;
8170 if (IsDevAddr) {
8171 if (IE->isGLValue())
8172 Ptr = CGF.EmitLValue(IE).getPointer(CGF);
8173 else
8174 Ptr = CGF.EmitScalarExpr(IE);
8175 } else {
8176 Ptr = CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
8177 }
8178 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF);
8179 }
8180 };
8181
8182 auto &&IsMapInfoExist = [&Info](CodeGenFunction &CGF, const ValueDecl *VD,
8183 const Expr *IE, bool IsDevAddr) -> bool {
8184 // We potentially have map information for this declaration already.
8185 // Look for the first set of components that refer to it. If found,
8186 // return true.
8187 // If the first component is a member expression, we have to look into
8188 // 'this', which maps to null in the map of map information. Otherwise
8189 // look directly for the information.
8190 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8191 if (It != Info.end()) {
8192 bool Found = false;
8193 for (auto &Data : It->second) {
8194 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) {
8195 return MI.Components.back().getAssociatedDeclaration() == VD;
8196 });
8197 // If we found a map entry, signal that the pointer has to be
8198 // returned and move on to the next declaration. Exclude cases where
8199 // the base pointer is mapped as array subscript, array section or
8200 // array shaping. The base address is passed as a pointer to base in
8201 // this case and cannot be used as a base for use_device_ptr list
8202 // item.
8203 if (CI != Data.end()) {
8204 if (IsDevAddr) {
8205 CI->ReturnDevicePointer = true;
8206 Found = true;
8207 break;
8208 } else {
8209 auto PrevCI = std::next(CI->Components.rbegin());
8210 const auto *VarD = dyn_cast<VarDecl>(VD);
8211 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8212 isa<MemberExpr>(IE) ||
8213 !VD->getType().getNonReferenceType()->isPointerType() ||
8214 PrevCI == CI->Components.rend() ||
8215 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
8216 VarD->hasLocalStorage()) {
8217 CI->ReturnDevicePointer = true;
8218 Found = true;
8219 break;
8220 }
8221 }
8222 }
8223 }
8224 return Found;
8225 }
8226 return false;
8227 };
8228
8229 // Look at the use_device_ptr clause information and mark the existing map
8230 // entries as such. If there is no map information for an entry in the
8231 // use_device_ptr list, we create one with map type 'alloc' and zero size
8232 // section. It is the user fault if that was not mapped before. If there is
8233 // no map information and the pointer is a struct member, then we defer the
8234 // emission of that entry until the whole struct has been processed.
8235 for (const auto *Cl : Clauses) {
8236 const auto *C = dyn_cast<OMPUseDevicePtrClause>(Cl);
8237 if (!C)
8238 continue;
8239 for (const auto L : C->component_lists()) {
8240 OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
8241 std::get<1>(L);
8242 assert(!Components.empty() &&(static_cast <bool> (!Components.empty() && "Not expecting empty list of components!"
) ? void (0) : __assert_fail ("!Components.empty() && \"Not expecting empty list of components!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8243, __extension__
__PRETTY_FUNCTION__))
8243 "Not expecting empty list of components!")(static_cast <bool> (!Components.empty() && "Not expecting empty list of components!"
) ? void (0) : __assert_fail ("!Components.empty() && \"Not expecting empty list of components!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8243, __extension__
__PRETTY_FUNCTION__))
;
8244 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
8245 VD = cast<ValueDecl>(VD->getCanonicalDecl());
8246 const Expr *IE = Components.back().getAssociatedExpression();
8247 if (IsMapInfoExist(CGF, VD, IE, /*IsDevAddr=*/false))
8248 continue;
8249 MapInfoGen(CGF, IE, VD, Components, C->isImplicit(),
8250 /*IsDevAddr=*/false);
8251 }
8252 }
8253
8254 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8255 for (const auto *Cl : Clauses) {
8256 const auto *C = dyn_cast<OMPUseDeviceAddrClause>(Cl);
8257 if (!C)
8258 continue;
8259 for (const auto L : C->component_lists()) {
8260 OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
8261 std::get<1>(L);
8262 assert(!std::get<1>(L).empty() &&(static_cast <bool> (!std::get<1>(L).empty() &&
"Not expecting empty list of components!") ? void (0) : __assert_fail
("!std::get<1>(L).empty() && \"Not expecting empty list of components!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8263, __extension__
__PRETTY_FUNCTION__))
8263 "Not expecting empty list of components!")(static_cast <bool> (!std::get<1>(L).empty() &&
"Not expecting empty list of components!") ? void (0) : __assert_fail
("!std::get<1>(L).empty() && \"Not expecting empty list of components!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8263, __extension__
__PRETTY_FUNCTION__))
;
8264 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
8265 if (!Processed.insert(VD).second)
8266 continue;
8267 VD = cast<ValueDecl>(VD->getCanonicalDecl());
8268 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
8269 if (IsMapInfoExist(CGF, VD, IE, /*IsDevAddr=*/true))
8270 continue;
8271 MapInfoGen(CGF, IE, VD, Components, C->isImplicit(),
8272 /*IsDevAddr=*/true);
8273 }
8274 }
8275
8276 for (const auto &Data : Info) {
8277 StructRangeInfoTy PartialStruct;
8278 // Temporary generated information.
8279 MapCombinedInfoTy CurInfo;
8280 const Decl *D = Data.first;
8281 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
8282 for (const auto &M : Data.second) {
8283 for (const MapInfo &L : M) {
8284 assert(!L.Components.empty() &&(static_cast <bool> (!L.Components.empty() && "Not expecting declaration with no component lists."
) ? void (0) : __assert_fail ("!L.Components.empty() && \"Not expecting declaration with no component lists.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8285, __extension__
__PRETTY_FUNCTION__))
8285 "Not expecting declaration with no component lists.")(static_cast <bool> (!L.Components.empty() && "Not expecting declaration with no component lists."
) ? void (0) : __assert_fail ("!L.Components.empty() && \"Not expecting declaration with no component lists.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8285, __extension__
__PRETTY_FUNCTION__))
;
8286
8287 // Remember the current base pointer index.
8288 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
8289 CurInfo.NonContigInfo.IsNonContiguous =
8290 L.Components.back().isNonContiguous();
8291 generateInfoForComponentList(
8292 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
8293 CurInfo, PartialStruct, /*IsFirstComponentList=*/false,
8294 L.IsImplicit, L.Mapper, L.ForDeviceAddr, VD, L.VarRef);
8295
8296 // If this entry relates with a device pointer, set the relevant
8297 // declaration and add the 'return pointer' flag.
8298 if (L.ReturnDevicePointer) {
8299 assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx &&(static_cast <bool> (CurInfo.BasePointers.size() > CurrentBasePointersIdx
&& "Unexpected number of mapped base pointers.") ? void
(0) : __assert_fail ("CurInfo.BasePointers.size() > CurrentBasePointersIdx && \"Unexpected number of mapped base pointers.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8300, __extension__
__PRETTY_FUNCTION__))
8300 "Unexpected number of mapped base pointers.")(static_cast <bool> (CurInfo.BasePointers.size() > CurrentBasePointersIdx
&& "Unexpected number of mapped base pointers.") ? void
(0) : __assert_fail ("CurInfo.BasePointers.size() > CurrentBasePointersIdx && \"Unexpected number of mapped base pointers.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8300, __extension__
__PRETTY_FUNCTION__))
;
8301
8302 const ValueDecl *RelevantVD =
8303 L.Components.back().getAssociatedDeclaration();
8304 assert(RelevantVD &&(static_cast <bool> (RelevantVD && "No relevant declaration related with device pointer??"
) ? void (0) : __assert_fail ("RelevantVD && \"No relevant declaration related with device pointer??\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8305, __extension__
__PRETTY_FUNCTION__))
8305 "No relevant declaration related with device pointer??")(static_cast <bool> (RelevantVD && "No relevant declaration related with device pointer??"
) ? void (0) : __assert_fail ("RelevantVD && \"No relevant declaration related with device pointer??\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8305, __extension__
__PRETTY_FUNCTION__))
;
8306
8307 CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
8308 CurInfo.Types[CurrentBasePointersIdx] |=
8309 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8310 }
8311 }
8312 }
8313
8314 // Append any pending zero-length pointers which are struct members and
8315 // used with use_device_ptr or use_device_addr.
8316 auto CI = DeferredInfo.find(Data.first);
8317 if (CI != DeferredInfo.end()) {
8318 for (const DeferredDevicePtrEntryTy &L : CI->second) {
8319 llvm::Value *BasePtr;
8320 llvm::Value *Ptr;
8321 if (L.ForDeviceAddr) {
8322 if (L.IE->isGLValue())
8323 Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
8324 else
8325 Ptr = this->CGF.EmitScalarExpr(L.IE);
8326 BasePtr = Ptr;
8327 // Entry is RETURN_PARAM. Also, set the placeholder value
8328 // MEMBER_OF=FFFF so that the entry is later updated with the
8329 // correct value of MEMBER_OF.
8330 CurInfo.Types.push_back(
8331 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8332 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8333 } else {
8334 BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
8335 Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE),
8336 L.IE->getExprLoc());
8337 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the
8338 // placeholder value MEMBER_OF=FFFF so that the entry is later
8339 // updated with the correct value of MEMBER_OF.
8340 CurInfo.Types.push_back(
8341 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8342 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8343 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8344 }
8345 CurInfo.Exprs.push_back(L.VD);
8346 CurInfo.BasePointers.emplace_back(BasePtr);
8347 CurInfo.DevicePtrDecls.emplace_back(L.VD);
8348 CurInfo.Pointers.push_back(Ptr);
8349 CurInfo.Sizes.push_back(
8350 llvm::Constant::getNullValue(this->CGF.Int64Ty));
8351 CurInfo.Mappers.push_back(nullptr);
8352 }
8353 }
8354 // If there is an entry in PartialStruct it means we have a struct with
8355 // individual members mapped. Emit an extra combined entry.
8356 if (PartialStruct.Base.isValid()) {
8357 CurInfo.NonContigInfo.Dims.push_back(0);
8358 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
8359 /*IsMapThis*/ !VD, VD);
8360 }
8361
8362 // We need to append the results of this capture to what we already
8363 // have.
8364 CombinedInfo.append(CurInfo);
8365 }
8366 // Append data for use_device_ptr clauses.
8367 CombinedInfo.append(UseDeviceDataCombinedInfo);
8368 }
8369
8370public:
8371 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
8372 : CurDir(&Dir), CGF(CGF) {
8373 // Extract firstprivate clause information.
8374 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
8375 for (const auto *D : C->varlists())
8376 FirstPrivateDecls.try_emplace(
8377 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
8378 // Extract implicit firstprivates from uses_allocators clauses.
8379 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
8380 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
8381 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
8382 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
8383 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
8384 /*Implicit=*/true);
8385 else if (const auto *VD = dyn_cast<VarDecl>(
8386 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
8387 ->getDecl()))
8388 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true);
8389 }
8390 }
8391 // Extract device pointer clause information.
8392 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
8393 for (auto L : C->component_lists())
8394 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
8395 // Extract device addr clause information.
8396 for (const auto *C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
8397 for (auto L : C->component_lists())
8398 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
8399 // Extract map information.
8400 for (const auto *C : Dir.getClausesOfKind<OMPMapClause>()) {
8401 if (C->getMapType() != OMPC_MAP_to)
8402 continue;
8403 for (auto L : C->component_lists()) {
8404 const ValueDecl *VD = std::get<0>(L);
8405 const auto *RD = VD ? VD->getType()
8406 .getCanonicalType()
8407 .getNonReferenceType()
8408 ->getAsCXXRecordDecl()
8409 : nullptr;
8410 if (RD && RD->isLambda())
8411 LambdasMap.try_emplace(std::get<0>(L), C);
8412 }
8413 }
8414 }
8415
8416 /// Constructor for the declare mapper directive.
8417 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
8418 : CurDir(&Dir), CGF(CGF) {}
8419
8420 /// Generate code for the combined entry if we have a partially mapped struct
8421 /// and take care of the mapping flags of the arguments corresponding to
8422 /// individual struct members.
8423 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
8424 MapFlagsArrayTy &CurTypes,
8425 const StructRangeInfoTy &PartialStruct, bool IsMapThis,
8426 const ValueDecl *VD = nullptr,
8427 bool NotTargetParams = true) const {
8428 if (CurTypes.size() == 1 &&
8429 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
8430 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
8431 !PartialStruct.IsArraySection)
8432 return;
8433 Address LBAddr = PartialStruct.LowestElem.second;
8434 Address HBAddr = PartialStruct.HighestElem.second;
8435 if (PartialStruct.HasCompleteRecord) {
8436 LBAddr = PartialStruct.LB;
8437 HBAddr = PartialStruct.LB;
8438 }
8439 CombinedInfo.Exprs.push_back(VD);
8440 // Base is the base of the struct
8441 CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer());
8442 CombinedInfo.DevicePtrDecls.push_back(nullptr);
8443 // Pointer is the address of the lowest element
8444 llvm::Value *LB = LBAddr.getPointer();
8445 const CXXMethodDecl *MD =
8446 CGF.CurFuncDecl ? dyn_cast<CXXMethodDecl>(CGF.CurFuncDecl) : nullptr;
8447 const CXXRecordDecl *RD = MD ? MD->getParent() : nullptr;
8448 bool HasBaseClass = RD && IsMapThis ? RD->getNumBases() > 0 : false;
8449 // There should not be a mapper for a combined entry.
8450 if (HasBaseClass) {
8451 // OpenMP 5.2 148:21:
8452 // If the target construct is within a class non-static member function,
8453 // and a variable is an accessible data member of the object for which the
8454 // non-static data member function is invoked, the variable is treated as
8455 // if the this[:1] expression had appeared in a map clause with a map-type
8456 // of tofrom.
8457 // Emit this[:1]
8458 CombinedInfo.Pointers.push_back(PartialStruct.Base.getPointer());
8459 QualType Ty = MD->getThisType()->getPointeeType();
8460 llvm::Value *Size =
8461 CGF.Builder.CreateIntCast(CGF.getTypeSize(Ty), CGF.Int64Ty,
8462 /*isSigned=*/true);
8463 CombinedInfo.Sizes.push_back(Size);
8464 } else {
8465 CombinedInfo.Pointers.push_back(LB);
8466 // Size is (addr of {highest+1} element) - (addr of lowest element)
8467 llvm::Value *HB = HBAddr.getPointer();
8468 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(
8469 HBAddr.getElementType(), HB, /*Idx0=*/1);
8470 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
8471 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
8472 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CGF.Int8Ty, CHAddr, CLAddr);
8473 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
8474 /*isSigned=*/false);
8475 CombinedInfo.Sizes.push_back(Size);
8476 }
8477 CombinedInfo.Mappers.push_back(nullptr);
8478 // Map type is always TARGET_PARAM, if generate info for captures.
8479 CombinedInfo.Types.push_back(
8480 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
8481 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
8482 // If any element has the present modifier, then make sure the runtime
8483 // doesn't attempt to allocate the struct.
8484 if (CurTypes.end() !=
8485 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) {
8486 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
8487 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
8488 }))
8489 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
8490 // Remove TARGET_PARAM flag from the first element
8491 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
8492 // If any element has the ompx_hold modifier, then make sure the runtime
8493 // uses the hold reference count for the struct as a whole so that it won't
8494 // be unmapped by an extra dynamic reference count decrement. Add it to all
8495 // elements as well so the runtime knows which reference count to check
8496 // when determining whether it's time for device-to-host transfers of
8497 // individual elements.
8498 if (CurTypes.end() !=
8499 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) {
8500 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
8501 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
8502 })) {
8503 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
8504 for (auto &M : CurTypes)
8505 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
8506 }
8507
8508 // All other current entries will be MEMBER_OF the combined entry
8509 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8510 // 0xFFFF in the MEMBER_OF field).
8511 OpenMPOffloadMappingFlags MemberOfFlag =
8512 getMemberOfFlag(CombinedInfo.BasePointers.size() - 1);
8513 for (auto &M : CurTypes)
8514 setCorrectMemberOfFlag(M, MemberOfFlag);
8515 }
8516
8517 /// Generate all the base pointers, section pointers, sizes, map types, and
8518 /// mappers for the extracted mappable expressions (all included in \a
8519 /// CombinedInfo). Also, for each item that relates with a device pointer, a
8520 /// pair of the relevant declaration and index where it occurs is appended to
8521 /// the device pointers info array.
8522 void generateAllInfo(
8523 MapCombinedInfoTy &CombinedInfo,
8524 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8525 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const {
8526 assert(CurDir.is<const OMPExecutableDirective *>() &&(static_cast <bool> (CurDir.is<const OMPExecutableDirective
*>() && "Expect a executable directive") ? void (
0) : __assert_fail ("CurDir.is<const OMPExecutableDirective *>() && \"Expect a executable directive\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8527, __extension__
__PRETTY_FUNCTION__))
8527 "Expect a executable directive")(static_cast <bool> (CurDir.is<const OMPExecutableDirective
*>() && "Expect a executable directive") ? void (
0) : __assert_fail ("CurDir.is<const OMPExecutableDirective *>() && \"Expect a executable directive\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8527, __extension__
__PRETTY_FUNCTION__))
;
8528 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8529 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, SkipVarSet);
8530 }
8531
8532 /// Generate all the base pointers, section pointers, sizes, map types, and
8533 /// mappers for the extracted map clauses of user-defined mapper (all included
8534 /// in \a CombinedInfo).
8535 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const {
8536 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&(static_cast <bool> (CurDir.is<const OMPDeclareMapperDecl
*>() && "Expect a declare mapper directive") ? void
(0) : __assert_fail ("CurDir.is<const OMPDeclareMapperDecl *>() && \"Expect a declare mapper directive\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8537, __extension__
__PRETTY_FUNCTION__))
8537 "Expect a declare mapper directive")(static_cast <bool> (CurDir.is<const OMPDeclareMapperDecl
*>() && "Expect a declare mapper directive") ? void
(0) : __assert_fail ("CurDir.is<const OMPDeclareMapperDecl *>() && \"Expect a declare mapper directive\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8537, __extension__
__PRETTY_FUNCTION__))
;
8538 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8539 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo);
8540 }
8541
8542 /// Emit capture info for lambdas for variables captured by reference.
8543 void generateInfoForLambdaCaptures(
8544 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8545 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
8546 QualType VDType = VD->getType().getCanonicalType().getNonReferenceType();
8547 const auto *RD = VDType->getAsCXXRecordDecl();
8548 if (!RD || !RD->isLambda())
8549 return;
8550 Address VDAddr(Arg, CGF.ConvertTypeForMem(VDType),
8551 CGF.getContext().getDeclAlign(VD));
8552 LValue VDLVal = CGF.MakeAddrLValue(VDAddr, VDType);
8553 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
8554 FieldDecl *ThisCapture = nullptr;
8555 RD->getCaptureFields(Captures, ThisCapture);
8556 if (ThisCapture) {
8557 LValue ThisLVal =
8558 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
8559 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
8560 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
8561 VDLVal.getPointer(CGF));
8562 CombinedInfo.Exprs.push_back(VD);
8563 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
8564 CombinedInfo.DevicePtrDecls.push_back(nullptr);
8565 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
8566 CombinedInfo.Sizes.push_back(
8567 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8568 CGF.Int64Ty, /*isSigned=*/true));
8569 CombinedInfo.Types.push_back(
8570 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8571 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8572 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8573 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
8574 CombinedInfo.Mappers.push_back(nullptr);
8575 }
8576 for (const LambdaCapture &LC : RD->captures()) {
8577 if (!LC.capturesVariable())
8578 continue;
8579 const VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
8580 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8581 continue;
8582 auto It = Captures.find(VD);
8583 assert(It != Captures.end() && "Found lambda capture without field.")(static_cast <bool> (It != Captures.end() && "Found lambda capture without field."
) ? void (0) : __assert_fail ("It != Captures.end() && \"Found lambda capture without field.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8583, __extension__
__PRETTY_FUNCTION__))
;
8584 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
8585 if (LC.getCaptureKind() == LCK_ByRef) {
8586 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8587 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8588 VDLVal.getPointer(CGF));
8589 CombinedInfo.Exprs.push_back(VD);
8590 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
8591 CombinedInfo.DevicePtrDecls.push_back(nullptr);
8592 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
8593 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
8594 CGF.getTypeSize(
8595 VD->getType().getCanonicalType().getNonReferenceType()),
8596 CGF.Int64Ty, /*isSigned=*/true));
8597 } else {
8598 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
8599 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8600 VDLVal.getPointer(CGF));
8601 CombinedInfo.Exprs.push_back(VD);
8602 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
8603 CombinedInfo.DevicePtrDecls.push_back(nullptr);
8604 CombinedInfo.Pointers.push_back(VarRVal.getScalarVal());
8605 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8606 }
8607 CombinedInfo.Types.push_back(
8608 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8609 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8610 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8611 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
8612 CombinedInfo.Mappers.push_back(nullptr);
8613 }
8614 }
8615
8616 /// Set correct indices for lambdas captures.
8617 void adjustMemberOfForLambdaCaptures(
8618 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8619 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8620 MapFlagsArrayTy &Types) const {
8621 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8622 // Set correct member_of idx for all implicit lambda captures.
8623 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8624 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
8625 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8626 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
8627 continue;
8628 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
8629 assert(BasePtr && "Unable to find base lambda address.")(static_cast <bool> (BasePtr && "Unable to find base lambda address."
) ? void (0) : __assert_fail ("BasePtr && \"Unable to find base lambda address.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8629, __extension__
__PRETTY_FUNCTION__))
;
8630 int TgtIdx = -1;
8631 for (unsigned J = I; J > 0; --J) {
8632 unsigned Idx = J - 1;
8633 if (Pointers[Idx] != BasePtr)
8634 continue;
8635 TgtIdx = Idx;
8636 break;
8637 }
8638 assert(TgtIdx != -1 && "Unable to find parent lambda.")(static_cast <bool> (TgtIdx != -1 && "Unable to find parent lambda."
) ? void (0) : __assert_fail ("TgtIdx != -1 && \"Unable to find parent lambda.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8638, __extension__
__PRETTY_FUNCTION__))
;
8639 // All other current entries will be MEMBER_OF the combined entry
8640 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8641 // 0xFFFF in the MEMBER_OF field).
8642 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8643 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8644 }
8645 }
8646
8647 /// Generate the base pointers, section pointers, sizes, map types, and
8648 /// mappers associated to a given capture (all included in \a CombinedInfo).
8649 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
8650 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8651 StructRangeInfoTy &PartialStruct) const {
8652 assert(!Cap->capturesVariableArrayType() &&(static_cast <bool> (!Cap->capturesVariableArrayType
() && "Not expecting to generate map info for a variable array type!"
) ? void (0) : __assert_fail ("!Cap->capturesVariableArrayType() && \"Not expecting to generate map info for a variable array type!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8653, __extension__
__PRETTY_FUNCTION__))
8653 "Not expecting to generate map info for a variable array type!")(static_cast <bool> (!Cap->capturesVariableArrayType
() && "Not expecting to generate map info for a variable array type!"
) ? void (0) : __assert_fail ("!Cap->capturesVariableArrayType() && \"Not expecting to generate map info for a variable array type!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8653, __extension__
__PRETTY_FUNCTION__))
;
8654
8655 // We need to know when we generating information for the first component
8656 const ValueDecl *VD = Cap->capturesThis()
8657 ? nullptr
8658 : Cap->getCapturedVar()->getCanonicalDecl();
8659
8660 // for map(to: lambda): skip here, processing it in
8661 // generateDefaultMapInfo
8662 if (LambdasMap.count(VD))
8663 return;
8664
8665 // If this declaration appears in a is_device_ptr clause we just have to
8666 // pass the pointer by value. If it is a reference to a declaration, we just
8667 // pass its value.
8668 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
8669 CombinedInfo.Exprs.push_back(VD);
8670 CombinedInfo.BasePointers.emplace_back(Arg);
8671 CombinedInfo.DevicePtrDecls.emplace_back(VD);
8672 CombinedInfo.Pointers.push_back(Arg);
8673 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
8674 CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty,
8675 /*isSigned=*/true));
8676 CombinedInfo.Types.push_back(
8677 (Cap->capturesVariable()
8678 ? OpenMPOffloadMappingFlags::OMP_MAP_TO
8679 : OpenMPOffloadMappingFlags::OMP_MAP_LITERAL) |
8680 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
8681 CombinedInfo.Mappers.push_back(nullptr);
8682 return;
8683 }
8684
8685 using MapData =
8686 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
8687 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool,
8688 const ValueDecl *, const Expr *>;
8689 SmallVector<MapData, 4> DeclComponentLists;
8690 // For member fields list in is_device_ptr, store it in
8691 // DeclComponentLists for generating components info.
8692 static const OpenMPMapModifierKind Unknown = OMPC_MAP_MODIFIER_unknown;
8693 auto It = DevPointersMap.find(VD);
8694 if (It != DevPointersMap.end())
8695 for (const auto &MCL : It->second)
8696 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to, Unknown,
8697 /*IsImpicit = */ true, nullptr,
8698 nullptr);
8699 auto I = HasDevAddrsMap.find(VD);
8700 if (I != HasDevAddrsMap.end())
8701 for (const auto &MCL : I->second)
8702 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom, Unknown,
8703 /*IsImpicit = */ true, nullptr,
8704 nullptr);
8705 assert(CurDir.is<const OMPExecutableDirective *>() &&(static_cast <bool> (CurDir.is<const OMPExecutableDirective
*>() && "Expect a executable directive") ? void (
0) : __assert_fail ("CurDir.is<const OMPExecutableDirective *>() && \"Expect a executable directive\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8706, __extension__
__PRETTY_FUNCTION__))
8706 "Expect a executable directive")(static_cast <bool> (CurDir.is<const OMPExecutableDirective
*>() && "Expect a executable directive") ? void (
0) : __assert_fail ("CurDir.is<const OMPExecutableDirective *>() && \"Expect a executable directive\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8706, __extension__
__PRETTY_FUNCTION__))
;
8707 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8708 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
8709 const auto *EI = C->getVarRefs().begin();
8710 for (const auto L : C->decl_component_lists(VD)) {
8711 const ValueDecl *VDecl, *Mapper;
8712 // The Expression is not correct if the mapping is implicit
8713 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr;
8714 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8715 std::tie(VDecl, Components, Mapper) = L;
8716 assert(VDecl == VD && "We got information for the wrong declaration??")(static_cast <bool> (VDecl == VD && "We got information for the wrong declaration??"
) ? void (0) : __assert_fail ("VDecl == VD && \"We got information for the wrong declaration??\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8716, __extension__
__PRETTY_FUNCTION__))
;
8717 assert(!Components.empty() &&(static_cast <bool> (!Components.empty() && "Not expecting declaration with no component lists."
) ? void (0) : __assert_fail ("!Components.empty() && \"Not expecting declaration with no component lists.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8718, __extension__
__PRETTY_FUNCTION__))
8718 "Not expecting declaration with no component lists.")(static_cast <bool> (!Components.empty() && "Not expecting declaration with no component lists."
) ? void (0) : __assert_fail ("!Components.empty() && \"Not expecting declaration with no component lists.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8718, __extension__
__PRETTY_FUNCTION__))
;
8719 DeclComponentLists.emplace_back(Components, C->getMapType(),
8720 C->getMapTypeModifiers(),
8721 C->isImplicit(), Mapper, E);
8722 ++EI;
8723 }
8724 }
8725 llvm::stable_sort(DeclComponentLists, [](const MapData &LHS,
8726 const MapData &RHS) {
8727 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
8728 OpenMPMapClauseKind MapType = std::get<1>(RHS);
8729 bool HasPresent =
8730 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
8731 bool HasAllocs = MapType == OMPC_MAP_alloc;
8732 MapModifiers = std::get<2>(RHS);
8733 MapType = std::get<1>(LHS);
8734 bool HasPresentR =
8735 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
8736 bool HasAllocsR = MapType == OMPC_MAP_alloc;
8737 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
8738 });
8739
8740 // Find overlapping elements (including the offset from the base element).
8741 llvm::SmallDenseMap<
8742 const MapData *,
8743 llvm::SmallVector<
8744 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8745 4>
8746 OverlappedData;
8747 size_t Count = 0;
8748 for (const MapData &L : DeclComponentLists) {
8749 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8750 OpenMPMapClauseKind MapType;
8751 ArrayRef<OpenMPMapModifierKind> MapModifiers;
8752 bool IsImplicit;
8753 const ValueDecl *Mapper;
8754 const Expr *VarRef;
8755 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
8756 L;
8757 ++Count;
8758 for (const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
8759 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
8760 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
8761 VarRef) = L1;
8762 auto CI = Components.rbegin();
8763 auto CE = Components.rend();
8764 auto SI = Components1.rbegin();
8765 auto SE = Components1.rend();
8766 for (; CI != CE && SI != SE; ++CI, ++SI) {
8767 if (CI->getAssociatedExpression()->getStmtClass() !=
8768 SI->getAssociatedExpression()->getStmtClass())
8769 break;
8770 // Are we dealing with different variables/fields?
8771 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8772 break;
8773 }
8774 // Found overlapping if, at least for one component, reached the head
8775 // of the components list.
8776 if (CI == CE || SI == SE) {
8777 // Ignore it if it is the same component.
8778 if (CI == CE && SI == SE)
8779 continue;
8780 const auto It = (SI == SE) ? CI : SI;
8781 // If one component is a pointer and another one is a kind of
8782 // dereference of this pointer (array subscript, section, dereference,
8783 // etc.), it is not an overlapping.
8784 // Same, if one component is a base and another component is a
8785 // dereferenced pointer memberexpr with the same base.
8786 if (!isa<MemberExpr>(It->getAssociatedExpression()) ||
8787 (std::prev(It)->getAssociatedDeclaration() &&
8788 std::prev(It)
8789 ->getAssociatedDeclaration()
8790 ->getType()
8791 ->isPointerType()) ||
8792 (It->getAssociatedDeclaration() &&
8793 It->getAssociatedDeclaration()->getType()->isPointerType() &&
8794 std::next(It) != CE && std::next(It) != SE))
8795 continue;
8796 const MapData &BaseData = CI == CE ? L : L1;
8797 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8798 SI == SE ? Components : Components1;
8799 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8800 OverlappedElements.getSecond().push_back(SubData);
8801 }
8802 }
8803 }
8804 // Sort the overlapped elements for each item.
8805 llvm::SmallVector<const FieldDecl *, 4> Layout;
8806 if (!OverlappedData.empty()) {
8807 const Type *BaseType = VD->getType().getCanonicalType().getTypePtr();
8808 const Type *OrigType = BaseType->getPointeeOrArrayElementType();
8809 while (BaseType != OrigType) {
8810 BaseType = OrigType->getCanonicalTypeInternal().getTypePtr();
8811 OrigType = BaseType->getPointeeOrArrayElementType();
8812 }
8813
8814 if (const auto *CRD = BaseType->getAsCXXRecordDecl())
8815 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8816 else {
8817 const auto *RD = BaseType->getAsRecordDecl();
8818 Layout.append(RD->field_begin(), RD->field_end());
8819 }
8820 }
8821 for (auto &Pair : OverlappedData) {
8822 llvm::stable_sort(
8823 Pair.getSecond(),
8824 [&Layout](
8825 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8826 OMPClauseMappableExprCommon::MappableExprComponentListRef
8827 Second) {
8828 auto CI = First.rbegin();
8829 auto CE = First.rend();
8830 auto SI = Second.rbegin();
8831 auto SE = Second.rend();
8832 for (; CI != CE && SI != SE; ++CI, ++SI) {
8833 if (CI->getAssociatedExpression()->getStmtClass() !=
8834 SI->getAssociatedExpression()->getStmtClass())
8835 break;
8836 // Are we dealing with different variables/fields?
8837 if (CI->getAssociatedDeclaration() !=
8838 SI->getAssociatedDeclaration())
8839 break;
8840 }
8841
8842 // Lists contain the same elements.
8843 if (CI == CE && SI == SE)
8844 return false;
8845
8846 // List with less elements is less than list with more elements.
8847 if (CI == CE || SI == SE)
8848 return CI == CE;
8849
8850 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8851 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8852 if (FD1->getParent() == FD2->getParent())
8853 return FD1->getFieldIndex() < FD2->getFieldIndex();
8854 const auto *It =
8855 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8856 return FD == FD1 || FD == FD2;
8857 });
8858 return *It == FD1;
8859 });
8860 }
8861
8862 // Associated with a capture, because the mapping flags depend on it.
8863 // Go through all of the elements with the overlapped elements.
8864 bool IsFirstComponentList = true;
8865 for (const auto &Pair : OverlappedData) {
8866 const MapData &L = *Pair.getFirst();
8867 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8868 OpenMPMapClauseKind MapType;
8869 ArrayRef<OpenMPMapModifierKind> MapModifiers;
8870 bool IsImplicit;
8871 const ValueDecl *Mapper;
8872 const Expr *VarRef;
8873 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
8874 L;
8875 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8876 OverlappedComponents = Pair.getSecond();
8877 generateInfoForComponentList(
8878 MapType, MapModifiers, std::nullopt, Components, CombinedInfo,
8879 PartialStruct, IsFirstComponentList, IsImplicit, Mapper,
8880 /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents);
8881 IsFirstComponentList = false;
8882 }
8883 // Go through other elements without overlapped elements.
8884 for (const MapData &L : DeclComponentLists) {
8885 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8886 OpenMPMapClauseKind MapType;
8887 ArrayRef<OpenMPMapModifierKind> MapModifiers;
8888 bool IsImplicit;
8889 const ValueDecl *Mapper;
8890 const Expr *VarRef;
8891 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
8892 L;
8893 auto It = OverlappedData.find(&L);
8894 if (It == OverlappedData.end())
8895 generateInfoForComponentList(MapType, MapModifiers, std::nullopt,
8896 Components, CombinedInfo, PartialStruct,
8897 IsFirstComponentList, IsImplicit, Mapper,
8898 /*ForDeviceAddr=*/false, VD, VarRef);
8899 IsFirstComponentList = false;
8900 }
8901 }
8902
8903 /// Generate the default map information for a given capture \a CI,
8904 /// record field declaration \a RI and captured value \a CV.
8905 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8906 const FieldDecl &RI, llvm::Value *CV,
8907 MapCombinedInfoTy &CombinedInfo) const {
8908 bool IsImplicit = true;
8909 // Do the default mapping.
8910 if (CI.capturesThis()) {
8911 CombinedInfo.Exprs.push_back(nullptr);
8912 CombinedInfo.BasePointers.push_back(CV);
8913 CombinedInfo.DevicePtrDecls.push_back(nullptr);
8914 CombinedInfo.Pointers.push_back(CV);
8915 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
8916 CombinedInfo.Sizes.push_back(
8917 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8918 CGF.Int64Ty, /*isSigned=*/true));
8919 // Default map type.
8920 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8921 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
8922 } else if (CI.capturesVariableByCopy()) {
8923 const VarDecl *VD = CI.getCapturedVar();
8924 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl());
8925 CombinedInfo.BasePointers.push_back(CV);
8926 CombinedInfo.DevicePtrDecls.push_back(nullptr);
8927 CombinedInfo.Pointers.push_back(CV);
8928 if (!RI.getType()->isAnyPointerType()) {
8929 // We have to signal to the runtime captures passed by value that are
8930 // not pointers.
8931 CombinedInfo.Types.push_back(
8932 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
8933 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
8934 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
8935 } else {
8936 // Pointers are implicitly mapped with a zero size and no flags
8937 // (other than first map that is added for all implicit maps).
8938 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
8939 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
8940 }
8941 auto I = FirstPrivateDecls.find(VD);
8942 if (I != FirstPrivateDecls.end())
8943 IsImplicit = I->getSecond();
8944 } else {
8945 assert(CI.capturesVariable() && "Expected captured reference.")(static_cast <bool> (CI.capturesVariable() && "Expected captured reference."
) ? void (0) : __assert_fail ("CI.capturesVariable() && \"Expected captured reference.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 8945, __extension__
__PRETTY_FUNCTION__))
;
8946 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
8947 QualType ElementType = PtrTy->getPointeeType();
8948 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
8949 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
8950 // The default map type for a scalar/complex type is 'to' because by
8951 // default the value doesn't have to be retrieved. For an aggregate
8952 // type, the default is 'tofrom'.
8953 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
8954 const VarDecl *VD = CI.getCapturedVar();
8955 auto I = FirstPrivateDecls.find(VD);
8956 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl());
8957 CombinedInfo.BasePointers.push_back(CV);
8958 CombinedInfo.DevicePtrDecls.push_back(nullptr);
8959 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
8960 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8961 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8962 AlignmentSource::Decl));
8963 CombinedInfo.Pointers.push_back(PtrAddr.getPointer());
8964 } else {
8965 CombinedInfo.Pointers.push_back(CV);
8966 }
8967 if (I != FirstPrivateDecls.end())
8968 IsImplicit = I->getSecond();
8969 }
8970 // Every default map produces a single argument which is a target parameter.
8971 CombinedInfo.Types.back() |=
8972 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
8973
8974 // Add flag stating this is an implicit map.
8975 if (IsImplicit)
8976 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
8977
8978 // No user-defined mapper for default mapping.
8979 CombinedInfo.Mappers.push_back(nullptr);
8980 }
8981};
8982} // anonymous namespace
8983
8984static void emitNonContiguousDescriptor(
8985 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
8986 CGOpenMPRuntime::TargetDataInfo &Info) {
8987 CodeGenModule &CGM = CGF.CGM;
8988 MappableExprsHandler::MapCombinedInfoTy::StructNonContiguousInfo
8989 &NonContigInfo = CombinedInfo.NonContigInfo;
8990
8991 // Build an array of struct descriptor_dim and then assign it to
8992 // offload_args.
8993 //
8994 // struct descriptor_dim {
8995 // uint64_t offset;
8996 // uint64_t count;
8997 // uint64_t stride
8998 // };
8999 ASTContext &C = CGF.getContext();
9000 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9001 RecordDecl *RD;
9002 RD = C.buildImplicitRecord("descriptor_dim");
9003 RD->startDefinition();
9004 addFieldToRecordDecl(C, RD, Int64Ty);
9005 addFieldToRecordDecl(C, RD, Int64Ty);
9006 addFieldToRecordDecl(C, RD, Int64Ty);
9007 RD->completeDefinition();
9008 QualType DimTy = C.getRecordType(RD);
9009
9010 enum { OffsetFD = 0, CountFD, StrideFD };
9011 // We need two index variable here since the size of "Dims" is the same as the
9012 // size of Components, however, the size of offset, count, and stride is equal
9013 // to the size of base declaration that is non-contiguous.
9014 for (unsigned I = 0, L = 0, E = NonContigInfo.Dims.size(); I < E; ++I) {
9015 // Skip emitting ir if dimension size is 1 since it cannot be
9016 // non-contiguous.
9017 if (NonContigInfo.Dims[I] == 1)
9018 continue;
9019 llvm::APInt Size(/*numBits=*/32, NonContigInfo.Dims[I]);
9020 QualType ArrayTy =
9021 C.getConstantArrayType(DimTy, Size, nullptr, ArrayType::Normal, 0);
9022 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
9023 for (unsigned II = 0, EE = NonContigInfo.Dims[I]; II < EE; ++II) {
9024 unsigned RevIdx = EE - II - 1;
9025 LValue DimsLVal = CGF.MakeAddrLValue(
9026 CGF.Builder.CreateConstArrayGEP(DimsAddr, II), DimTy);
9027 // Offset
9028 LValue OffsetLVal = CGF.EmitLValueForField(
9029 DimsLVal, *std::next(RD->field_begin(), OffsetFD));
9030 CGF.EmitStoreOfScalar(NonContigInfo.Offsets[L][RevIdx], OffsetLVal);
9031 // Count
9032 LValue CountLVal = CGF.EmitLValueForField(
9033 DimsLVal, *std::next(RD->field_begin(), CountFD));
9034 CGF.EmitStoreOfScalar(NonContigInfo.Counts[L][RevIdx], CountLVal);
9035 // Stride
9036 LValue StrideLVal = CGF.EmitLValueForField(
9037 DimsLVal, *std::next(RD->field_begin(), StrideFD));
9038 CGF.EmitStoreOfScalar(NonContigInfo.Strides[L][RevIdx], StrideLVal);
9039 }
9040 // args[I] = &dims
9041 Address DAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
9042 DimsAddr, CGM.Int8PtrTy, CGM.Int8Ty);
9043 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
9044 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
9045 Info.RTArgs.PointersArray, 0, I);
9046 Address PAddr(P, CGM.VoidPtrTy, CGF.getPointerAlign());
9047 CGF.Builder.CreateStore(DAddr.getPointer(), PAddr);
9048 ++L;
9049 }
9050}
9051
9052// Try to extract the base declaration from a `this->x` expression if possible.
9053static ValueDecl *getDeclFromThisExpr(const Expr *E) {
9054 if (!E)
9055 return nullptr;
9056
9057 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenCasts()))
9058 if (const MemberExpr *ME =
9059 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
9060 return ME->getMemberDecl();
9061 return nullptr;
9062}
9063
9064/// Emit a string constant containing the names of the values mapped to the
9065/// offloading runtime library.
9066llvm::Constant *
9067emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder,
9068 MappableExprsHandler::MappingExprInfo &MapExprs) {
9069
9070 uint32_t SrcLocStrSize;
9071 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
9072 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
9073
9074 SourceLocation Loc;
9075 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
9076 if (const ValueDecl *VD = getDeclFromThisExpr(MapExprs.getMapExpr()))
9077 Loc = VD->getLocation();
9078 else
9079 Loc = MapExprs.getMapExpr()->getExprLoc();
9080 } else {
9081 Loc = MapExprs.getMapDecl()->getLocation();
9082 }
9083
9084 std::string ExprName;
9085 if (MapExprs.getMapExpr()) {
9086 PrintingPolicy P(CGF.getContext().getLangOpts());
9087 llvm::raw_string_ostream OS(ExprName);
9088 MapExprs.getMapExpr()->printPretty(OS, nullptr, P);
9089 OS.flush();
9090 } else {
9091 ExprName = MapExprs.getMapDecl()->getNameAsString();
9092 }
9093
9094 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
9095 return OMPBuilder.getOrCreateSrcLocStr(PLoc.getFilename(), ExprName,
9096 PLoc.getLine(), PLoc.getColumn(),
9097 SrcLocStrSize);
9098}
9099
9100/// Emit the arrays used to pass the captures and map information to the
9101/// offloading runtime library. If there is no map or capture information,
9102/// return nullptr by reference.
9103static void emitOffloadingArrays(
9104 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
9105 CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder,
9106 bool IsNonContiguous = false) {
9107 CodeGenModule &CGM = CGF.CGM;
9108 ASTContext &Ctx = CGF.getContext();
9109
9110 // Reset the array information.
9111 Info.clearArrayInfo();
9112 Info.NumberOfPtrs = CombinedInfo.BasePointers.size();
9113
9114 if (Info.NumberOfPtrs) {
9115 // Detect if we have any capture size requiring runtime evaluation of the
9116 // size so that a constant array could be eventually used.
9117
9118 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
9119 QualType PointerArrayType = Ctx.getConstantArrayType(
9120 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
9121 /*IndexTypeQuals=*/0);
9122
9123 Info.RTArgs.BasePointersArray =
9124 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
9125 Info.RTArgs.PointersArray =
9126 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
9127 Address MappersArray =
9128 CGF.CreateMemTemp(PointerArrayType, ".offload_mappers");
9129 Info.RTArgs.MappersArray = MappersArray.getPointer();
9130
9131 // If we don't have any VLA types or other types that require runtime
9132 // evaluation, we can use a constant array for the map sizes, otherwise we
9133 // need to fill up the arrays as we do for the pointers.
9134 QualType Int64Ty =
9135 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9136 SmallVector<llvm::Constant *> ConstSizes(
9137 CombinedInfo.Sizes.size(), llvm::ConstantInt::get(CGF.Int64Ty, 0));
9138 llvm::SmallBitVector RuntimeSizes(CombinedInfo.Sizes.size());
9139 for (unsigned I = 0, E = CombinedInfo.Sizes.size(); I < E; ++I) {
9140 if (auto *CI = dyn_cast<llvm::Constant>(CombinedInfo.Sizes[I])) {
9141 if (!isa<llvm::ConstantExpr>(CI) && !isa<llvm::GlobalValue>(CI)) {
9142 if (IsNonContiguous &&
9143 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9144 CombinedInfo.Types[I] &
9145 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG))
9146 ConstSizes[I] = llvm::ConstantInt::get(
9147 CGF.Int64Ty, CombinedInfo.NonContigInfo.Dims[I]);
9148 else
9149 ConstSizes[I] = CI;
9150 continue;
9151 }
9152 }
9153 RuntimeSizes.set(I);
9154 }
9155
9156 if (RuntimeSizes.all()) {
9157 QualType SizeArrayType = Ctx.getConstantArrayType(
9158 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
9159 /*IndexTypeQuals=*/0);
9160 Info.RTArgs.SizesArray =
9161 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
9162 } else {
9163 auto *SizesArrayInit = llvm::ConstantArray::get(
9164 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
9165 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
9166 auto *SizesArrayGbl = new llvm::GlobalVariable(
9167 CGM.getModule(), SizesArrayInit->getType(), /*isConstant=*/true,
9168 llvm::GlobalValue::PrivateLinkage, SizesArrayInit, Name);
9169 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
9170 if (RuntimeSizes.any()) {
9171 QualType SizeArrayType = Ctx.getConstantArrayType(
9172 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
9173 /*IndexTypeQuals=*/0);
9174 Address Buffer = CGF.CreateMemTemp(SizeArrayType, ".offload_sizes");
9175 llvm::Value *GblConstPtr =
9176 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
9177 SizesArrayGbl, CGM.Int64Ty->getPointerTo());
9178 CGF.Builder.CreateMemCpy(
9179 Buffer,
9180 Address(GblConstPtr, CGM.Int64Ty,
9181 CGM.getNaturalTypeAlignment(Ctx.getIntTypeForBitwidth(
9182 /*DestWidth=*/64, /*Signed=*/false))),
9183 CGF.getTypeSize(SizeArrayType));
9184 Info.RTArgs.SizesArray = Buffer.getPointer();
9185 } else {
9186 Info.RTArgs.SizesArray = SizesArrayGbl;
9187 }
9188 }
9189
9190 // The map types are always constant so we don't need to generate code to
9191 // fill arrays. Instead, we create an array constant.
9192 SmallVector<uint64_t, 4> Mapping;
9193 for (auto mapFlag : CombinedInfo.Types)
9194 Mapping.push_back(
9195 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9196 mapFlag));
9197 std::string MaptypesName =
9198 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
9199 auto *MapTypesArrayGbl =
9200 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName);
9201 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
9202
9203 // The information types are only built if there is debug information
9204 // requested.
9205 if (CGM.getCodeGenOpts().getDebugInfo() ==
9206 llvm::codegenoptions::NoDebugInfo) {
9207 Info.RTArgs.MapNamesArray = llvm::Constant::getNullValue(
9208 llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo());
9209 } else {
9210 auto fillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
9211 return emitMappingInformation(CGF, OMPBuilder, MapExpr);
9212 };
9213 SmallVector<llvm::Constant *, 4> InfoMap(CombinedInfo.Exprs.size());
9214 llvm::transform(CombinedInfo.Exprs, InfoMap.begin(), fillInfoMap);
9215 std::string MapnamesName =
9216 CGM.getOpenMPRuntime().getName({"offload_mapnames"});
9217 auto *MapNamesArrayGbl =
9218 OMPBuilder.createOffloadMapnames(InfoMap, MapnamesName);
9219 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
9220 }
9221
9222 // If there's a present map type modifier, it must not be applied to the end
9223 // of a region, so generate a separate map type array in that case.
9224 if (Info.separateBeginEndCalls()) {
9225 bool EndMapTypesDiffer = false;
9226 for (uint64_t &Type : Mapping) {
9227 if (Type &
9228 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9229 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
9230 Type &=
9231 ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9232 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9233 EndMapTypesDiffer = true;
9234 }
9235 }
9236 if (EndMapTypesDiffer) {
9237 MapTypesArrayGbl =
9238 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName);
9239 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
9240 }
9241 }
9242
9243 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
9244 llvm::Value *BPVal = CombinedInfo.BasePointers[I];
9245 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
9246 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
9247 Info.RTArgs.BasePointersArray, 0, I);
9248 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
9249 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
9250 Address BPAddr(BP, BPVal->getType(),
9251 Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
9252 CGF.Builder.CreateStore(BPVal, BPAddr);
9253
9254 if (Info.requiresDevicePointerInfo())
9255 if (const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I])
9256 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
9257
9258 llvm::Value *PVal = CombinedInfo.Pointers[I];
9259 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
9260 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
9261 Info.RTArgs.PointersArray, 0, I);
9262 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
9263 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
9264 Address PAddr(P, PVal->getType(), Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
9265 CGF.Builder.CreateStore(PVal, PAddr);
9266
9267 if (RuntimeSizes.test(I)) {
9268 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
9269 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
9270 Info.RTArgs.SizesArray,
9271 /*Idx0=*/0,
9272 /*Idx1=*/I);
9273 Address SAddr(S, CGM.Int64Ty, Ctx.getTypeAlignInChars(Int64Ty));
9274 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(CombinedInfo.Sizes[I],
9275 CGM.Int64Ty,
9276 /*isSigned=*/true),
9277 SAddr);
9278 }
9279
9280 // Fill up the mapper array.
9281 llvm::Value *MFunc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
9282 if (CombinedInfo.Mappers[I]) {
9283 MFunc = CGM.getOpenMPRuntime().getOrCreateUserDefinedMapperFunc(
9284 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
9285 MFunc = CGF.Builder.CreatePointerCast(MFunc, CGM.VoidPtrTy);
9286 Info.HasMapper = true;
9287 }
9288 Address MAddr = CGF.Builder.CreateConstArrayGEP(MappersArray, I);
9289 CGF.Builder.CreateStore(MFunc, MAddr);
9290 }
9291 }
9292
9293 if (!IsNonContiguous || CombinedInfo.NonContigInfo.Offsets.empty() ||
9294 Info.NumberOfPtrs == 0)
9295 return;
9296
9297 emitNonContiguousDescriptor(CGF, CombinedInfo, Info);
9298}
9299
9300/// Check for inner distribute directive.
9301static const OMPExecutableDirective *
9302getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
9303 const auto *CS = D.getInnermostCapturedStmt();
9304 const auto *Body =
9305 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
9306 const Stmt *ChildStmt =
9307 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
9308
9309 if (const auto *NestedDir =
9310 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
9311 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
9312 switch (D.getDirectiveKind()) {
9313 case OMPD_target:
9314 if (isOpenMPDistributeDirective(DKind))
9315 return NestedDir;
9316 if (DKind == OMPD_teams) {
9317 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
9318 /*IgnoreCaptured=*/true);
9319 if (!Body)
9320 return nullptr;
9321 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
9322 if (const auto *NND =
9323 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
9324 DKind = NND->getDirectiveKind();
9325 if (isOpenMPDistributeDirective(DKind))
9326 return NND;
9327 }
9328 }
9329 return nullptr;
9330 case OMPD_target_teams:
9331 if (isOpenMPDistributeDirective(DKind))
9332 return NestedDir;
9333 return nullptr;
9334 case OMPD_target_parallel:
9335 case OMPD_target_simd:
9336 case OMPD_target_parallel_for:
9337 case OMPD_target_parallel_for_simd:
9338 return nullptr;
9339 case OMPD_target_teams_distribute:
9340 case OMPD_target_teams_distribute_simd:
9341 case OMPD_target_teams_distribute_parallel_for:
9342 case OMPD_target_teams_distribute_parallel_for_simd:
9343 case OMPD_parallel:
9344 case OMPD_for:
9345 case OMPD_parallel_for:
9346 case OMPD_parallel_master:
9347 case OMPD_parallel_sections:
9348 case OMPD_for_simd:
9349 case OMPD_parallel_for_simd:
9350 case OMPD_cancel:
9351 case OMPD_cancellation_point:
9352 case OMPD_ordered:
9353 case OMPD_threadprivate:
9354 case OMPD_allocate:
9355 case OMPD_task:
9356 case OMPD_simd:
9357 case OMPD_tile:
9358 case OMPD_unroll:
9359 case OMPD_sections:
9360 case OMPD_section:
9361 case OMPD_single:
9362 case OMPD_master:
9363 case OMPD_critical:
9364 case OMPD_taskyield:
9365 case OMPD_barrier:
9366 case OMPD_taskwait:
9367 case OMPD_taskgroup:
9368 case OMPD_atomic:
9369 case OMPD_flush:
9370 case OMPD_depobj:
9371 case OMPD_scan:
9372 case OMPD_teams:
9373 case OMPD_target_data:
9374 case OMPD_target_exit_data:
9375 case OMPD_target_enter_data:
9376 case OMPD_distribute:
9377 case OMPD_distribute_simd:
9378 case OMPD_distribute_parallel_for:
9379 case OMPD_distribute_parallel_for_simd:
9380 case OMPD_teams_distribute:
9381 case OMPD_teams_distribute_simd:
9382 case OMPD_teams_distribute_parallel_for:
9383 case OMPD_teams_distribute_parallel_for_simd:
9384 case OMPD_target_update:
9385 case OMPD_declare_simd:
9386 case OMPD_declare_variant:
9387 case OMPD_begin_declare_variant:
9388 case OMPD_end_declare_variant:
9389 case OMPD_declare_target:
9390 case OMPD_end_declare_target:
9391 case OMPD_declare_reduction:
9392 case OMPD_declare_mapper:
9393 case OMPD_taskloop:
9394 case OMPD_taskloop_simd:
9395 case OMPD_master_taskloop:
9396 case OMPD_master_taskloop_simd:
9397 case OMPD_parallel_master_taskloop:
9398 case OMPD_parallel_master_taskloop_simd:
9399 case OMPD_requires:
9400 case OMPD_metadirective:
9401 case OMPD_unknown:
9402 default:
9403 llvm_unreachable("Unexpected directive.")::llvm::llvm_unreachable_internal("Unexpected directive.", "clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9403)
;
9404 }
9405 }
9406
9407 return nullptr;
9408}
9409
9410/// Emit the user-defined mapper function. The code generation follows the
9411/// pattern in the example below.
9412/// \code
9413/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
9414/// void *base, void *begin,
9415/// int64_t size, int64_t type,
9416/// void *name = nullptr) {
9417/// // Allocate space for an array section first or add a base/begin for
9418/// // pointer dereference.
9419/// if ((size > 1 || (base != begin && maptype.IsPtrAndObj)) &&
9420/// !maptype.IsDelete)
9421/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
9422/// size*sizeof(Ty), clearToFromMember(type));
9423/// // Map members.
9424/// for (unsigned i = 0; i < size; i++) {
9425/// // For each component specified by this mapper:
9426/// for (auto c : begin[i]->all_components) {
9427/// if (c.hasMapper())
9428/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
9429/// c.arg_type, c.arg_name);
9430/// else
9431/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
9432/// c.arg_begin, c.arg_size, c.arg_type,
9433/// c.arg_name);
9434/// }
9435/// }
9436/// // Delete the array section.
9437/// if (size > 1 && maptype.IsDelete)
9438/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
9439/// size*sizeof(Ty), clearToFromMember(type));
9440/// }
9441/// \endcode
9442void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
9443 CodeGenFunction *CGF) {
9444 if (UDMMap.count(D) > 0)
9445 return;
9446 ASTContext &C = CGM.getContext();
9447 QualType Ty = D->getType();
9448 QualType PtrTy = C.getPointerType(Ty).withRestrict();
9449 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
9450 auto *MapperVarDecl =
9451 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
9452 SourceLocation Loc = D->getLocation();
9453 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
9454 llvm::Type *ElemTy = CGM.getTypes().ConvertTypeForMem(Ty);
9455
9456 // Prepare mapper function arguments and attributes.
9457 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
9458 C.VoidPtrTy, ImplicitParamDecl::Other);
9459 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
9460 ImplicitParamDecl::Other);
9461 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
9462 C.VoidPtrTy, ImplicitParamDecl::Other);
9463 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
9464 ImplicitParamDecl::Other);
9465 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
9466 ImplicitParamDecl::Other);
9467 ImplicitParamDecl NameArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
9468 ImplicitParamDecl::Other);
9469 FunctionArgList Args;
9470 Args.push_back(&HandleArg);
9471 Args.push_back(&BaseArg);
9472 Args.push_back(&BeginArg);
9473 Args.push_back(&SizeArg);
9474 Args.push_back(&TypeArg);
9475 Args.push_back(&NameArg);
9476 const CGFunctionInfo &FnInfo =
9477 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
9478 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
9479 SmallString<64> TyStr;
9480 llvm::raw_svector_ostream Out(TyStr);
9481 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
9482 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
9483 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
9484 Name, &CGM.getModule());
9485 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
9486 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
9487 // Start the mapper function code generation.
9488 CodeGenFunction MapperCGF(CGM);
9489 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
9490 // Compute the starting and end addresses of array elements.
9491 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
9492 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
9493 C.getPointerType(Int64Ty), Loc);
9494 // Prepare common arguments for array initiation and deletion.
9495 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
9496 MapperCGF.GetAddrOfLocalVar(&HandleArg),
9497 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9498 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
9499 MapperCGF.GetAddrOfLocalVar(&BaseArg),
9500 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9501 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
9502 MapperCGF.GetAddrOfLocalVar(&BeginArg),
9503 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9504 // Convert the size in bytes into the number of array elements.
9505 Size = MapperCGF.Builder.CreateExactUDiv(
9506 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9507 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
9508 BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy));
9509 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(ElemTy, PtrBegin, Size);
9510 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
9511 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
9512 C.getPointerType(Int64Ty), Loc);
9513 llvm::Value *MapName = MapperCGF.EmitLoadOfScalar(
9514 MapperCGF.GetAddrOfLocalVar(&NameArg),
9515 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9516
9517 // Emit array initiation if this is an array section and \p MapType indicates
9518 // that memory allocation is required.
9519 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
9520 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9521 MapName, ElementSize, HeadBB, /*IsInit=*/true);
9522
9523 // Emit a for loop to iterate through SizeArg of elements and map all of them.
9524
9525 // Emit the loop header block.
9526 MapperCGF.EmitBlock(HeadBB);
9527 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
9528 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
9529 // Evaluate whether the initial condition is satisfied.
9530 llvm::Value *IsEmpty =
9531 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
9532 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
9533 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
9534
9535 // Emit the loop body block.
9536 MapperCGF.EmitBlock(BodyBB);
9537 llvm::BasicBlock *LastBB = BodyBB;
9538 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
9539 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
9540 PtrPHI->addIncoming(PtrBegin, EntryBB);
9541 Address PtrCurrent(PtrPHI, ElemTy,
9542 MapperCGF.GetAddrOfLocalVar(&BeginArg)
9543 .getAlignment()
9544 .alignmentOfArrayElement(ElementSize));
9545 // Privatize the declared variable of mapper to be the current array element.
9546 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
9547 Scope.addPrivate(MapperVarDecl, PtrCurrent);
9548 (void)Scope.Privatize();
9549
9550 // Get map clause information. Fill up the arrays with all mapped variables.
9551 MappableExprsHandler::MapCombinedInfoTy Info;
9552 MappableExprsHandler MEHandler(*D, MapperCGF);
9553 MEHandler.generateAllInfoForMapper(Info);
9554
9555 // Call the runtime API __tgt_mapper_num_components to get the number of
9556 // pre-existing components.
9557 llvm::Value *OffloadingArgs[] = {Handle};
9558 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
9559 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
9560 OMPRTL___tgt_mapper_num_components),
9561 OffloadingArgs);
9562 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
9563 PreviousSize,
9564 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
9565
9566 // Fill up the runtime mapper handle for all components.
9567 for (unsigned I = 0; I < Info.BasePointers.size(); ++I) {
9568 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
9569 Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9570 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
9571 Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9572 llvm::Value *CurSizeArg = Info.Sizes[I];
9573 llvm::Value *CurNameArg =
9574 (CGM.getCodeGenOpts().getDebugInfo() ==
9575 llvm::codegenoptions::NoDebugInfo)
9576 ? llvm::ConstantPointerNull::get(CGM.VoidPtrTy)
9577 : emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]);
9578
9579 // Extract the MEMBER_OF field from the map type.
9580 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(
9581 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9582 Info.Types[I]));
9583 llvm::Value *MemberMapType =
9584 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
9585
9586 // Combine the map type inherited from user-defined mapper with that
9587 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
9588 // bits of the \a MapType, which is the input argument of the mapper
9589 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
9590 // bits of MemberMapType.
9591 // [OpenMP 5.0], 1.2.6. map-type decay.
9592 // | alloc | to | from | tofrom | release | delete
9593 // ----------------------------------------------------------
9594 // alloc | alloc | alloc | alloc | alloc | release | delete
9595 // to | alloc | to | alloc | to | release | delete
9596 // from | alloc | alloc | from | from | release | delete
9597 // tofrom | alloc | to | from | tofrom | release | delete
9598 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9599 MapType,
9600 MapperCGF.Builder.getInt64(
9601 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9602 OpenMPOffloadMappingFlags::OMP_MAP_TO |
9603 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
9604 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9605 llvm::BasicBlock *AllocElseBB =
9606 MapperCGF.createBasicBlock("omp.type.alloc.else");
9607 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9608 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9609 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9610 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9611 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9612 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9613 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9614 MapperCGF.EmitBlock(AllocBB);
9615 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9616 MemberMapType,
9617 MapperCGF.Builder.getInt64(
9618 ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9619 OpenMPOffloadMappingFlags::OMP_MAP_TO |
9620 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
9621 MapperCGF.Builder.CreateBr(EndBB);
9622 MapperCGF.EmitBlock(AllocElseBB);
9623 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9624 LeftToFrom,
9625 MapperCGF.Builder.getInt64(
9626 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9627 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
9628 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9629 // In case of to, clear OMP_MAP_FROM.
9630 MapperCGF.EmitBlock(ToBB);
9631 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9632 MemberMapType,
9633 MapperCGF.Builder.getInt64(
9634 ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9635 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
9636 MapperCGF.Builder.CreateBr(EndBB);
9637 MapperCGF.EmitBlock(ToElseBB);
9638 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9639 LeftToFrom,
9640 MapperCGF.Builder.getInt64(
9641 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9642 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
9643 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9644 // In case of from, clear OMP_MAP_TO.
9645 MapperCGF.EmitBlock(FromBB);
9646 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9647 MemberMapType,
9648 MapperCGF.Builder.getInt64(
9649 ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9650 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
9651 // In case of tofrom, do nothing.
9652 MapperCGF.EmitBlock(EndBB);
9653 LastBB = EndBB;
9654 llvm::PHINode *CurMapType =
9655 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9656 CurMapType->addIncoming(AllocMapType, AllocBB);
9657 CurMapType->addIncoming(ToMapType, ToBB);
9658 CurMapType->addIncoming(FromMapType, FromBB);
9659 CurMapType->addIncoming(MemberMapType, ToElseBB);
9660
9661 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9662 CurSizeArg, CurMapType, CurNameArg};
9663 if (Info.Mappers[I]) {
9664 // Call the corresponding mapper function.
9665 llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc(
9666 cast<OMPDeclareMapperDecl>(Info.Mappers[I]));
9667 assert(MapperFunc && "Expect a valid mapper function is available.")(static_cast <bool> (MapperFunc && "Expect a valid mapper function is available."
) ? void (0) : __assert_fail ("MapperFunc && \"Expect a valid mapper function is available.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 9667, __extension__
__PRETTY_FUNCTION__))
;
9668 MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs);
9669 } else {
9670 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9671 // data structure.
9672 MapperCGF.EmitRuntimeCall(
9673 OMPBuilder.getOrCreateRuntimeFunction(
9674 CGM.getModule(), OMPRTL___tgt_push_mapper_component),
9675 OffloadingArgs);
9676 }
9677 }
9678
9679 // Update the pointer to point to the next element that needs to be mapped,
9680 // and check whether we have mapped all elements.
9681 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9682 ElemTy, PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9683 PtrPHI->addIncoming(PtrNext, LastBB);
9684 llvm::Value *IsDone =
9685 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9686 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9687 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9688
9689 MapperCGF.EmitBlock(ExitBB);
9690 // Emit array deletion if this is an array section and \p MapType indicates
9691 // that deletion is required.
9692 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9693 MapName, ElementSize, DoneBB, /*IsInit=*/false);
9694
9695 // Emit the function exit block.
9696 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9697 MapperCGF.FinishFunction();
9698 UDMMap.try_emplace(D, Fn);
9699 if (CGF) {
9700 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9701 Decls.second.push_back(D);
9702 }
9703}
9704
9705/// Emit the array initialization or deletion portion for user-defined mapper
9706/// code generation. First, it evaluates whether an array section is mapped and
9707/// whether the \a MapType instructs to delete this section. If \a IsInit is
9708/// true, and \a MapType indicates to not delete this array, array
9709/// initialization code is generated. If \a IsInit is false, and \a MapType
9710/// indicates to not this array, array deletion code is generated.
9711void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9712 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9713 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9714 llvm::Value *MapName, CharUnits ElementSize, llvm::BasicBlock *ExitBB,
9715 bool IsInit) {
9716 StringRef Prefix = IsInit ? ".init" : ".del";
9717
9718 // Evaluate if this is an array section.
9719 llvm::BasicBlock *BodyBB =
9720 MapperCGF.createBasicBlock(getName({"omp.array", Prefix}));
9721 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGT(
9722 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9723 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9724 MapType,
9725 MapperCGF.Builder.getInt64(
9726 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9727 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
9728 llvm::Value *DeleteCond;
9729 llvm::Value *Cond;
9730 if (IsInit) {
9731 // base != begin?
9732 llvm::Value *BaseIsBegin = MapperCGF.Builder.CreateICmpNE(Base, Begin);
9733 // IsPtrAndObj?
9734 llvm::Value *PtrAndObjBit = MapperCGF.Builder.CreateAnd(
9735 MapType,
9736 MapperCGF.Builder.getInt64(
9737 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9738 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ)));
9739 PtrAndObjBit = MapperCGF.Builder.CreateIsNotNull(PtrAndObjBit);
9740 BaseIsBegin = MapperCGF.Builder.CreateAnd(BaseIsBegin, PtrAndObjBit);
9741 Cond = MapperCGF.Builder.CreateOr(IsArray, BaseIsBegin);
9742 DeleteCond = MapperCGF.Builder.CreateIsNull(
9743 DeleteBit, getName({"omp.array", Prefix, ".delete"}));
9744 } else {
9745 Cond = IsArray;
9746 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9747 DeleteBit, getName({"omp.array", Prefix, ".delete"}));
9748 }
9749 Cond = MapperCGF.Builder.CreateAnd(Cond, DeleteCond);
9750 MapperCGF.Builder.CreateCondBr(Cond, BodyBB, ExitBB);
9751
9752 MapperCGF.EmitBlock(BodyBB);
9753 // Get the array size by multiplying element size and element number (i.e., \p
9754 // Size).
9755 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9756 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9757 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9758 // memory allocation/deletion purpose only.
9759 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9760 MapType,
9761 MapperCGF.Builder.getInt64(
9762 ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9763 OpenMPOffloadMappingFlags::OMP_MAP_TO |
9764 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
9765 MapTypeArg = MapperCGF.Builder.CreateOr(
9766 MapTypeArg,
9767 MapperCGF.Builder.getInt64(
9768 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9769 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
9770
9771 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9772 // data structure.
9773 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin,
9774 ArraySize, MapTypeArg, MapName};
9775 MapperCGF.EmitRuntimeCall(
9776 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
9777 OMPRTL___tgt_push_mapper_component),
9778 OffloadingArgs);
9779}
9780
9781llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc(
9782 const OMPDeclareMapperDecl *D) {
9783 auto I = UDMMap.find(D);
9784 if (I != UDMMap.end())
9785 return I->second;
9786 emitUserDefinedMapper(D);
9787 return UDMMap.lookup(D);
9788}
9789
9790llvm::Value *CGOpenMPRuntime::emitTargetNumIterationsCall(
9791 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9792 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9793 const OMPLoopDirective &D)>
9794 SizeEmitter) {
9795 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9796 const OMPExecutableDirective *TD = &D;
9797 // Get nested teams distribute kind directive, if any.
9798 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9799 TD = getNestedDistributeDirective(CGM.getContext(), D);
9800 if (!TD)
9801 return llvm::ConstantInt::get(CGF.Int64Ty, 0);
9802
9803 const auto *LD = cast<OMPLoopDirective>(TD);
9804 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
9805 return NumIterations;
9806 return llvm::ConstantInt::get(CGF.Int64Ty, 0);
9807}
9808
9809void CGOpenMPRuntime::emitTargetCall(
9810 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9811 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9812 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device,
9813 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9814 const OMPLoopDirective &D)>
9815 SizeEmitter) {
9816 if (!CGF.HaveInsertPoint())
9817 return;
9818
9819 const bool OffloadingMandatory = !CGM.getLangOpts().OpenMPIsDevice &&
9820 CGM.getLangOpts().OpenMPOffloadMandatory;
9821
9822 assert((OffloadingMandatory || OutlinedFn) && "Invalid outlined function!")(static_cast <bool> ((OffloadingMandatory || OutlinedFn
) && "Invalid outlined function!") ? void (0) : __assert_fail
("(OffloadingMandatory || OutlinedFn) && \"Invalid outlined function!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 9822, __extension__
__PRETTY_FUNCTION__))
;
9823
9824 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() ||
9825 D.hasClausesOfKind<OMPNowaitClause>() ||
9826 D.hasClausesOfKind<OMPInReductionClause>();
9827 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
9828 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
9829 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9830 PrePostActionTy &) {
9831 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9832 };
9833 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
9834
9835 CodeGenFunction::OMPTargetDataInfo InputInfo;
9836 llvm::Value *MapTypesArray = nullptr;
9837 llvm::Value *MapNamesArray = nullptr;
9838 // Generate code for the host fallback function.
9839 auto &&FallbackGen = [this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask,
9840 &CS, OffloadingMandatory](CodeGenFunction &CGF) {
9841 if (OffloadingMandatory) {
9842 CGF.Builder.CreateUnreachable();
9843 } else {
9844 if (RequiresOuterTask) {
9845 CapturedVars.clear();
9846 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9847 }
9848 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
9849 }
9850 };
9851 // Fill up the pointer arrays and transfer execution to the device.
9852 auto &&ThenGen = [this, Device, OutlinedFnID, &D, &InputInfo, &MapTypesArray,
9853 &MapNamesArray, SizeEmitter,
9854 FallbackGen](CodeGenFunction &CGF, PrePostActionTy &) {
9855 if (Device.getInt() == OMPC_DEVICE_ancestor) {
9856 // Reverse offloading is not supported, so just execute on the host.
9857 FallbackGen(CGF);
9858 return;
9859 }
9860
9861 // On top of the arrays that were filled up, the target offloading call
9862 // takes as arguments the device id as well as the host pointer. The host
9863 // pointer is used by the runtime library to identify the current target
9864 // region, so it only has to be unique and not necessarily point to
9865 // anything. It could be the pointer to the outlined function that
9866 // implements the target region, but we aren't using that so that the
9867 // compiler doesn't need to keep that, and could therefore inline the host
9868 // function if proven worthwhile during optimization.
9869
9870 // From this point on, we need to have an ID of the target region defined.
9871 assert(OutlinedFnID && "Invalid outlined function ID!")(static_cast <bool> (OutlinedFnID && "Invalid outlined function ID!"
) ? void (0) : __assert_fail ("OutlinedFnID && \"Invalid outlined function ID!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 9871, __extension__
__PRETTY_FUNCTION__))
;
9872 (void)OutlinedFnID;
9873
9874 // Emit device ID if any.
9875 llvm::Value *DeviceID;
9876 if (Device.getPointer()) {
9877 assert((Device.getInt() == OMPC_DEVICE_unknown ||(static_cast <bool> ((Device.getInt() == OMPC_DEVICE_unknown
|| Device.getInt() == OMPC_DEVICE_device_num) && "Expected device_num modifier."
) ? void (0) : __assert_fail ("(Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() == OMPC_DEVICE_device_num) && \"Expected device_num modifier.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 9879, __extension__
__PRETTY_FUNCTION__))
9878 Device.getInt() == OMPC_DEVICE_device_num) &&(static_cast <bool> ((Device.getInt() == OMPC_DEVICE_unknown
|| Device.getInt() == OMPC_DEVICE_device_num) && "Expected device_num modifier."
) ? void (0) : __assert_fail ("(Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() == OMPC_DEVICE_device_num) && \"Expected device_num modifier.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 9879, __extension__
__PRETTY_FUNCTION__))
9879 "Expected device_num modifier.")(static_cast <bool> ((Device.getInt() == OMPC_DEVICE_unknown
|| Device.getInt() == OMPC_DEVICE_device_num) && "Expected device_num modifier."
) ? void (0) : __assert_fail ("(Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() == OMPC_DEVICE_device_num) && \"Expected device_num modifier.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 9879, __extension__
__PRETTY_FUNCTION__))
;
9880 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer());
9881 DeviceID =
9882 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true);
9883 } else {
9884 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9885 }
9886
9887 // Emit the number of elements in the offloading arrays.
9888 llvm::Value *PointerNum =
9889 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
9890
9891 // Return value of the runtime offloading call.
9892 llvm::Value *Return;
9893
9894 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9895 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
9896
9897 // Source location for the ident struct
9898 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
9899
9900 // Get tripcount for the target loop-based directive.
9901 llvm::Value *NumIterations =
9902 emitTargetNumIterationsCall(CGF, D, SizeEmitter);
9903
9904 llvm::Value *DynCGroupMem = CGF.Builder.getInt32(0);
9905 if (auto *DynMemClause = D.getSingleClause<OMPXDynCGroupMemClause>()) {
9906 CodeGenFunction::RunCleanupsScope DynCGroupMemScope(CGF);
9907 llvm::Value *DynCGroupMemVal = CGF.EmitScalarExpr(
9908 DynMemClause->getSize(), /*IgnoreResultAssign=*/true);
9909 DynCGroupMem = CGF.Builder.CreateIntCast(DynCGroupMemVal, CGF.Int32Ty,
9910 /*isSigned=*/false);
9911 }
9912
9913 llvm::Value *ZeroArray =
9914 llvm::Constant::getNullValue(llvm::ArrayType::get(CGF.CGM.Int32Ty, 3));
9915
9916 bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>();
9917 llvm::Value *Flags = CGF.Builder.getInt64(HasNoWait);
9918
9919 llvm::Value *NumTeams3D =
9920 CGF.Builder.CreateInsertValue(ZeroArray, NumTeams, {0});
9921 llvm::Value *NumThreads3D =
9922 CGF.Builder.CreateInsertValue(ZeroArray, NumThreads, {0});
9923
9924 // Arguments for the target kernel.
9925 SmallVector<llvm::Value *> KernelArgs{
9926 CGF.Builder.getInt32(/* Version */ 2),
9927 PointerNum,
9928 InputInfo.BasePointersArray.getPointer(),
9929 InputInfo.PointersArray.getPointer(),
9930 InputInfo.SizesArray.getPointer(),
9931 MapTypesArray,
9932 MapNamesArray,
9933 InputInfo.MappersArray.getPointer(),
9934 NumIterations,
9935 Flags,
9936 NumTeams3D,
9937 NumThreads3D,
9938 DynCGroupMem,
9939 };
9940
9941 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
9942 CGF.AllocaInsertPt->getParent(), CGF.AllocaInsertPt->getIterator());
9943
9944 // The target region is an outlined function launched by the runtime
9945 // via calls to __tgt_target_kernel().
9946 //
9947 // Note that on the host and CPU targets, the runtime implementation of
9948 // these calls simply call the outlined function without forking threads.
9949 // The outlined functions themselves have runtime calls to
9950 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9951 // the compiler in emitTeamsCall() and emitParallelCall().
9952 //
9953 // In contrast, on the NVPTX target, the implementation of
9954 // __tgt_target_teams() launches a GPU kernel with the requested number
9955 // of teams and threads so no additional calls to the runtime are required.
9956 // Check the error code and execute the host version if required.
9957 CGF.Builder.restoreIP(OMPBuilder.emitTargetKernel(
9958 CGF.Builder, AllocaIP, Return, RTLoc, DeviceID, NumTeams, NumThreads,
9959 OutlinedFnID, KernelArgs));
9960
9961 llvm::BasicBlock *OffloadFailedBlock =
9962 CGF.createBasicBlock("omp_offload.failed");
9963 llvm::BasicBlock *OffloadContBlock =
9964 CGF.createBasicBlock("omp_offload.cont");
9965 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9966 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9967
9968 CGF.EmitBlock(OffloadFailedBlock);
9969 FallbackGen(CGF);
9970
9971 CGF.EmitBranch(OffloadContBlock);
9972
9973 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
9974 };
9975
9976 // Notify that the host version must be executed.
9977 auto &&ElseGen = [FallbackGen](CodeGenFunction &CGF, PrePostActionTy &) {
9978 FallbackGen(CGF);
9979 };
9980
9981 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9982 &MapNamesArray, &CapturedVars, RequiresOuterTask,
9983 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9984 // Fill up the arrays with all the captured variables.
9985 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
9986
9987 // Get mappable expression information.
9988 MappableExprsHandler MEHandler(D, CGF);
9989 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
9990 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
9991
9992 auto RI = CS.getCapturedRecordDecl()->field_begin();
9993 auto *CV = CapturedVars.begin();
9994 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9995 CE = CS.capture_end();
9996 CI != CE; ++CI, ++RI, ++CV) {
9997 MappableExprsHandler::MapCombinedInfoTy CurInfo;
9998 MappableExprsHandler::StructRangeInfoTy PartialStruct;
9999
10000 // VLA sizes are passed to the outlined region by copy and do not have map
10001 // information associated.
10002 if (CI->capturesVariableArrayType()) {
10003 CurInfo.Exprs.push_back(nullptr);
10004 CurInfo.BasePointers.push_back(*CV);
10005 CurInfo.DevicePtrDecls.push_back(nullptr);
10006 CurInfo.Pointers.push_back(*CV);
10007 CurInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
10008 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
10009 // Copy to the device as an argument. No need to retrieve it.
10010 CurInfo.Types.push_back(
10011 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10012 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10013 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10014 CurInfo.Mappers.push_back(nullptr);
10015 } else {
10016 // If we have any information in the map clause, we use it, otherwise we
10017 // just do a default mapping.
10018 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct);
10019 if (!CI->capturesThis())
10020 MappedVarSet.insert(CI->getCapturedVar());
10021 else
10022 MappedVarSet.insert(nullptr);
10023 if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid())
10024 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10025 // Generate correct mapping for variables captured by reference in
10026 // lambdas.
10027 if (CI->capturesVariable())
10028 MEHandler.generateInfoForLambdaCaptures(CI->getCapturedVar(), *CV,
10029 CurInfo, LambdaPointers);
10030 }
10031 // We expect to have at least an element of information for this capture.
10032 assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) &&(static_cast <bool> ((!CurInfo.BasePointers.empty() || PartialStruct
.Base.isValid()) && "Non-existing map pointer for capture!"
) ? void (0) : __assert_fail ("(!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) && \"Non-existing map pointer for capture!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10033, __extension__
__PRETTY_FUNCTION__))
10033 "Non-existing map pointer for capture!")(static_cast <bool> ((!CurInfo.BasePointers.empty() || PartialStruct
.Base.isValid()) && "Non-existing map pointer for capture!"
) ? void (0) : __assert_fail ("(!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) && \"Non-existing map pointer for capture!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10033, __extension__
__PRETTY_FUNCTION__))
;
10034 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&(static_cast <bool> (CurInfo.BasePointers.size() == CurInfo
.Pointers.size() && CurInfo.BasePointers.size() == CurInfo
.Sizes.size() && CurInfo.BasePointers.size() == CurInfo
.Types.size() && CurInfo.BasePointers.size() == CurInfo
.Mappers.size() && "Inconsistent map information sizes!"
) ? void (0) : __assert_fail ("CurInfo.BasePointers.size() == CurInfo.Pointers.size() && CurInfo.BasePointers.size() == CurInfo.Sizes.size() && CurInfo.BasePointers.size() == CurInfo.Types.size() && CurInfo.BasePointers.size() == CurInfo.Mappers.size() && \"Inconsistent map information sizes!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10038, __extension__
__PRETTY_FUNCTION__))
10035 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&(static_cast <bool> (CurInfo.BasePointers.size() == CurInfo
.Pointers.size() && CurInfo.BasePointers.size() == CurInfo
.Sizes.size() && CurInfo.BasePointers.size() == CurInfo
.Types.size() && CurInfo.BasePointers.size() == CurInfo
.Mappers.size() && "Inconsistent map information sizes!"
) ? void (0) : __assert_fail ("CurInfo.BasePointers.size() == CurInfo.Pointers.size() && CurInfo.BasePointers.size() == CurInfo.Sizes.size() && CurInfo.BasePointers.size() == CurInfo.Types.size() && CurInfo.BasePointers.size() == CurInfo.Mappers.size() && \"Inconsistent map information sizes!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10038, __extension__
__PRETTY_FUNCTION__))
10036 CurInfo.BasePointers.size() == CurInfo.Types.size() &&(static_cast <bool> (CurInfo.BasePointers.size() == CurInfo
.Pointers.size() && CurInfo.BasePointers.size() == CurInfo
.Sizes.size() && CurInfo.BasePointers.size() == CurInfo
.Types.size() && CurInfo.BasePointers.size() == CurInfo
.Mappers.size() && "Inconsistent map information sizes!"
) ? void (0) : __assert_fail ("CurInfo.BasePointers.size() == CurInfo.Pointers.size() && CurInfo.BasePointers.size() == CurInfo.Sizes.size() && CurInfo.BasePointers.size() == CurInfo.Types.size() && CurInfo.BasePointers.size() == CurInfo.Mappers.size() && \"Inconsistent map information sizes!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10038, __extension__
__PRETTY_FUNCTION__))
10037 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&(static_cast <bool> (CurInfo.BasePointers.size() == CurInfo
.Pointers.size() && CurInfo.BasePointers.size() == CurInfo
.Sizes.size() && CurInfo.BasePointers.size() == CurInfo
.Types.size() && CurInfo.BasePointers.size() == CurInfo
.Mappers.size() && "Inconsistent map information sizes!"
) ? void (0) : __assert_fail ("CurInfo.BasePointers.size() == CurInfo.Pointers.size() && CurInfo.BasePointers.size() == CurInfo.Sizes.size() && CurInfo.BasePointers.size() == CurInfo.Types.size() && CurInfo.BasePointers.size() == CurInfo.Mappers.size() && \"Inconsistent map information sizes!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10038, __extension__
__PRETTY_FUNCTION__))
10038 "Inconsistent map information sizes!")(static_cast <bool> (CurInfo.BasePointers.size() == CurInfo
.Pointers.size() && CurInfo.BasePointers.size() == CurInfo
.Sizes.size() && CurInfo.BasePointers.size() == CurInfo
.Types.size() && CurInfo.BasePointers.size() == CurInfo
.Mappers.size() && "Inconsistent map information sizes!"
) ? void (0) : __assert_fail ("CurInfo.BasePointers.size() == CurInfo.Pointers.size() && CurInfo.BasePointers.size() == CurInfo.Sizes.size() && CurInfo.BasePointers.size() == CurInfo.Types.size() && CurInfo.BasePointers.size() == CurInfo.Mappers.size() && \"Inconsistent map information sizes!\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10038, __extension__
__PRETTY_FUNCTION__))
;
10039
10040 // If there is an entry in PartialStruct it means we have a struct with
10041 // individual members mapped. Emit an extra combined entry.
10042 if (PartialStruct.Base.isValid()) {
10043 CombinedInfo.append(PartialStruct.PreliminaryMapData);
10044 MEHandler.emitCombinedEntry(
10045 CombinedInfo, CurInfo.Types, PartialStruct, CI->capturesThis(),
10046 nullptr, !PartialStruct.PreliminaryMapData.BasePointers.empty());
10047 }
10048
10049 // We need to append the results of this capture to what we already have.
10050 CombinedInfo.append(CurInfo);
10051 }
10052 // Adjust MEMBER_OF flags for the lambdas captures.
10053 MEHandler.adjustMemberOfForLambdaCaptures(
10054 LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers,
10055 CombinedInfo.Types);
10056 // Map any list items in a map clause that were not captures because they
10057 // weren't referenced within the construct.
10058 MEHandler.generateAllInfo(CombinedInfo, MappedVarSet);
10059
10060 CGOpenMPRuntime::TargetDataInfo Info;
10061 // Fill up the arrays and create the arguments.
10062 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder);
10063 bool EmitDebug = CGF.CGM.getCodeGenOpts().getDebugInfo() !=
10064 llvm::codegenoptions::NoDebugInfo;
10065 OMPBuilder.emitOffloadingArraysArgument(CGF.Builder, Info.RTArgs, Info,
10066 EmitDebug,
10067 /*ForEndCall=*/false);
10068
10069 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10070 InputInfo.BasePointersArray = Address(Info.RTArgs.BasePointersArray,
10071 CGF.VoidPtrTy, CGM.getPointerAlign());
10072 InputInfo.PointersArray = Address(Info.RTArgs.PointersArray, CGF.VoidPtrTy,
10073 CGM.getPointerAlign());
10074 InputInfo.SizesArray =
10075 Address(Info.RTArgs.SizesArray, CGF.Int64Ty, CGM.getPointerAlign());
10076 InputInfo.MappersArray =
10077 Address(Info.RTArgs.MappersArray, CGF.VoidPtrTy, CGM.getPointerAlign());
10078 MapTypesArray = Info.RTArgs.MapTypesArray;
10079 MapNamesArray = Info.RTArgs.MapNamesArray;
10080 if (RequiresOuterTask)
10081 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10082 else
10083 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
10084 };
10085
10086 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
10087 CodeGenFunction &CGF, PrePostActionTy &) {
10088 if (RequiresOuterTask) {
10089 CodeGenFunction::OMPTargetDataInfo InputInfo;
10090 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
10091 } else {
10092 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
10093 }
10094 };
10095
10096 // If we have a target function ID it means that we need to support
10097 // offloading, otherwise, just execute on the host. We need to execute on host
10098 // regardless of the conditional in the if clause if, e.g., the user do not
10099 // specify target triples.
10100 if (OutlinedFnID) {
10101 if (IfCond) {
10102 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
10103 } else {
10104 RegionCodeGenTy ThenRCG(TargetThenGen);
10105 ThenRCG(CGF);
10106 }
10107 } else {
10108 RegionCodeGenTy ElseRCG(TargetElseGen);
10109 ElseRCG(CGF);
10110 }
10111}
10112
10113void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
10114 StringRef ParentName) {
10115 if (!S)
10116 return;
10117
10118 // Codegen OMP target directives that offload compute to the device.
10119 bool RequiresDeviceCodegen =
10120 isa<OMPExecutableDirective>(S) &&
10121 isOpenMPTargetExecutionDirective(
10122 cast<OMPExecutableDirective>(S)->getDirectiveKind());
10123
10124 if (RequiresDeviceCodegen) {
10125 const auto &E = *cast<OMPExecutableDirective>(S);
10126 auto EntryInfo =
10127 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), ParentName);
10128
10129 // Is this a target region that should not be emitted as an entry point? If
10130 // so just signal we are done with this target region.
10131 if (!OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
10132 return;
10133
10134 switch (E.getDirectiveKind()) {
10135 case OMPD_target:
10136 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
10137 cast<OMPTargetDirective>(E));
10138 break;
10139 case OMPD_target_parallel:
10140 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
10141 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
10142 break;
10143 case OMPD_target_teams:
10144 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
10145 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
10146 break;
10147 case OMPD_target_teams_distribute:
10148 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
10149 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
10150 break;
10151 case OMPD_target_teams_distribute_simd:
10152 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
10153 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
10154 break;
10155 case OMPD_target_parallel_for:
10156 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
10157 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
10158 break;
10159 case OMPD_target_parallel_for_simd:
10160 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
10161 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
10162 break;
10163 case OMPD_target_simd:
10164 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
10165 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
10166 break;
10167 case OMPD_target_teams_distribute_parallel_for:
10168 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
10169 CGM, ParentName,
10170 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
10171 break;
10172 case OMPD_target_teams_distribute_parallel_for_simd:
10173 CodeGenFunction::
10174 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
10175 CGM, ParentName,
10176 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
10177 break;
10178 case OMPD_parallel:
10179 case OMPD_for:
10180 case OMPD_parallel_for:
10181 case OMPD_parallel_master:
10182 case OMPD_parallel_sections:
10183 case OMPD_for_simd:
10184 case OMPD_parallel_for_simd:
10185 case OMPD_cancel:
10186 case OMPD_cancellation_point:
10187 case OMPD_ordered:
10188 case OMPD_threadprivate:
10189 case OMPD_allocate:
10190 case OMPD_task:
10191 case OMPD_simd:
10192 case OMPD_tile:
10193 case OMPD_unroll:
10194 case OMPD_sections:
10195 case OMPD_section:
10196 case OMPD_single:
10197 case OMPD_master:
10198 case OMPD_critical:
10199 case OMPD_taskyield:
10200 case OMPD_barrier:
10201 case OMPD_taskwait:
10202 case OMPD_taskgroup:
10203 case OMPD_atomic:
10204 case OMPD_flush:
10205 case OMPD_depobj:
10206 case OMPD_scan:
10207 case OMPD_teams:
10208 case OMPD_target_data:
10209 case OMPD_target_exit_data:
10210 case OMPD_target_enter_data:
10211 case OMPD_distribute:
10212 case OMPD_distribute_simd:
10213 case OMPD_distribute_parallel_for:
10214 case OMPD_distribute_parallel_for_simd:
10215 case OMPD_teams_distribute:
10216 case OMPD_teams_distribute_simd:
10217 case OMPD_teams_distribute_parallel_for:
10218 case OMPD_teams_distribute_parallel_for_simd:
10219 case OMPD_target_update:
10220 case OMPD_declare_simd:
10221 case OMPD_declare_variant:
10222 case OMPD_begin_declare_variant:
10223 case OMPD_end_declare_variant:
10224 case OMPD_declare_target:
10225 case OMPD_end_declare_target:
10226 case OMPD_declare_reduction:
10227 case OMPD_declare_mapper:
10228 case OMPD_taskloop:
10229 case OMPD_taskloop_simd:
10230 case OMPD_master_taskloop:
10231 case OMPD_master_taskloop_simd:
10232 case OMPD_parallel_master_taskloop:
10233 case OMPD_parallel_master_taskloop_simd:
10234 case OMPD_requires:
10235 case OMPD_metadirective:
10236 case OMPD_unknown:
10237 default:
10238 llvm_unreachable("Unknown target directive for OpenMP device codegen.")::llvm::llvm_unreachable_internal("Unknown target directive for OpenMP device codegen."
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10238)
;
10239 }
10240 return;
10241 }
10242
10243 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
10244 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
10245 return;
10246
10247 scanForTargetRegionsFunctions(E->getRawStmt(), ParentName);
10248 return;
10249 }
10250
10251 // If this is a lambda function, look into its body.
10252 if (const auto *L = dyn_cast<LambdaExpr>(S))
10253 S = L->getBody();
10254
10255 // Keep looking for target regions recursively.
10256 for (const Stmt *II : S->children())
10257 scanForTargetRegionsFunctions(II, ParentName);
10258}
10259
10260static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice) {
10261 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
10262 OMPDeclareTargetDeclAttr::getDeviceType(VD);
10263 if (!DevTy)
10264 return false;
10265 // Do not emit device_type(nohost) functions for the host.
10266 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
10267 return true;
10268 // Do not emit device_type(host) functions for the device.
10269 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
10270 return true;
10271 return false;
10272}
10273
10274bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
10275 // If emitting code for the host, we do not process FD here. Instead we do
10276 // the normal code generation.
10277 if (!CGM.getLangOpts().OpenMPIsDevice) {
10278 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl()))
10279 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD),
10280 CGM.getLangOpts().OpenMPIsDevice))
10281 return true;
10282 return false;
10283 }
10284
10285 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
10286 // Try to detect target regions in the function.
10287 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
10288 StringRef Name = CGM.getMangledName(GD);
10289 scanForTargetRegionsFunctions(FD->getBody(), Name);
10290 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD),
10291 CGM.getLangOpts().OpenMPIsDevice))
10292 return true;
10293 }
10294
10295 // Do not to emit function if it is not marked as declare target.
10296 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
10297 AlreadyEmittedTargetDecls.count(VD) == 0;
10298}
10299
10300bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
10301 if (isAssumedToBeNotEmitted(cast<ValueDecl>(GD.getDecl()),
10302 CGM.getLangOpts().OpenMPIsDevice))
10303 return true;
10304
10305 if (!CGM.getLangOpts().OpenMPIsDevice)
10306 return false;
10307
10308 // Check if there are Ctors/Dtors in this declaration and look for target
10309 // regions in it. We use the complete variant to produce the kernel name
10310 // mangling.
10311 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
10312 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
10313 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
10314 StringRef ParentName =
10315 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
10316 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
10317 }
10318 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
10319 StringRef ParentName =
10320 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
10321 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
10322 }
10323 }
10324
10325 // Do not to emit variable if it is not marked as declare target.
10326 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10327 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
10328 cast<VarDecl>(GD.getDecl()));
10329 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
10330 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10331 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10332 HasRequiresUnifiedSharedMemory)) {
10333 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
10334 return true;
10335 }
10336 return false;
10337}
10338
10339void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
10340 llvm::Constant *Addr) {
10341 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
10342 !CGM.getLangOpts().OpenMPIsDevice)
10343 return;
10344
10345 // If we have host/nohost variables, they do not need to be registered.
10346 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
10347 OMPDeclareTargetDeclAttr::getDeviceType(VD);
10348 if (DevTy && *DevTy != OMPDeclareTargetDeclAttr::DT_Any)
10349 return;
10350
10351 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10352 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10353 if (!Res) {
10354 if (CGM.getLangOpts().OpenMPIsDevice) {
10355 // Register non-target variables being emitted in device code (debug info
10356 // may cause this).
10357 StringRef VarName = CGM.getMangledName(VD);
10358 EmittedNonTargetVariables.try_emplace(VarName, Addr);
10359 }
10360 return;
10361 }
10362 // Register declare target variables.
10363 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind Flags;
10364 StringRef VarName;
10365 int64_t VarSize;
10366 llvm::GlobalValue::LinkageTypes Linkage;
10367
10368 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10369 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10370 !HasRequiresUnifiedSharedMemory) {
10371 Flags = llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
10372 VarName = CGM.getMangledName(VD);
10373 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
10374 VarSize =
10375 CGM.getContext().getTypeSizeInChars(VD->getType()).getQuantity();
10376 assert(VarSize != 0 && "Expected non-zero size of the variable")(static_cast <bool> (VarSize != 0 && "Expected non-zero size of the variable"
) ? void (0) : __assert_fail ("VarSize != 0 && \"Expected non-zero size of the variable\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10376, __extension__
__PRETTY_FUNCTION__))
;
10377 } else {
10378 VarSize = 0;
10379 }
10380 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
10381 // Temp solution to prevent optimizations of the internal variables.
10382 if (CGM.getLangOpts().OpenMPIsDevice &&
10383 (!VD->isExternallyVisible() ||
10384 Linkage == llvm::GlobalValue::LinkOnceODRLinkage)) {
10385 // Do not create a "ref-variable" if the original is not also available
10386 // on the host.
10387 if (!OMPBuilder.OffloadInfoManager.hasDeviceGlobalVarEntryInfo(VarName))
10388 return;
10389 std::string RefName = getName({VarName, "ref"});
10390 if (!CGM.GetGlobalValue(RefName)) {
10391 llvm::Constant *AddrRef =
10392 OMPBuilder.getOrCreateInternalVariable(Addr->getType(), RefName);
10393 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
10394 GVAddrRef->setConstant(/*Val=*/true);
10395 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
10396 GVAddrRef->setInitializer(Addr);
10397 CGM.addCompilerUsedGlobal(GVAddrRef);
10398 }
10399 }
10400 } else {
10401 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||(static_cast <bool> (((*Res == OMPDeclareTargetDeclAttr
::MT_Link) || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res
== OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory
)) && "Declare target attribute must link or to with unified memory."
) ? void (0) : __assert_fail ("((*Res == OMPDeclareTargetDeclAttr::MT_Link) || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && \"Declare target attribute must link or to with unified memory.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10405, __extension__
__PRETTY_FUNCTION__))
10402 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||(static_cast <bool> (((*Res == OMPDeclareTargetDeclAttr
::MT_Link) || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res
== OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory
)) && "Declare target attribute must link or to with unified memory."
) ? void (0) : __assert_fail ("((*Res == OMPDeclareTargetDeclAttr::MT_Link) || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && \"Declare target attribute must link or to with unified memory.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10405, __extension__
__PRETTY_FUNCTION__))
10403 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&(static_cast <bool> (((*Res == OMPDeclareTargetDeclAttr
::MT_Link) || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res
== OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory
)) && "Declare target attribute must link or to with unified memory."
) ? void (0) : __assert_fail ("((*Res == OMPDeclareTargetDeclAttr::MT_Link) || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && \"Declare target attribute must link or to with unified memory.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10405, __extension__
__PRETTY_FUNCTION__))
10404 HasRequiresUnifiedSharedMemory)) &&(static_cast <bool> (((*Res == OMPDeclareTargetDeclAttr
::MT_Link) || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res
== OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory
)) && "Declare target attribute must link or to with unified memory."
) ? void (0) : __assert_fail ("((*Res == OMPDeclareTargetDeclAttr::MT_Link) || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && \"Declare target attribute must link or to with unified memory.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10405, __extension__
__PRETTY_FUNCTION__))
10405 "Declare target attribute must link or to with unified memory.")(static_cast <bool> (((*Res == OMPDeclareTargetDeclAttr
::MT_Link) || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res
== OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory
)) && "Declare target attribute must link or to with unified memory."
) ? void (0) : __assert_fail ("((*Res == OMPDeclareTargetDeclAttr::MT_Link) || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && \"Declare target attribute must link or to with unified memory.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10405, __extension__
__PRETTY_FUNCTION__))
;
10406 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
10407 Flags = llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
10408 else
10409 Flags = llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
10410
10411 if (CGM.getLangOpts().OpenMPIsDevice) {
10412 VarName = Addr->getName();
10413 Addr = nullptr;
10414 } else {
10415 VarName = getAddrOfDeclareTargetVar(VD).getName();
10416 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
10417 }
10418 VarSize = CGM.getPointerSize().getQuantity();
10419 Linkage = llvm::GlobalValue::WeakAnyLinkage;
10420 }
10421
10422 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
10423 VarName, Addr, VarSize, Flags, Linkage);
10424}
10425
10426bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
10427 if (isa<FunctionDecl>(GD.getDecl()) ||
10428 isa<OMPDeclareReductionDecl>(GD.getDecl()))
10429 return emitTargetFunctions(GD);
10430
10431 return emitTargetGlobalVariable(GD);
10432}
10433
10434void CGOpenMPRuntime::emitDeferredTargetDecls() const {
10435 for (const VarDecl *VD : DeferredGlobalVariables) {
10436 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10437 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10438 if (!Res)
10439 continue;
10440 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10441 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10442 !HasRequiresUnifiedSharedMemory) {
10443 CGM.EmitGlobal(VD);
10444 } else {
10445 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||(static_cast <bool> ((*Res == OMPDeclareTargetDeclAttr::
MT_Link || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res ==
OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory
)) && "Expected link clause or to clause with unified memory."
) ? void (0) : __assert_fail ("(*Res == OMPDeclareTargetDeclAttr::MT_Link || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && \"Expected link clause or to clause with unified memory.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10449, __extension__
__PRETTY_FUNCTION__))
10446 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||(static_cast <bool> ((*Res == OMPDeclareTargetDeclAttr::
MT_Link || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res ==
OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory
)) && "Expected link clause or to clause with unified memory."
) ? void (0) : __assert_fail ("(*Res == OMPDeclareTargetDeclAttr::MT_Link || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && \"Expected link clause or to clause with unified memory.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10449, __extension__
__PRETTY_FUNCTION__))
10447 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&(static_cast <bool> ((*Res == OMPDeclareTargetDeclAttr::
MT_Link || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res ==
OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory
)) && "Expected link clause or to clause with unified memory."
) ? void (0) : __assert_fail ("(*Res == OMPDeclareTargetDeclAttr::MT_Link || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && \"Expected link clause or to clause with unified memory.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10449, __extension__
__PRETTY_FUNCTION__))
10448 HasRequiresUnifiedSharedMemory)) &&(static_cast <bool> ((*Res == OMPDeclareTargetDeclAttr::
MT_Link || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res ==
OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory
)) && "Expected link clause or to clause with unified memory."
) ? void (0) : __assert_fail ("(*Res == OMPDeclareTargetDeclAttr::MT_Link || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && \"Expected link clause or to clause with unified memory.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10449, __extension__
__PRETTY_FUNCTION__))
10449 "Expected link clause or to clause with unified memory.")(static_cast <bool> ((*Res == OMPDeclareTargetDeclAttr::
MT_Link || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res ==
OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory
)) && "Expected link clause or to clause with unified memory."
) ? void (0) : __assert_fail ("(*Res == OMPDeclareTargetDeclAttr::MT_Link || ((*Res == OMPDeclareTargetDeclAttr::MT_To || *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && \"Expected link clause or to clause with unified memory.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10449, __extension__
__PRETTY_FUNCTION__))
;
10450 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
10451 }
10452 }
10453}
10454
10455void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
10456 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
10457 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&(static_cast <bool> (isOpenMPTargetExecutionDirective(D
.getDirectiveKind()) && " Expected target-based directive."
) ? void (0) : __assert_fail ("isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && \" Expected target-based directive.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10458, __extension__
__PRETTY_FUNCTION__))
10458 " Expected target-based directive.")(static_cast <bool> (isOpenMPTargetExecutionDirective(D
.getDirectiveKind()) && " Expected target-based directive."
) ? void (0) : __assert_fail ("isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && \" Expected target-based directive.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10458, __extension__
__PRETTY_FUNCTION__))
;
10459}
10460
10461void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) {
10462 for (const OMPClause *Clause : D->clauselists()) {
10463 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
10464 HasRequiresUnifiedSharedMemory = true;
10465 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(true);
10466 } else if (const auto *AC =
10467 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
10468 switch (AC->getAtomicDefaultMemOrderKind()) {
10469 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
10470 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease;
10471 break;
10472 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
10473 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent;
10474 break;
10475 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
10476 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic;
10477 break;
10478 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown:
10479 break;
10480 }
10481 }
10482 }
10483}
10484
10485llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const {
10486 return RequiresAtomicOrdering;
10487}
10488
10489bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
10490 LangAS &AS) {
10491 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
10492 return false;
10493 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
10494 switch(A->getAllocatorType()) {
10495 case OMPAllocateDeclAttr::OMPNullMemAlloc:
10496 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
10497 // Not supported, fallback to the default mem space.
10498 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
10499 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
10500 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
10501 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
10502 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
10503 case OMPAllocateDeclAttr::OMPConstMemAlloc:
10504 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
10505 AS = LangAS::Default;
10506 return true;
10507 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
10508 llvm_unreachable("Expected predefined allocator for the variables with the "::llvm::llvm_unreachable_internal("Expected predefined allocator for the variables with the "
"static storage.", "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10509
)
10509 "static storage.")::llvm::llvm_unreachable_internal("Expected predefined allocator for the variables with the "
"static storage.", "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10509
)
;
10510 }
10511 return false;
10512}
10513
10514bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
10515 return HasRequiresUnifiedSharedMemory;
10516}
10517
10518CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
10519 CodeGenModule &CGM)
10520 : CGM(CGM) {
10521 if (CGM.getLangOpts().OpenMPIsDevice) {
10522 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
10523 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
10524 }
10525}
10526
10527CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
10528 if (CGM.getLangOpts().OpenMPIsDevice)
10529 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
10530}
10531
10532bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
10533 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
10534 return true;
10535
10536 const auto *D = cast<FunctionDecl>(GD.getDecl());
10537 // Do not to emit function if it is marked as declare target as it was already
10538 // emitted.
10539 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
10540 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) {
10541 if (auto *F = dyn_cast_or_null<llvm::Function>(
10542 CGM.GetGlobalValue(CGM.getMangledName(GD))))
10543 return !F->isDeclaration();
10544 return false;
10545 }
10546 return true;
10547 }
10548
10549 return !AlreadyEmittedTargetDecls.insert(D).second;
10550}
10551
10552llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
10553 // If we don't have entries or if we are emitting code for the device, we
10554 // don't need to do anything.
10555 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
10556 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
10557 (OMPBuilder.OffloadInfoManager.empty() &&
10558 !HasEmittedDeclareTargetRegion && !HasEmittedTargetRegion))
10559 return nullptr;
10560
10561 // Create and register the function that handles the requires directives.
10562 ASTContext &C = CGM.getContext();
10563
10564 llvm::Function *RequiresRegFn;
10565 {
10566 CodeGenFunction CGF(CGM);
10567 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
10568 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
10569 std::string ReqName = getName({"omp_offloading", "requires_reg"});
10570 RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI);
10571 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
10572 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
10573 // TODO: check for other requires clauses.
10574 // The requires directive takes effect only when a target region is
10575 // present in the compilation unit. Otherwise it is ignored and not
10576 // passed to the runtime. This avoids the runtime from throwing an error
10577 // for mismatching requires clauses across compilation units that don't
10578 // contain at least 1 target region.
10579 assert((HasEmittedTargetRegion || HasEmittedDeclareTargetRegion ||(static_cast <bool> ((HasEmittedTargetRegion || HasEmittedDeclareTargetRegion
|| !OMPBuilder.OffloadInfoManager.empty()) && "Target or declare target region expected."
) ? void (0) : __assert_fail ("(HasEmittedTargetRegion || HasEmittedDeclareTargetRegion || !OMPBuilder.OffloadInfoManager.empty()) && \"Target or declare target region expected.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10581, __extension__
__PRETTY_FUNCTION__))
10580 !OMPBuilder.OffloadInfoManager.empty()) &&(static_cast <bool> ((HasEmittedTargetRegion || HasEmittedDeclareTargetRegion
|| !OMPBuilder.OffloadInfoManager.empty()) && "Target or declare target region expected."
) ? void (0) : __assert_fail ("(HasEmittedTargetRegion || HasEmittedDeclareTargetRegion || !OMPBuilder.OffloadInfoManager.empty()) && \"Target or declare target region expected.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10581, __extension__
__PRETTY_FUNCTION__))
10581 "Target or declare target region expected.")(static_cast <bool> ((HasEmittedTargetRegion || HasEmittedDeclareTargetRegion
|| !OMPBuilder.OffloadInfoManager.empty()) && "Target or declare target region expected."
) ? void (0) : __assert_fail ("(HasEmittedTargetRegion || HasEmittedDeclareTargetRegion || !OMPBuilder.OffloadInfoManager.empty()) && \"Target or declare target region expected.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10581, __extension__
__PRETTY_FUNCTION__))
;
10582 if (HasRequiresUnifiedSharedMemory)
10583 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
10584 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
10585 CGM.getModule(), OMPRTL___tgt_register_requires),
10586 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
10587 CGF.FinishFunction();
10588 }
10589 return RequiresRegFn;
10590}
10591
10592void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
10593 const OMPExecutableDirective &D,
10594 SourceLocation Loc,
10595 llvm::Function *OutlinedFn,
10596 ArrayRef<llvm::Value *> CapturedVars) {
10597 if (!CGF.HaveInsertPoint())
10598 return;
10599
10600 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
10601 CodeGenFunction::RunCleanupsScope Scope(CGF);
10602
10603 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
10604 llvm::Value *Args[] = {
10605 RTLoc,
10606 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
10607 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
10608 llvm::SmallVector<llvm::Value *, 16> RealArgs;
10609 RealArgs.append(std::begin(Args), std::end(Args));
10610 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
10611
10612 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction(
10613 CGM.getModule(), OMPRTL___kmpc_fork_teams);
10614 CGF.EmitRuntimeCall(RTLFn, RealArgs);
10615}
10616
10617void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
10618 const Expr *NumTeams,
10619 const Expr *ThreadLimit,
10620 SourceLocation Loc) {
10621 if (!CGF.HaveInsertPoint())
10622 return;
10623
10624 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
10625
10626 llvm::Value *NumTeamsVal =
10627 NumTeams
10628 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
10629 CGF.CGM.Int32Ty, /* isSigned = */ true)
10630 : CGF.Builder.getInt32(0);
10631
10632 llvm::Value *ThreadLimitVal =
10633 ThreadLimit
10634 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
10635 CGF.CGM.Int32Ty, /* isSigned = */ true)
10636 : CGF.Builder.getInt32(0);
10637
10638 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
10639 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
10640 ThreadLimitVal};
10641 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
10642 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
10643 PushNumTeamsArgs);
10644}
10645
10646void CGOpenMPRuntime::emitTargetDataCalls(
10647 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10648 const Expr *Device, const RegionCodeGenTy &CodeGen,
10649 CGOpenMPRuntime::TargetDataInfo &Info) {
10650 if (!CGF.HaveInsertPoint())
10651 return;
10652
10653 // Action used to replace the default codegen action and turn privatization
10654 // off.
10655 PrePostActionTy NoPrivAction;
10656
10657 // Generate the code for the opening of the data environment. Capture all the
10658 // arguments of the runtime call by reference because they are used in the
10659 // closing of the region.
10660 auto &&BeginThenGen = [this, &D, Device, &Info,
10661 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
10662 // Fill up the arrays with all the mapped variables.
10663 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10664
10665 // Get map clause information.
10666 MappableExprsHandler MEHandler(D, CGF);
10667 MEHandler.generateAllInfo(CombinedInfo);
10668
10669 // Fill up the arrays and create the arguments.
10670 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder,
10671 /*IsNonContiguous=*/true);
10672
10673 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs;
10674 bool EmitDebug = CGF.CGM.getCodeGenOpts().getDebugInfo() !=
10675 llvm::codegenoptions::NoDebugInfo;
10676 OMPBuilder.emitOffloadingArraysArgument(CGF.Builder, RTArgs, Info,
10677 EmitDebug);
10678
10679 // Emit device ID if any.
10680 llvm::Value *DeviceID = nullptr;
10681 if (Device) {
10682 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10683 CGF.Int64Ty, /*isSigned=*/true);
10684 } else {
10685 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10686 }
10687
10688 // Emit the number of elements in the offloading arrays.
10689 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
10690 //
10691 // Source location for the ident struct
10692 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
10693
10694 llvm::Value *OffloadingArgs[] = {RTLoc,
10695 DeviceID,
10696 PointerNum,
10697 RTArgs.BasePointersArray,
10698 RTArgs.PointersArray,
10699 RTArgs.SizesArray,
10700 RTArgs.MapTypesArray,
10701 RTArgs.MapNamesArray,
10702 RTArgs.MappersArray};
10703 CGF.EmitRuntimeCall(
10704 OMPBuilder.getOrCreateRuntimeFunction(
10705 CGM.getModule(), OMPRTL___tgt_target_data_begin_mapper),
10706 OffloadingArgs);
10707
10708 // If device pointer privatization is required, emit the body of the region
10709 // here. It will have to be duplicated: with and without privatization.
10710 if (!Info.CaptureDeviceAddrMap.empty())
10711 CodeGen(CGF);
10712 };
10713
10714 // Generate code for the closing of the data region.
10715 auto &&EndThenGen = [this, Device, &Info, &D](CodeGenFunction &CGF,
10716 PrePostActionTy &) {
10717 assert(Info.isValid() && "Invalid data environment closing arguments.")(static_cast <bool> (Info.isValid() && "Invalid data environment closing arguments."
) ? void (0) : __assert_fail ("Info.isValid() && \"Invalid data environment closing arguments.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10717, __extension__
__PRETTY_FUNCTION__))
;
10718
10719 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs;
10720 bool EmitDebug = CGF.CGM.getCodeGenOpts().getDebugInfo() !=
10721 llvm::codegenoptions::NoDebugInfo;
10722 OMPBuilder.emitOffloadingArraysArgument(CGF.Builder, RTArgs, Info,
10723 EmitDebug,
10724 /*ForEndCall=*/true);
10725
10726 // Emit device ID if any.
10727 llvm::Value *DeviceID = nullptr;
10728 if (Device) {
10729 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10730 CGF.Int64Ty, /*isSigned=*/true);
10731 } else {
10732 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10733 }
10734
10735 // Emit the number of elements in the offloading arrays.
10736 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
10737
10738 // Source location for the ident struct
10739 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
10740
10741 llvm::Value *OffloadingArgs[] = {RTLoc,
10742 DeviceID,
10743 PointerNum,
10744 RTArgs.BasePointersArray,
10745 RTArgs.PointersArray,
10746 RTArgs.SizesArray,
10747 RTArgs.MapTypesArray,
10748 RTArgs.MapNamesArray,
10749 RTArgs.MappersArray};
10750 CGF.EmitRuntimeCall(
10751 OMPBuilder.getOrCreateRuntimeFunction(
10752 CGM.getModule(), OMPRTL___tgt_target_data_end_mapper),
10753 OffloadingArgs);
10754 };
10755
10756 // If we need device pointer privatization, we need to emit the body of the
10757 // region with no privatization in the 'else' branch of the conditional.
10758 // Otherwise, we don't have to do anything.
10759 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10760 PrePostActionTy &) {
10761 if (!Info.CaptureDeviceAddrMap.empty()) {
10762 CodeGen.setAction(NoPrivAction);
10763 CodeGen(CGF);
10764 }
10765 };
10766
10767 // We don't have to do anything to close the region if the if clause evaluates
10768 // to false.
10769 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
10770
10771 if (IfCond) {
10772 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
10773 } else {
10774 RegionCodeGenTy RCG(BeginThenGen);
10775 RCG(CGF);
10776 }
10777
10778 // If we don't require privatization of device pointers, we emit the body in
10779 // between the runtime calls. This avoids duplicating the body code.
10780 if (Info.CaptureDeviceAddrMap.empty()) {
10781 CodeGen.setAction(NoPrivAction);
10782 CodeGen(CGF);
10783 }
10784
10785 if (IfCond) {
10786 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen);
10787 } else {
10788 RegionCodeGenTy RCG(EndThenGen);
10789 RCG(CGF);
10790 }
10791}
10792
10793void CGOpenMPRuntime::emitTargetDataStandAloneCall(
10794 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10795 const Expr *Device) {
10796 if (!CGF.HaveInsertPoint())
10797 return;
10798
10799 assert((isa<OMPTargetEnterDataDirective>(D) ||(static_cast <bool> ((isa<OMPTargetEnterDataDirective
>(D) || isa<OMPTargetExitDataDirective>(D) || isa<
OMPTargetUpdateDirective>(D)) && "Expecting either target enter, exit data, or update directives."
) ? void (0) : __assert_fail ("(isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective>(D) || isa<OMPTargetUpdateDirective>(D)) && \"Expecting either target enter, exit data, or update directives.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10802, __extension__
__PRETTY_FUNCTION__))
10800 isa<OMPTargetExitDataDirective>(D) ||(static_cast <bool> ((isa<OMPTargetEnterDataDirective
>(D) || isa<OMPTargetExitDataDirective>(D) || isa<
OMPTargetUpdateDirective>(D)) && "Expecting either target enter, exit data, or update directives."
) ? void (0) : __assert_fail ("(isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective>(D) || isa<OMPTargetUpdateDirective>(D)) && \"Expecting either target enter, exit data, or update directives.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10802, __extension__
__PRETTY_FUNCTION__))
10801 isa<OMPTargetUpdateDirective>(D)) &&(static_cast <bool> ((isa<OMPTargetEnterDataDirective
>(D) || isa<OMPTargetExitDataDirective>(D) || isa<
OMPTargetUpdateDirective>(D)) && "Expecting either target enter, exit data, or update directives."
) ? void (0) : __assert_fail ("(isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective>(D) || isa<OMPTargetUpdateDirective>(D)) && \"Expecting either target enter, exit data, or update directives.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10802, __extension__
__PRETTY_FUNCTION__))
10802 "Expecting either target enter, exit data, or update directives.")(static_cast <bool> ((isa<OMPTargetEnterDataDirective
>(D) || isa<OMPTargetExitDataDirective>(D) || isa<
OMPTargetUpdateDirective>(D)) && "Expecting either target enter, exit data, or update directives."
) ? void (0) : __assert_fail ("(isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective>(D) || isa<OMPTargetUpdateDirective>(D)) && \"Expecting either target enter, exit data, or update directives.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10802, __extension__
__PRETTY_FUNCTION__))
;
10803
10804 CodeGenFunction::OMPTargetDataInfo InputInfo;
10805 llvm::Value *MapTypesArray = nullptr;
10806 llvm::Value *MapNamesArray = nullptr;
10807 // Generate the code for the opening of the data environment.
10808 auto &&ThenGen = [this, &D, Device, &InputInfo, &MapTypesArray,
10809 &MapNamesArray](CodeGenFunction &CGF, PrePostActionTy &) {
10810 // Emit device ID if any.
10811 llvm::Value *DeviceID = nullptr;
10812 if (Device) {
10813 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10814 CGF.Int64Ty, /*isSigned=*/true);
10815 } else {
10816 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10817 }
10818
10819 // Emit the number of elements in the offloading arrays.
10820 llvm::Constant *PointerNum =
10821 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
10822
10823 // Source location for the ident struct
10824 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
10825
10826 llvm::Value *OffloadingArgs[] = {RTLoc,
10827 DeviceID,
10828 PointerNum,
10829 InputInfo.BasePointersArray.getPointer(),
10830 InputInfo.PointersArray.getPointer(),
10831 InputInfo.SizesArray.getPointer(),
10832 MapTypesArray,
10833 MapNamesArray,
10834 InputInfo.MappersArray.getPointer()};
10835
10836 // Select the right runtime function call for each standalone
10837 // directive.
10838 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
10839 RuntimeFunction RTLFn;
10840 switch (D.getDirectiveKind()) {
10841 case OMPD_target_enter_data:
10842 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
10843 : OMPRTL___tgt_target_data_begin_mapper;
10844 break;
10845 case OMPD_target_exit_data:
10846 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
10847 : OMPRTL___tgt_target_data_end_mapper;
10848 break;
10849 case OMPD_target_update:
10850 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
10851 : OMPRTL___tgt_target_data_update_mapper;
10852 break;
10853 case OMPD_parallel:
10854 case OMPD_for:
10855 case OMPD_parallel_for:
10856 case OMPD_parallel_master:
10857 case OMPD_parallel_sections:
10858 case OMPD_for_simd:
10859 case OMPD_parallel_for_simd:
10860 case OMPD_cancel:
10861 case OMPD_cancellation_point:
10862 case OMPD_ordered:
10863 case OMPD_threadprivate:
10864 case OMPD_allocate:
10865 case OMPD_task:
10866 case OMPD_simd:
10867 case OMPD_tile:
10868 case OMPD_unroll:
10869 case OMPD_sections:
10870 case OMPD_section:
10871 case OMPD_single:
10872 case OMPD_master:
10873 case OMPD_critical:
10874 case OMPD_taskyield:
10875 case OMPD_barrier:
10876 case OMPD_taskwait:
10877 case OMPD_taskgroup:
10878 case OMPD_atomic:
10879 case OMPD_flush:
10880 case OMPD_depobj:
10881 case OMPD_scan:
10882 case OMPD_teams:
10883 case OMPD_target_data:
10884 case OMPD_distribute:
10885 case OMPD_distribute_simd:
10886 case OMPD_distribute_parallel_for:
10887 case OMPD_distribute_parallel_for_simd:
10888 case OMPD_teams_distribute:
10889 case OMPD_teams_distribute_simd:
10890 case OMPD_teams_distribute_parallel_for:
10891 case OMPD_teams_distribute_parallel_for_simd:
10892 case OMPD_declare_simd:
10893 case OMPD_declare_variant:
10894 case OMPD_begin_declare_variant:
10895 case OMPD_end_declare_variant:
10896 case OMPD_declare_target:
10897 case OMPD_end_declare_target:
10898 case OMPD_declare_reduction:
10899 case OMPD_declare_mapper:
10900 case OMPD_taskloop:
10901 case OMPD_taskloop_simd:
10902 case OMPD_master_taskloop:
10903 case OMPD_master_taskloop_simd:
10904 case OMPD_parallel_master_taskloop:
10905 case OMPD_parallel_master_taskloop_simd:
10906 case OMPD_target:
10907 case OMPD_target_simd:
10908 case OMPD_target_teams_distribute:
10909 case OMPD_target_teams_distribute_simd:
10910 case OMPD_target_teams_distribute_parallel_for:
10911 case OMPD_target_teams_distribute_parallel_for_simd:
10912 case OMPD_target_teams:
10913 case OMPD_target_parallel:
10914 case OMPD_target_parallel_for:
10915 case OMPD_target_parallel_for_simd:
10916 case OMPD_requires:
10917 case OMPD_metadirective:
10918 case OMPD_unknown:
10919 default:
10920 llvm_unreachable("Unexpected standalone target data directive.")::llvm::llvm_unreachable_internal("Unexpected standalone target data directive."
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 10920)
;
10921 break;
10922 }
10923 CGF.EmitRuntimeCall(
10924 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), RTLFn),
10925 OffloadingArgs);
10926 };
10927
10928 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
10929 &MapNamesArray](CodeGenFunction &CGF,
10930 PrePostActionTy &) {
10931 // Fill up the arrays with all the mapped variables.
10932 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10933
10934 // Get map clause information.
10935 MappableExprsHandler MEHandler(D, CGF);
10936 MEHandler.generateAllInfo(CombinedInfo);
10937
10938 CGOpenMPRuntime::TargetDataInfo Info;
10939 // Fill up the arrays and create the arguments.
10940 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder,
10941 /*IsNonContiguous=*/true);
10942 bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() ||
10943 D.hasClausesOfKind<OMPNowaitClause>();
10944 bool EmitDebug = CGF.CGM.getCodeGenOpts().getDebugInfo() !=
10945 llvm::codegenoptions::NoDebugInfo;
10946 OMPBuilder.emitOffloadingArraysArgument(CGF.Builder, Info.RTArgs, Info,
10947 EmitDebug,
10948 /*ForEndCall=*/false);
10949 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10950 InputInfo.BasePointersArray = Address(Info.RTArgs.BasePointersArray,
10951 CGF.VoidPtrTy, CGM.getPointerAlign());
10952 InputInfo.PointersArray = Address(Info.RTArgs.PointersArray, CGF.VoidPtrTy,
10953 CGM.getPointerAlign());
10954 InputInfo.SizesArray =
10955 Address(Info.RTArgs.SizesArray, CGF.Int64Ty, CGM.getPointerAlign());
10956 InputInfo.MappersArray =
10957 Address(Info.RTArgs.MappersArray, CGF.VoidPtrTy, CGM.getPointerAlign());
10958 MapTypesArray = Info.RTArgs.MapTypesArray;
10959 MapNamesArray = Info.RTArgs.MapNamesArray;
10960 if (RequiresOuterTask)
10961 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10962 else
10963 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
10964 };
10965
10966 if (IfCond) {
10967 emitIfClause(CGF, IfCond, TargetThenGen,
10968 [](CodeGenFunction &CGF, PrePostActionTy &) {});
10969 } else {
10970 RegionCodeGenTy ThenRCG(TargetThenGen);
10971 ThenRCG(CGF);
10972 }
10973}
10974
10975namespace {
10976 /// Kind of parameter in a function with 'declare simd' directive.
10977enum ParamKindTy {
10978 Linear,
10979 LinearRef,
10980 LinearUVal,
10981 LinearVal,
10982 Uniform,
10983 Vector,
10984};
10985/// Attribute set of the parameter.
10986struct ParamAttrTy {
10987 ParamKindTy Kind = Vector;
10988 llvm::APSInt StrideOrArg;
10989 llvm::APSInt Alignment;
10990 bool HasVarStride = false;
10991};
10992} // namespace
10993
10994static unsigned evaluateCDTSize(const FunctionDecl *FD,
10995 ArrayRef<ParamAttrTy> ParamAttrs) {
10996 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10997 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10998 // of that clause. The VLEN value must be power of 2.
10999 // In other case the notion of the function`s "characteristic data type" (CDT)
11000 // is used to compute the vector length.
11001 // CDT is defined in the following order:
11002 // a) For non-void function, the CDT is the return type.
11003 // b) If the function has any non-uniform, non-linear parameters, then the
11004 // CDT is the type of the first such parameter.
11005 // c) If the CDT determined by a) or b) above is struct, union, or class
11006 // type which is pass-by-value (except for the type that maps to the
11007 // built-in complex data type), the characteristic data type is int.
11008 // d) If none of the above three cases is applicable, the CDT is int.
11009 // The VLEN is then determined based on the CDT and the size of vector
11010 // register of that ISA for which current vector version is generated. The
11011 // VLEN is computed using the formula below:
11012 // VLEN = sizeof(vector_register) / sizeof(CDT),
11013 // where vector register size specified in section 3.2.1 Registers and the
11014 // Stack Frame of original AMD64 ABI document.
11015 QualType RetType = FD->getReturnType();
11016 if (RetType.isNull())
11017 return 0;
11018 ASTContext &C = FD->getASTContext();
11019 QualType CDT;
11020 if (!RetType.isNull() && !RetType->isVoidType()) {
11021 CDT = RetType;
11022 } else {
11023 unsigned Offset = 0;
11024 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11025 if (ParamAttrs[Offset].Kind == Vector)
11026 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
11027 ++Offset;
11028 }
11029 if (CDT.isNull()) {
11030 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
11031 if (ParamAttrs[I + Offset].Kind == Vector) {
11032 CDT = FD->getParamDecl(I)->getType();
11033 break;
11034 }
11035 }
11036 }
11037 }
11038 if (CDT.isNull())
11039 CDT = C.IntTy;
11040 CDT = CDT->getCanonicalTypeUnqualified();
11041 if (CDT->isRecordType() || CDT->isUnionType())
11042 CDT = C.IntTy;
11043 return C.getTypeSize(CDT);
11044}
11045
11046/// Mangle the parameter part of the vector function name according to
11047/// their OpenMP classification. The mangling function is defined in
11048/// section 4.5 of the AAVFABI(2021Q1).
11049static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
11050 SmallString<256> Buffer;
11051 llvm::raw_svector_ostream Out(Buffer);
11052 for (const auto &ParamAttr : ParamAttrs) {
11053 switch (ParamAttr.Kind) {
11054 case Linear:
11055 Out << 'l';
11056 break;
11057 case LinearRef:
11058 Out << 'R';
11059 break;
11060 case LinearUVal:
11061 Out << 'U';
11062 break;
11063 case LinearVal:
11064 Out << 'L';
11065 break;
11066 case Uniform:
11067 Out << 'u';
11068 break;
11069 case Vector:
11070 Out << 'v';
11071 break;
11072 }
11073 if (ParamAttr.HasVarStride)
11074 Out << "s" << ParamAttr.StrideOrArg;
11075 else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
11076 ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
11077 // Don't print the step value if it is not present or if it is
11078 // equal to 1.
11079 if (ParamAttr.StrideOrArg < 0)
11080 Out << 'n' << -ParamAttr.StrideOrArg;
11081 else if (ParamAttr.StrideOrArg != 1)
11082 Out << ParamAttr.StrideOrArg;
11083 }
11084
11085 if (!!ParamAttr.Alignment)
11086 Out << 'a' << ParamAttr.Alignment;
11087 }
11088
11089 return std::string(Out.str());
11090}
11091
11092static void
11093emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
11094 const llvm::APSInt &VLENVal,
11095 ArrayRef<ParamAttrTy> ParamAttrs,
11096 OMPDeclareSimdDeclAttr::BranchStateTy State) {
11097 struct ISADataTy {
11098 char ISA;
11099 unsigned VecRegSize;
11100 };
11101 ISADataTy ISAData[] = {
11102 {
11103 'b', 128
11104 }, // SSE
11105 {
11106 'c', 256
11107 }, // AVX
11108 {
11109 'd', 256
11110 }, // AVX2
11111 {
11112 'e', 512
11113 }, // AVX512
11114 };
11115 llvm::SmallVector<char, 2> Masked;
11116 switch (State) {
11117 case OMPDeclareSimdDeclAttr::BS_Undefined:
11118 Masked.push_back('N');
11119 Masked.push_back('M');
11120 break;
11121 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11122 Masked.push_back('N');
11123 break;
11124 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11125 Masked.push_back('M');
11126 break;
11127 }
11128 for (char Mask : Masked) {
11129 for (const ISADataTy &Data : ISAData) {
11130 SmallString<256> Buffer;
11131 llvm::raw_svector_ostream Out(Buffer);
11132 Out << "_ZGV" << Data.ISA << Mask;
11133 if (!VLENVal) {
11134 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
11135 assert(NumElts && "Non-zero simdlen/cdtsize expected")(static_cast <bool> (NumElts && "Non-zero simdlen/cdtsize expected"
) ? void (0) : __assert_fail ("NumElts && \"Non-zero simdlen/cdtsize expected\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11135, __extension__
__PRETTY_FUNCTION__))
;
11136 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
11137 } else {
11138 Out << VLENVal;
11139 }
11140 Out << mangleVectorParameters(ParamAttrs);
11141 Out << '_' << Fn->getName();
11142 Fn->addFnAttr(Out.str());
11143 }
11144 }
11145}
11146
11147// This are the Functions that are needed to mangle the name of the
11148// vector functions generated by the compiler, according to the rules
11149// defined in the "Vector Function ABI specifications for AArch64",
11150// available at
11151// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
11152
11153/// Maps To Vector (MTV), as defined in 4.1.1 of the AAVFABI (2021Q1).
11154static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
11155 QT = QT.getCanonicalType();
11156
11157 if (QT->isVoidType())
11158 return false;
11159
11160 if (Kind == ParamKindTy::Uniform)
11161 return false;
11162
11163 if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
11164 return false;
11165
11166 if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
11167 !QT->isReferenceType())
11168 return false;
11169
11170 return true;
11171}
11172
11173/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
11174static bool getAArch64PBV(QualType QT, ASTContext &C) {
11175 QT = QT.getCanonicalType();
11176 unsigned Size = C.getTypeSize(QT);
11177
11178 // Only scalars and complex within 16 bytes wide set PVB to true.
11179 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
11180 return false;
11181
11182 if (QT->isFloatingType())
11183 return true;
11184
11185 if (QT->isIntegerType())
11186 return true;
11187
11188 if (QT->isPointerType())
11189 return true;
11190
11191 // TODO: Add support for complex types (section 3.1.2, item 2).
11192
11193 return false;
11194}
11195
11196/// Computes the lane size (LS) of a return type or of an input parameter,
11197/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
11198/// TODO: Add support for references, section 3.2.1, item 1.
11199static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
11200 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
11201 QualType PTy = QT.getCanonicalType()->getPointeeType();
11202 if (getAArch64PBV(PTy, C))
11203 return C.getTypeSize(PTy);
11204 }
11205 if (getAArch64PBV(QT, C))
11206 return C.getTypeSize(QT);
11207
11208 return C.getTypeSize(C.getUIntPtrType());
11209}
11210
11211// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
11212// signature of the scalar function, as defined in 3.2.2 of the
11213// AAVFABI.
11214static std::tuple<unsigned, unsigned, bool>
11215getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
11216 QualType RetType = FD->getReturnType().getCanonicalType();
11217
11218 ASTContext &C = FD->getASTContext();
11219
11220 bool OutputBecomesInput = false;
11221
11222 llvm::SmallVector<unsigned, 8> Sizes;
11223 if (!RetType->isVoidType()) {
11224 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
11225 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
11226 OutputBecomesInput = true;
11227 }
11228 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
11229 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
11230 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
11231 }
11232
11233 assert(!Sizes.empty() && "Unable to determine NDS and WDS.")(static_cast <bool> (!Sizes.empty() && "Unable to determine NDS and WDS."
) ? void (0) : __assert_fail ("!Sizes.empty() && \"Unable to determine NDS and WDS.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11233, __extension__
__PRETTY_FUNCTION__))
;
11234 // The LS of a function parameter / return value can only be a power
11235 // of 2, starting from 8 bits, up to 128.
11236 assert(llvm::all_of(Sizes,(static_cast <bool> (llvm::all_of(Sizes, [](unsigned Size
) { return Size == 8 || Size == 16 || Size == 32 || Size == 64
|| Size == 128; }) && "Invalid size") ? void (0) : __assert_fail
("llvm::all_of(Sizes, [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11241, __extension__
__PRETTY_FUNCTION__))
11237 [](unsigned Size) {(static_cast <bool> (llvm::all_of(Sizes, [](unsigned Size
) { return Size == 8 || Size == 16 || Size == 32 || Size == 64
|| Size == 128; }) && "Invalid size") ? void (0) : __assert_fail
("llvm::all_of(Sizes, [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11241, __extension__
__PRETTY_FUNCTION__))
11238 return Size == 8 || Size == 16 || Size == 32 ||(static_cast <bool> (llvm::all_of(Sizes, [](unsigned Size
) { return Size == 8 || Size == 16 || Size == 32 || Size == 64
|| Size == 128; }) && "Invalid size") ? void (0) : __assert_fail
("llvm::all_of(Sizes, [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11241, __extension__
__PRETTY_FUNCTION__))
11239 Size == 64 || Size == 128;(static_cast <bool> (llvm::all_of(Sizes, [](unsigned Size
) { return Size == 8 || Size == 16 || Size == 32 || Size == 64
|| Size == 128; }) && "Invalid size") ? void (0) : __assert_fail
("llvm::all_of(Sizes, [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11241, __extension__
__PRETTY_FUNCTION__))
11240 }) &&(static_cast <bool> (llvm::all_of(Sizes, [](unsigned Size
) { return Size == 8 || Size == 16 || Size == 32 || Size == 64
|| Size == 128; }) && "Invalid size") ? void (0) : __assert_fail
("llvm::all_of(Sizes, [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11241, __extension__
__PRETTY_FUNCTION__))
11241 "Invalid size")(static_cast <bool> (llvm::all_of(Sizes, [](unsigned Size
) { return Size == 8 || Size == 16 || Size == 32 || Size == 64
|| Size == 128; }) && "Invalid size") ? void (0) : __assert_fail
("llvm::all_of(Sizes, [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11241, __extension__
__PRETTY_FUNCTION__))
;
11242
11243 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
11244 *std::max_element(std::begin(Sizes), std::end(Sizes)),
11245 OutputBecomesInput);
11246}
11247
11248// Function used to add the attribute. The parameter `VLEN` is
11249// templated to allow the use of "x" when targeting scalable functions
11250// for SVE.
11251template <typename T>
11252static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
11253 char ISA, StringRef ParSeq,
11254 StringRef MangledName, bool OutputBecomesInput,
11255 llvm::Function *Fn) {
11256 SmallString<256> Buffer;
11257 llvm::raw_svector_ostream Out(Buffer);
11258 Out << Prefix << ISA << LMask << VLEN;
11259 if (OutputBecomesInput)
11260 Out << "v";
11261 Out << ParSeq << "_" << MangledName;
11262 Fn->addFnAttr(Out.str());
11263}
11264
11265// Helper function to generate the Advanced SIMD names depending on
11266// the value of the NDS when simdlen is not present.
11267static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
11268 StringRef Prefix, char ISA,
11269 StringRef ParSeq, StringRef MangledName,
11270 bool OutputBecomesInput,
11271 llvm::Function *Fn) {
11272 switch (NDS) {
11273 case 8:
11274 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
11275 OutputBecomesInput, Fn);
11276 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
11277 OutputBecomesInput, Fn);
11278 break;
11279 case 16:
11280 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
11281 OutputBecomesInput, Fn);
11282 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
11283 OutputBecomesInput, Fn);
11284 break;
11285 case 32:
11286 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
11287 OutputBecomesInput, Fn);
11288 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
11289 OutputBecomesInput, Fn);
11290 break;
11291 case 64:
11292 case 128:
11293 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
11294 OutputBecomesInput, Fn);
11295 break;
11296 default:
11297 llvm_unreachable("Scalar type is too wide.")::llvm::llvm_unreachable_internal("Scalar type is too wide.",
"clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11297)
;
11298 }
11299}
11300
11301/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
11302static void emitAArch64DeclareSimdFunction(
11303 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
11304 ArrayRef<ParamAttrTy> ParamAttrs,
11305 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
11306 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
11307
11308 // Get basic data for building the vector signature.
11309 const auto Data = getNDSWDS(FD, ParamAttrs);
11310 const unsigned NDS = std::get<0>(Data);
11311 const unsigned WDS = std::get<1>(Data);
11312 const bool OutputBecomesInput = std::get<2>(Data);
11313
11314 // Check the values provided via `simdlen` by the user.
11315 // 1. A `simdlen(1)` doesn't produce vector signatures,
11316 if (UserVLEN == 1) {
11317 unsigned DiagID = CGM.getDiags().getCustomDiagID(
11318 DiagnosticsEngine::Warning,
11319 "The clause simdlen(1) has no effect when targeting aarch64.");
11320 CGM.getDiags().Report(SLoc, DiagID);
11321 return;
11322 }
11323
11324 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
11325 // Advanced SIMD output.
11326 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
11327 unsigned DiagID = CGM.getDiags().getCustomDiagID(
11328 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
11329 "power of 2 when targeting Advanced SIMD.");
11330 CGM.getDiags().Report(SLoc, DiagID);
11331 return;
11332 }
11333
11334 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
11335 // limits.
11336 if (ISA == 's' && UserVLEN != 0) {
11337 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
11338 unsigned DiagID = CGM.getDiags().getCustomDiagID(
11339 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
11340 "lanes in the architectural constraints "
11341 "for SVE (min is 128-bit, max is "
11342 "2048-bit, by steps of 128-bit)");
11343 CGM.getDiags().Report(SLoc, DiagID) << WDS;
11344 return;
11345 }
11346 }
11347
11348 // Sort out parameter sequence.
11349 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
11350 StringRef Prefix = "_ZGV";
11351 // Generate simdlen from user input (if any).
11352 if (UserVLEN) {
11353 if (ISA == 's') {
11354 // SVE generates only a masked function.
11355 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
11356 OutputBecomesInput, Fn);
11357 } else {
11358 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.")(static_cast <bool> (ISA == 'n' && "Expected ISA either 's' or 'n'."
) ? void (0) : __assert_fail ("ISA == 'n' && \"Expected ISA either 's' or 'n'.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11358, __extension__
__PRETTY_FUNCTION__))
;
11359 // Advanced SIMD generates one or two functions, depending on
11360 // the `[not]inbranch` clause.
11361 switch (State) {
11362 case OMPDeclareSimdDeclAttr::BS_Undefined:
11363 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
11364 OutputBecomesInput, Fn);
11365 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
11366 OutputBecomesInput, Fn);
11367 break;
11368 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11369 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
11370 OutputBecomesInput, Fn);
11371 break;
11372 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11373 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
11374 OutputBecomesInput, Fn);
11375 break;
11376 }
11377 }
11378 } else {
11379 // If no user simdlen is provided, follow the AAVFABI rules for
11380 // generating the vector length.
11381 if (ISA == 's') {
11382 // SVE, section 3.4.1, item 1.
11383 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
11384 OutputBecomesInput, Fn);
11385 } else {
11386 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.")(static_cast <bool> (ISA == 'n' && "Expected ISA either 's' or 'n'."
) ? void (0) : __assert_fail ("ISA == 'n' && \"Expected ISA either 's' or 'n'.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11386, __extension__
__PRETTY_FUNCTION__))
;
11387 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
11388 // two vector names depending on the use of the clause
11389 // `[not]inbranch`.
11390 switch (State) {
11391 case OMPDeclareSimdDeclAttr::BS_Undefined:
11392 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
11393 OutputBecomesInput, Fn);
11394 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
11395 OutputBecomesInput, Fn);
11396 break;
11397 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11398 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
11399 OutputBecomesInput, Fn);
11400 break;
11401 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11402 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
11403 OutputBecomesInput, Fn);
11404 break;
11405 }
11406 }
11407 }
11408}
11409
11410void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
11411 llvm::Function *Fn) {
11412 ASTContext &C = CGM.getContext();
11413 FD = FD->getMostRecentDecl();
11414 while (FD) {
11415 // Map params to their positions in function decl.
11416 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
11417 if (isa<CXXMethodDecl>(FD))
11418 ParamPositions.try_emplace(FD, 0);
11419 unsigned ParamPos = ParamPositions.size();
11420 for (const ParmVarDecl *P : FD->parameters()) {
11421 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
11422 ++ParamPos;
11423 }
11424 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
11425 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
11426 // Mark uniform parameters.
11427 for (const Expr *E : Attr->uniforms()) {
11428 E = E->IgnoreParenImpCasts();
11429 unsigned Pos;
11430 if (isa<CXXThisExpr>(E)) {
11431 Pos = ParamPositions[FD];
11432 } else {
11433 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
11434 ->getCanonicalDecl();
11435 auto It = ParamPositions.find(PVD);
11436 assert(It != ParamPositions.end() && "Function parameter not found")(static_cast <bool> (It != ParamPositions.end() &&
"Function parameter not found") ? void (0) : __assert_fail (
"It != ParamPositions.end() && \"Function parameter not found\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11436, __extension__
__PRETTY_FUNCTION__))
;
11437 Pos = It->second;
11438 }
11439 ParamAttrs[Pos].Kind = Uniform;
11440 }
11441 // Get alignment info.
11442 auto *NI = Attr->alignments_begin();
11443 for (const Expr *E : Attr->aligneds()) {
11444 E = E->IgnoreParenImpCasts();
11445 unsigned Pos;
11446 QualType ParmTy;
11447 if (isa<CXXThisExpr>(E)) {
11448 Pos = ParamPositions[FD];
11449 ParmTy = E->getType();
11450 } else {
11451 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
11452 ->getCanonicalDecl();
11453 auto It = ParamPositions.find(PVD);
11454 assert(It != ParamPositions.end() && "Function parameter not found")(static_cast <bool> (It != ParamPositions.end() &&
"Function parameter not found") ? void (0) : __assert_fail (
"It != ParamPositions.end() && \"Function parameter not found\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11454, __extension__
__PRETTY_FUNCTION__))
;
11455 Pos = It->second;
11456 ParmTy = PVD->getType();
11457 }
11458 ParamAttrs[Pos].Alignment =
11459 (*NI)
11460 ? (*NI)->EvaluateKnownConstInt(C)
11461 : llvm::APSInt::getUnsigned(
11462 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
11463 .getQuantity());
11464 ++NI;
11465 }
11466 // Mark linear parameters.
11467 auto *SI = Attr->steps_begin();
11468 auto *MI = Attr->modifiers_begin();
11469 for (const Expr *E : Attr->linears()) {
11470 E = E->IgnoreParenImpCasts();
11471 unsigned Pos;
11472 bool IsReferenceType = false;
11473 // Rescaling factor needed to compute the linear parameter
11474 // value in the mangled name.
11475 unsigned PtrRescalingFactor = 1;
11476 if (isa<CXXThisExpr>(E)) {
11477 Pos = ParamPositions[FD];
11478 auto *P = cast<PointerType>(E->getType());
11479 PtrRescalingFactor = CGM.getContext()
11480 .getTypeSizeInChars(P->getPointeeType())
11481 .getQuantity();
11482 } else {
11483 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
11484 ->getCanonicalDecl();
11485 auto It = ParamPositions.find(PVD);
11486 assert(It != ParamPositions.end() && "Function parameter not found")(static_cast <bool> (It != ParamPositions.end() &&
"Function parameter not found") ? void (0) : __assert_fail (
"It != ParamPositions.end() && \"Function parameter not found\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11486, __extension__
__PRETTY_FUNCTION__))
;
11487 Pos = It->second;
11488 if (auto *P = dyn_cast<PointerType>(PVD->getType()))
11489 PtrRescalingFactor = CGM.getContext()
11490 .getTypeSizeInChars(P->getPointeeType())
11491 .getQuantity();
11492 else if (PVD->getType()->isReferenceType()) {
11493 IsReferenceType = true;
11494 PtrRescalingFactor =
11495 CGM.getContext()
11496 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
11497 .getQuantity();
11498 }
11499 }
11500 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
11501 if (*MI == OMPC_LINEAR_ref)
11502 ParamAttr.Kind = LinearRef;
11503 else if (*MI == OMPC_LINEAR_uval)
11504 ParamAttr.Kind = LinearUVal;
11505 else if (IsReferenceType)
11506 ParamAttr.Kind = LinearVal;
11507 else
11508 ParamAttr.Kind = Linear;
11509 // Assuming a stride of 1, for `linear` without modifiers.
11510 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
11511 if (*SI) {
11512 Expr::EvalResult Result;
11513 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
11514 if (const auto *DRE =
11515 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
11516 if (const auto *StridePVD =
11517 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
11518 ParamAttr.HasVarStride = true;
11519 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
11520 assert(It != ParamPositions.end() &&(static_cast <bool> (It != ParamPositions.end() &&
"Function parameter not found") ? void (0) : __assert_fail (
"It != ParamPositions.end() && \"Function parameter not found\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11521, __extension__
__PRETTY_FUNCTION__))
11521 "Function parameter not found")(static_cast <bool> (It != ParamPositions.end() &&
"Function parameter not found") ? void (0) : __assert_fail (
"It != ParamPositions.end() && \"Function parameter not found\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11521, __extension__
__PRETTY_FUNCTION__))
;
11522 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
11523 }
11524 }
11525 } else {
11526 ParamAttr.StrideOrArg = Result.Val.getInt();
11527 }
11528 }
11529 // If we are using a linear clause on a pointer, we need to
11530 // rescale the value of linear_step with the byte size of the
11531 // pointee type.
11532 if (!ParamAttr.HasVarStride &&
11533 (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
11534 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
11535 ++SI;
11536 ++MI;
11537 }
11538 llvm::APSInt VLENVal;
11539 SourceLocation ExprLoc;
11540 const Expr *VLENExpr = Attr->getSimdlen();
11541 if (VLENExpr) {
11542 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
11543 ExprLoc = VLENExpr->getExprLoc();
11544 }
11545 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
11546 if (CGM.getTriple().isX86()) {
11547 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
11548 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
11549 unsigned VLEN = VLENVal.getExtValue();
11550 StringRef MangledName = Fn->getName();
11551 if (CGM.getTarget().hasFeature("sve"))
11552 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
11553 MangledName, 's', 128, Fn, ExprLoc);
11554 else if (CGM.getTarget().hasFeature("neon"))
11555 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
11556 MangledName, 'n', 128, Fn, ExprLoc);
11557 }
11558 }
11559 FD = FD->getPreviousDecl();
11560 }
11561}
11562
11563namespace {
11564/// Cleanup action for doacross support.
11565class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
11566public:
11567 static const int DoacrossFinArgs = 2;
11568
11569private:
11570 llvm::FunctionCallee RTLFn;
11571 llvm::Value *Args[DoacrossFinArgs];
11572
11573public:
11574 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
11575 ArrayRef<llvm::Value *> CallArgs)
11576 : RTLFn(RTLFn) {
11577 assert(CallArgs.size() == DoacrossFinArgs)(static_cast <bool> (CallArgs.size() == DoacrossFinArgs
) ? void (0) : __assert_fail ("CallArgs.size() == DoacrossFinArgs"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11577, __extension__
__PRETTY_FUNCTION__))
;
11578 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11579 }
11580 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
11581 if (!CGF.HaveInsertPoint())
11582 return;
11583 CGF.EmitRuntimeCall(RTLFn, Args);
11584 }
11585};
11586} // namespace
11587
11588void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
11589 const OMPLoopDirective &D,
11590 ArrayRef<Expr *> NumIterations) {
11591 if (!CGF.HaveInsertPoint())
11592 return;
11593
11594 ASTContext &C = CGM.getContext();
11595 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
11596 RecordDecl *RD;
11597 if (KmpDimTy.isNull()) {
11598 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
11599 // kmp_int64 lo; // lower
11600 // kmp_int64 up; // upper
11601 // kmp_int64 st; // stride
11602 // };
11603 RD = C.buildImplicitRecord("kmp_dim");
11604 RD->startDefinition();
11605 addFieldToRecordDecl(C, RD, Int64Ty);
11606 addFieldToRecordDecl(C, RD, Int64Ty);
11607 addFieldToRecordDecl(C, RD, Int64Ty);
11608 RD->completeDefinition();
11609 KmpDimTy = C.getRecordType(RD);
11610 } else {
11611 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
11612 }
11613 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
11614 QualType ArrayTy =
11615 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
11616
11617 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
11618 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
11619 enum { LowerFD = 0, UpperFD, StrideFD };
11620 // Fill dims with data.
11621 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
11622 LValue DimsLVal = CGF.MakeAddrLValue(
11623 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
11624 // dims.upper = num_iterations;
11625 LValue UpperLVal = CGF.EmitLValueForField(
11626 DimsLVal, *std::next(RD->field_begin(), UpperFD));
11627 llvm::Value *NumIterVal = CGF.EmitScalarConversion(
11628 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
11629 Int64Ty, NumIterations[I]->getExprLoc());
11630 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
11631 // dims.stride = 1;
11632 LValue StrideLVal = CGF.EmitLValueForField(
11633 DimsLVal, *std::next(RD->field_begin(), StrideFD));
11634 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
11635 StrideLVal);
11636 }
11637
11638 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
11639 // kmp_int32 num_dims, struct kmp_dim * dims);
11640 llvm::Value *Args[] = {
11641 emitUpdateLocation(CGF, D.getBeginLoc()),
11642 getThreadID(CGF, D.getBeginLoc()),
11643 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
11644 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11645 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
11646 CGM.VoidPtrTy)};
11647
11648 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction(
11649 CGM.getModule(), OMPRTL___kmpc_doacross_init);
11650 CGF.EmitRuntimeCall(RTLFn, Args);
11651 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
11652 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
11653 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction(
11654 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
11655 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11656 llvm::ArrayRef(FiniArgs));
11657}
11658
11659void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11660 const OMPDependClause *C) {
11661 QualType Int64Ty =
11662 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
11663 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
11664 QualType ArrayTy = CGM.getContext().getConstantArrayType(
11665 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
11666 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
11667 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
11668 const Expr *CounterVal = C->getLoopData(I);
11669 assert(CounterVal)(static_cast <bool> (CounterVal) ? void (0) : __assert_fail
("CounterVal", "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11669
, __extension__ __PRETTY_FUNCTION__))
;
11670 llvm::Value *CntVal = CGF.EmitScalarConversion(
11671 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
11672 CounterVal->getExprLoc());
11673 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
11674 /*Volatile=*/false, Int64Ty);
11675 }
11676 llvm::Value *Args[] = {
11677 emitUpdateLocation(CGF, C->getBeginLoc()),
11678 getThreadID(CGF, C->getBeginLoc()),
11679 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
11680 llvm::FunctionCallee RTLFn;
11681 if (C->getDependencyKind() == OMPC_DEPEND_source) {
11682 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
11683 OMPRTL___kmpc_doacross_post);
11684 } else {
11685 assert(C->getDependencyKind() == OMPC_DEPEND_sink)(static_cast <bool> (C->getDependencyKind() == OMPC_DEPEND_sink
) ? void (0) : __assert_fail ("C->getDependencyKind() == OMPC_DEPEND_sink"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11685, __extension__
__PRETTY_FUNCTION__))
;
11686 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
11687 OMPRTL___kmpc_doacross_wait);
11688 }
11689 CGF.EmitRuntimeCall(RTLFn, Args);
11690}
11691
11692void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
11693 llvm::FunctionCallee Callee,
11694 ArrayRef<llvm::Value *> Args) const {
11695 assert(Loc.isValid() && "Outlined function call location must be valid.")(static_cast <bool> (Loc.isValid() && "Outlined function call location must be valid."
) ? void (0) : __assert_fail ("Loc.isValid() && \"Outlined function call location must be valid.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11695, __extension__
__PRETTY_FUNCTION__))
;
11696 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
11697
11698 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
11699 if (Fn->doesNotThrow()) {
11700 CGF.EmitNounwindRuntimeCall(Fn, Args);
11701 return;
11702 }
11703 }
11704 CGF.EmitRuntimeCall(Callee, Args);
11705}
11706
11707void CGOpenMPRuntime::emitOutlinedFunctionCall(
11708 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
11709 ArrayRef<llvm::Value *> Args) const {
11710 emitCall(CGF, Loc, OutlinedFn, Args);
11711}
11712
11713void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
11714 if (const auto *FD = dyn_cast<FunctionDecl>(D))
11715 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
11716 HasEmittedDeclareTargetRegion = true;
11717}
11718
11719Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
11720 const VarDecl *NativeParam,
11721 const VarDecl *TargetParam) const {
11722 return CGF.GetAddrOfLocalVar(NativeParam);
11723}
11724
11725/// Return allocator value from expression, or return a null allocator (default
11726/// when no allocator specified).
11727static llvm::Value *getAllocatorVal(CodeGenFunction &CGF,
11728 const Expr *Allocator) {
11729 llvm::Value *AllocVal;
11730 if (Allocator) {
11731 AllocVal = CGF.EmitScalarExpr(Allocator);
11732 // According to the standard, the original allocator type is a enum
11733 // (integer). Convert to pointer type, if required.
11734 AllocVal = CGF.EmitScalarConversion(AllocVal, Allocator->getType(),
11735 CGF.getContext().VoidPtrTy,
11736 Allocator->getExprLoc());
11737 } else {
11738 // If no allocator specified, it defaults to the null allocator.
11739 AllocVal = llvm::Constant::getNullValue(
11740 CGF.CGM.getTypes().ConvertType(CGF.getContext().VoidPtrTy));
11741 }
11742 return AllocVal;
11743}
11744
11745/// Return the alignment from an allocate directive if present.
11746static llvm::Value *getAlignmentValue(CodeGenModule &CGM, const VarDecl *VD) {
11747 std::optional<CharUnits> AllocateAlignment = CGM.getOMPAllocateAlignment(VD);
11748
11749 if (!AllocateAlignment)
11750 return nullptr;
11751
11752 return llvm::ConstantInt::get(CGM.SizeTy, AllocateAlignment->getQuantity());
11753}
11754
11755Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
11756 const VarDecl *VD) {
11757 if (!VD)
11758 return Address::invalid();
11759 Address UntiedAddr = Address::invalid();
11760 Address UntiedRealAddr = Address::invalid();
11761 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn);
11762 if (It != FunctionToUntiedTaskStackMap.end()) {
11763 const UntiedLocalVarsAddressesMap &UntiedData =
11764 UntiedLocalVarsStack[It->second];
11765 auto I = UntiedData.find(VD);
11766 if (I != UntiedData.end()) {
11767 UntiedAddr = I->second.first;
11768 UntiedRealAddr = I->second.second;
11769 }
11770 }
11771 const VarDecl *CVD = VD->getCanonicalDecl();
11772 if (CVD->hasAttr<OMPAllocateDeclAttr>()) {
11773 // Use the default allocation.
11774 if (!isAllocatableDecl(VD))
11775 return UntiedAddr;
11776 llvm::Value *Size;
11777 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
11778 if (CVD->getType()->isVariablyModifiedType()) {
11779 Size = CGF.getTypeSize(CVD->getType());
11780 // Align the size: ((size + align - 1) / align) * align
11781 Size = CGF.Builder.CreateNUWAdd(
11782 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
11783 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
11784 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
11785 } else {
11786 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
11787 Size = CGM.getSize(Sz.alignTo(Align));
11788 }
11789 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11790 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
11791 const Expr *Allocator = AA->getAllocator();
11792 llvm::Value *AllocVal = getAllocatorVal(CGF, Allocator);
11793 llvm::Value *Alignment = getAlignmentValue(CGM, CVD);
11794 SmallVector<llvm::Value *, 4> Args;
11795 Args.push_back(ThreadID);
11796 if (Alignment)
11797 Args.push_back(Alignment);
11798 Args.push_back(Size);
11799 Args.push_back(AllocVal);
11800 llvm::omp::RuntimeFunction FnID =
11801 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
11802 llvm::Value *Addr = CGF.EmitRuntimeCall(
11803 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), FnID), Args,
11804 getName({CVD->getName(), ".void.addr"}));
11805 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction(
11806 CGM.getModule(), OMPRTL___kmpc_free);
11807 QualType Ty = CGM.getContext().getPointerType(CVD->getType());
11808 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11809 Addr, CGF.ConvertTypeForMem(Ty), getName({CVD->getName(), ".addr"}));
11810 if (UntiedAddr.isValid())
11811 CGF.EmitStoreOfScalar(Addr, UntiedAddr, /*Volatile=*/false, Ty);
11812
11813 // Cleanup action for allocate support.
11814 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
11815 llvm::FunctionCallee RTLFn;
11816 SourceLocation::UIntTy LocEncoding;
11817 Address Addr;
11818 const Expr *AllocExpr;
11819
11820 public:
11821 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
11822 SourceLocation::UIntTy LocEncoding, Address Addr,
11823 const Expr *AllocExpr)
11824 : RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr),
11825 AllocExpr(AllocExpr) {}
11826 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
11827 if (!CGF.HaveInsertPoint())
11828 return;
11829 llvm::Value *Args[3];
11830 Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID(
11831 CGF, SourceLocation::getFromRawEncoding(LocEncoding));
11832 Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11833 Addr.getPointer(), CGF.VoidPtrTy);
11834 llvm::Value *AllocVal = getAllocatorVal(CGF, AllocExpr);
11835 Args[2] = AllocVal;
11836 CGF.EmitRuntimeCall(RTLFn, Args);
11837 }
11838 };
11839 Address VDAddr =
11840 UntiedRealAddr.isValid()
11841 ? UntiedRealAddr
11842 : Address(Addr, CGF.ConvertTypeForMem(CVD->getType()), Align);
11843 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(
11844 NormalAndEHCleanup, FiniRTLFn, CVD->getLocation().getRawEncoding(),
11845 VDAddr, Allocator);
11846 if (UntiedRealAddr.isValid())
11847 if (auto *Region =
11848 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
11849 Region->emitUntiedSwitch(CGF);
11850 return VDAddr;
11851 }
11852 return UntiedAddr;
11853}
11854
11855bool CGOpenMPRuntime::isLocalVarInUntiedTask(CodeGenFunction &CGF,
11856 const VarDecl *VD) const {
11857 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn);
11858 if (It == FunctionToUntiedTaskStackMap.end())
11859 return false;
11860 return UntiedLocalVarsStack[It->second].count(VD) > 0;
11861}
11862
11863CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII(
11864 CodeGenModule &CGM, const OMPLoopDirective &S)
11865 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) {
11866 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.")(static_cast <bool> (CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.") ? void (0) : __assert_fail ("CGM.getLangOpts().OpenMP && \"Not in OpenMP mode.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11866, __extension__
__PRETTY_FUNCTION__))
;
11867 if (!NeedToPush)
11868 return;
11869 NontemporalDeclsSet &DS =
11870 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
11871 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) {
11872 for (const Stmt *Ref : C->private_refs()) {
11873 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts();
11874 const ValueDecl *VD;
11875 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
11876 VD = DRE->getDecl();
11877 } else {
11878 const auto *ME = cast<MemberExpr>(SimpleRefExpr);
11879 assert((ME->isImplicitCXXThis() ||(static_cast <bool> ((ME->isImplicitCXXThis() || isa
<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts(
))) && "Expected member of current class.") ? void (0
) : __assert_fail ("(ME->isImplicitCXXThis() || isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && \"Expected member of current class.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11881, __extension__
__PRETTY_FUNCTION__))
11880 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) &&(static_cast <bool> ((ME->isImplicitCXXThis() || isa
<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts(
))) && "Expected member of current class.") ? void (0
) : __assert_fail ("(ME->isImplicitCXXThis() || isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && \"Expected member of current class.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11881, __extension__
__PRETTY_FUNCTION__))
11881 "Expected member of current class.")(static_cast <bool> ((ME->isImplicitCXXThis() || isa
<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts(
))) && "Expected member of current class.") ? void (0
) : __assert_fail ("(ME->isImplicitCXXThis() || isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && \"Expected member of current class.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11881, __extension__
__PRETTY_FUNCTION__))
;
11882 VD = ME->getMemberDecl();
11883 }
11884 DS.insert(VD);
11885 }
11886 }
11887}
11888
11889CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() {
11890 if (!NeedToPush)
11891 return;
11892 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
11893}
11894
11895CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII(
11896 CodeGenFunction &CGF,
11897 const llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
11898 std::pair<Address, Address>> &LocalVars)
11899 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
11900 if (!NeedToPush)
11901 return;
11902 CGM.getOpenMPRuntime().FunctionToUntiedTaskStackMap.try_emplace(
11903 CGF.CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
11904 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
11905}
11906
11907CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::~UntiedTaskLocalDeclsRAII() {
11908 if (!NeedToPush)
11909 return;
11910 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
11911}
11912
11913bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const {
11914 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.")(static_cast <bool> (CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.") ? void (0) : __assert_fail ("CGM.getLangOpts().OpenMP && \"Not in OpenMP mode.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 11914, __extension__
__PRETTY_FUNCTION__))
;
11915
11916 return llvm::any_of(
11917 CGM.getOpenMPRuntime().NontemporalDeclsStack,
11918 [VD](const NontemporalDeclsSet &Set) { return Set.contains(VD); });
11919}
11920
11921void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
11922 const OMPExecutableDirective &S,
11923 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled)
11924 const {
11925 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
11926 // Vars in target/task regions must be excluded completely.
11927 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) ||
11928 isOpenMPTaskingDirective(S.getDirectiveKind())) {
11929 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
11930 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind());
11931 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
11932 for (const CapturedStmt::Capture &Cap : CS->captures()) {
11933 if (Cap.capturesVariable() || Cap.capturesVariableByCopy())
11934 NeedToCheckForLPCs.insert(Cap.getCapturedVar());
11935 }
11936 }
11937 // Exclude vars in private clauses.
11938 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
11939 for (const Expr *Ref : C->varlists()) {
11940 if (!Ref->getType()->isScalarType())
11941 continue;
11942 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11943 if (!DRE)
11944 continue;
11945 NeedToCheckForLPCs.insert(DRE->getDecl());
11946 }
11947 }
11948 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
11949 for (const Expr *Ref : C->varlists()) {
11950 if (!Ref->getType()->isScalarType())
11951 continue;
11952 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11953 if (!DRE)
11954 continue;
11955 NeedToCheckForLPCs.insert(DRE->getDecl());
11956 }
11957 }
11958 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
11959 for (const Expr *Ref : C->varlists()) {
11960 if (!Ref->getType()->isScalarType())
11961 continue;
11962 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11963 if (!DRE)
11964 continue;
11965 NeedToCheckForLPCs.insert(DRE->getDecl());
11966 }
11967 }
11968 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
11969 for (const Expr *Ref : C->varlists()) {
11970 if (!Ref->getType()->isScalarType())
11971 continue;
11972 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11973 if (!DRE)
11974 continue;
11975 NeedToCheckForLPCs.insert(DRE->getDecl());
11976 }
11977 }
11978 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
11979 for (const Expr *Ref : C->varlists()) {
11980 if (!Ref->getType()->isScalarType())
11981 continue;
11982 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11983 if (!DRE)
11984 continue;
11985 NeedToCheckForLPCs.insert(DRE->getDecl());
11986 }
11987 }
11988 for (const Decl *VD : NeedToCheckForLPCs) {
11989 for (const LastprivateConditionalData &Data :
11990 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
11991 if (Data.DeclToUniqueName.count(VD) > 0) {
11992 if (!Data.Disabled)
11993 NeedToAddForLPCsAsDisabled.insert(VD);
11994 break;
11995 }
11996 }
11997 }
11998}
11999
12000CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12001 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal)
12002 : CGM(CGF.CGM),
12003 Action((CGM.getLangOpts().OpenMP >= 50 &&
12004 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12005 [](const OMPLastprivateClause *C) {
12006 return C->getKind() ==
12007 OMPC_LASTPRIVATE_conditional;
12008 }))
12009 ? ActionToDo::PushAsLastprivateConditional
12010 : ActionToDo::DoNotPush) {
12011 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.")(static_cast <bool> (CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.") ? void (0) : __assert_fail ("CGM.getLangOpts().OpenMP && \"Not in OpenMP mode.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12011, __extension__
__PRETTY_FUNCTION__))
;
12012 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12013 return;
12014 assert(Action == ActionToDo::PushAsLastprivateConditional &&(static_cast <bool> (Action == ActionToDo::PushAsLastprivateConditional
&& "Expected a push action.") ? void (0) : __assert_fail
("Action == ActionToDo::PushAsLastprivateConditional && \"Expected a push action.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12015, __extension__
__PRETTY_FUNCTION__))
12015 "Expected a push action.")(static_cast <bool> (Action == ActionToDo::PushAsLastprivateConditional
&& "Expected a push action.") ? void (0) : __assert_fail
("Action == ActionToDo::PushAsLastprivateConditional && \"Expected a push action.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12015, __extension__
__PRETTY_FUNCTION__))
;
12016 LastprivateConditionalData &Data =
12017 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12018 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
12019 if (C->getKind() != OMPC_LASTPRIVATE_conditional)
12020 continue;
12021
12022 for (const Expr *Ref : C->varlists()) {
12023 Data.DeclToUniqueName.insert(std::make_pair(
12024 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(),
12025 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref))));
12026 }
12027 }
12028 Data.IVLVal = IVLVal;
12029 Data.Fn = CGF.CurFn;
12030}
12031
12032CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12033 CodeGenFunction &CGF, const OMPExecutableDirective &S)
12034 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) {
12035 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.")(static_cast <bool> (CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.") ? void (0) : __assert_fail ("CGM.getLangOpts().OpenMP && \"Not in OpenMP mode.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12035, __extension__
__PRETTY_FUNCTION__))
;
12036 if (CGM.getLangOpts().OpenMP < 50)
12037 return;
12038 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12039 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12040 if (!NeedToAddForLPCsAsDisabled.empty()) {
12041 Action = ActionToDo::DisableLastprivateConditional;
12042 LastprivateConditionalData &Data =
12043 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12044 for (const Decl *VD : NeedToAddForLPCsAsDisabled)
12045 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>()));
12046 Data.Fn = CGF.CurFn;
12047 Data.Disabled = true;
12048 }
12049}
12050
12051CGOpenMPRuntime::LastprivateConditionalRAII
12052CGOpenMPRuntime::LastprivateConditionalRAII::disable(
12053 CodeGenFunction &CGF, const OMPExecutableDirective &S) {
12054 return LastprivateConditionalRAII(CGF, S);
12055}
12056
12057CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() {
12058 if (CGM.getLangOpts().OpenMP < 50)
12059 return;
12060 if (Action == ActionToDo::DisableLastprivateConditional) {
12061 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&(static_cast <bool> (CGM.getOpenMPRuntime().LastprivateConditionalStack
.back().Disabled && "Expected list of disabled private vars."
) ? void (0) : __assert_fail ("CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && \"Expected list of disabled private vars.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12062, __extension__
__PRETTY_FUNCTION__))
12062 "Expected list of disabled private vars.")(static_cast <bool> (CGM.getOpenMPRuntime().LastprivateConditionalStack
.back().Disabled && "Expected list of disabled private vars."
) ? void (0) : __assert_fail ("CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && \"Expected list of disabled private vars.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12062, __extension__
__PRETTY_FUNCTION__))
;
12063 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12064 }
12065 if (Action == ActionToDo::PushAsLastprivateConditional) {
12066 assert((static_cast <bool> (!CGM.getOpenMPRuntime().LastprivateConditionalStack
.back().Disabled && "Expected list of lastprivate conditional vars."
) ? void (0) : __assert_fail ("!CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && \"Expected list of lastprivate conditional vars.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12068, __extension__
__PRETTY_FUNCTION__))
12067 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&(static_cast <bool> (!CGM.getOpenMPRuntime().LastprivateConditionalStack
.back().Disabled && "Expected list of lastprivate conditional vars."
) ? void (0) : __assert_fail ("!CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && \"Expected list of lastprivate conditional vars.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12068, __extension__
__PRETTY_FUNCTION__))
12068 "Expected list of lastprivate conditional vars.")(static_cast <bool> (!CGM.getOpenMPRuntime().LastprivateConditionalStack
.back().Disabled && "Expected list of lastprivate conditional vars."
) ? void (0) : __assert_fail ("!CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && \"Expected list of lastprivate conditional vars.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12068, __extension__
__PRETTY_FUNCTION__))
;
12069 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12070 }
12071}
12072
12073Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF,
12074 const VarDecl *VD) {
12075 ASTContext &C = CGM.getContext();
12076 auto I = LastprivateConditionalToTypes.find(CGF.CurFn);
12077 if (I == LastprivateConditionalToTypes.end())
12078 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first;
12079 QualType NewType;
12080 const FieldDecl *VDField;
12081 const FieldDecl *FiredField;
12082 LValue BaseLVal;
12083 auto VI = I->getSecond().find(VD);
12084 if (VI == I->getSecond().end()) {
12085 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional");
12086 RD->startDefinition();
12087 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType());
12088 FiredField = addFieldToRecordDecl(C, RD, C.CharTy);
12089 RD->completeDefinition();
12090 NewType = C.getRecordType(RD);
12091 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName());
12092 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl);
12093 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12094 } else {
12095 NewType = std::get<0>(VI->getSecond());
12096 VDField = std::get<1>(VI->getSecond());
12097 FiredField = std::get<2>(VI->getSecond());
12098 BaseLVal = std::get<3>(VI->getSecond());
12099 }
12100 LValue FiredLVal =
12101 CGF.EmitLValueForField(BaseLVal, FiredField);
12102 CGF.EmitStoreOfScalar(
12103 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)),
12104 FiredLVal);
12105 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF);
12106}
12107
12108namespace {
12109/// Checks if the lastprivate conditional variable is referenced in LHS.
12110class LastprivateConditionalRefChecker final
12111 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> {
12112 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM;
12113 const Expr *FoundE = nullptr;
12114 const Decl *FoundD = nullptr;
12115 StringRef UniqueDeclName;
12116 LValue IVLVal;
12117 llvm::Function *FoundFn = nullptr;
12118 SourceLocation Loc;
12119
12120public:
12121 bool VisitDeclRefExpr(const DeclRefExpr *E) {
12122 for (const CGOpenMPRuntime::LastprivateConditionalData &D :
12123 llvm::reverse(LPM)) {
12124 auto It = D.DeclToUniqueName.find(E->getDecl());
12125 if (It == D.DeclToUniqueName.end())
12126 continue;
12127 if (D.Disabled)
12128 return false;
12129 FoundE = E;
12130 FoundD = E->getDecl()->getCanonicalDecl();
12131 UniqueDeclName = It->second;
12132 IVLVal = D.IVLVal;
12133 FoundFn = D.Fn;
12134 break;
12135 }
12136 return FoundE == E;
12137 }
12138 bool VisitMemberExpr(const MemberExpr *E) {
12139 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase()))
12140 return false;
12141 for (const CGOpenMPRuntime::LastprivateConditionalData &D :
12142 llvm::reverse(LPM)) {
12143 auto It = D.DeclToUniqueName.find(E->getMemberDecl());
12144 if (It == D.DeclToUniqueName.end())
12145 continue;
12146 if (D.Disabled)
12147 return false;
12148 FoundE = E;
12149 FoundD = E->getMemberDecl()->getCanonicalDecl();
12150 UniqueDeclName = It->second;
12151 IVLVal = D.IVLVal;
12152 FoundFn = D.Fn;
12153 break;
12154 }
12155 return FoundE == E;
12156 }
12157 bool VisitStmt(const Stmt *S) {
12158 for (const Stmt *Child : S->children()) {
12159 if (!Child)
12160 continue;
12161 if (const auto *E = dyn_cast<Expr>(Child))
12162 if (!E->isGLValue())
12163 continue;
12164 if (Visit(Child))
12165 return true;
12166 }
12167 return false;
12168 }
12169 explicit LastprivateConditionalRefChecker(
12170 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12171 : LPM(LPM) {}
12172 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12173 getFoundData() const {
12174 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12175 }
12176};
12177} // namespace
12178
12179void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF,
12180 LValue IVLVal,
12181 StringRef UniqueDeclName,
12182 LValue LVal,
12183 SourceLocation Loc) {
12184 // Last updated loop counter for the lastprivate conditional var.
12185 // int<xx> last_iv = 0;
12186 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType());
12187 llvm::Constant *LastIV = OMPBuilder.getOrCreateInternalVariable(
12188 LLIVTy, getName({UniqueDeclName, "iv"}));
12189 cast<llvm::GlobalVariable>(LastIV)->setAlignment(
12190 IVLVal.getAlignment().getAsAlign());
12191 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType());
12192
12193 // Last value of the lastprivate conditional.
12194 // decltype(priv_a) last_a;
12195 llvm::GlobalVariable *Last = OMPBuilder.getOrCreateInternalVariable(
12196 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName);
12197 Last->setAlignment(LVal.getAlignment().getAsAlign());
12198 LValue LastLVal = CGF.MakeAddrLValue(
12199 Address(Last, Last->getValueType(), LVal.getAlignment()), LVal.getType());
12200
12201 // Global loop counter. Required to handle inner parallel-for regions.
12202 // iv
12203 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc);
12204
12205 // #pragma omp critical(a)
12206 // if (last_iv <= iv) {
12207 // last_iv = iv;
12208 // last_a = priv_a;
12209 // }
12210 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
12211 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
12212 Action.Enter(CGF);
12213 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc);
12214 // (last_iv <= iv) ? Check if the variable is updated and store new
12215 // value in global var.
12216 llvm::Value *CmpRes;
12217 if (IVLVal.getType()->isSignedIntegerType()) {
12218 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal);
12219 } else {
12220 assert(IVLVal.getType()->isUnsignedIntegerType() &&(static_cast <bool> (IVLVal.getType()->isUnsignedIntegerType
() && "Loop iteration variable must be integer.") ? void
(0) : __assert_fail ("IVLVal.getType()->isUnsignedIntegerType() && \"Loop iteration variable must be integer.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12221, __extension__
__PRETTY_FUNCTION__))
12221 "Loop iteration variable must be integer.")(static_cast <bool> (IVLVal.getType()->isUnsignedIntegerType
() && "Loop iteration variable must be integer.") ? void
(0) : __assert_fail ("IVLVal.getType()->isUnsignedIntegerType() && \"Loop iteration variable must be integer.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12221, __extension__
__PRETTY_FUNCTION__))
;
12222 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal);
12223 }
12224 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then");
12225 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit");
12226 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
12227 // {
12228 CGF.EmitBlock(ThenBB);
12229
12230 // last_iv = iv;
12231 CGF.EmitStoreOfScalar(IVVal, LastIVLVal);
12232
12233 // last_a = priv_a;
12234 switch (CGF.getEvaluationKind(LVal.getType())) {
12235 case TEK_Scalar: {
12236 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc);
12237 CGF.EmitStoreOfScalar(PrivVal, LastLVal);
12238 break;
12239 }
12240 case TEK_Complex: {
12241 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc);
12242 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false);
12243 break;
12244 }
12245 case TEK_Aggregate:
12246 llvm_unreachable(::llvm::llvm_unreachable_internal("Aggregates are not supported in lastprivate conditional."
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12247)
12247 "Aggregates are not supported in lastprivate conditional.")::llvm::llvm_unreachable_internal("Aggregates are not supported in lastprivate conditional."
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12247)
;
12248 }
12249 // }
12250 CGF.EmitBranch(ExitBB);
12251 // There is no need to emit line number for unconditional branch.
12252 (void)ApplyDebugLocation::CreateEmpty(CGF);
12253 CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
12254 };
12255
12256 if (CGM.getLangOpts().OpenMPSimd) {
12257 // Do not emit as a critical region as no parallel region could be emitted.
12258 RegionCodeGenTy ThenRCG(CodeGen);
12259 ThenRCG(CGF);
12260 } else {
12261 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc);
12262 }
12263}
12264
12265void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF,
12266 const Expr *LHS) {
12267 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
12268 return;
12269 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack);
12270 if (!Checker.Visit(LHS))
12271 return;
12272 const Expr *FoundE;
12273 const Decl *FoundD;
12274 StringRef UniqueDeclName;
12275 LValue IVLVal;
12276 llvm::Function *FoundFn;
12277 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
12278 Checker.getFoundData();
12279 if (FoundFn != CGF.CurFn) {
12280 // Special codegen for inner parallel regions.
12281 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1;
12282 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD);
12283 assert(It != LastprivateConditionalToTypes[FoundFn].end() &&(static_cast <bool> (It != LastprivateConditionalToTypes
[FoundFn].end() && "Lastprivate conditional is not found in outer region."
) ? void (0) : __assert_fail ("It != LastprivateConditionalToTypes[FoundFn].end() && \"Lastprivate conditional is not found in outer region.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12284, __extension__
__PRETTY_FUNCTION__))
12284 "Lastprivate conditional is not found in outer region.")(static_cast <bool> (It != LastprivateConditionalToTypes
[FoundFn].end() && "Lastprivate conditional is not found in outer region."
) ? void (0) : __assert_fail ("It != LastprivateConditionalToTypes[FoundFn].end() && \"Lastprivate conditional is not found in outer region.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12284, __extension__
__PRETTY_FUNCTION__))
;
12285 QualType StructTy = std::get<0>(It->getSecond());
12286 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
12287 LValue PrivLVal = CGF.EmitLValue(FoundE);
12288 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
12289 PrivLVal.getAddress(CGF),
12290 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy)),
12291 CGF.ConvertTypeForMem(StructTy));
12292 LValue BaseLVal =
12293 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl);
12294 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl);
12295 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get(
12296 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)),
12297 FiredLVal, llvm::AtomicOrdering::Unordered,
12298 /*IsVolatile=*/true, /*isInit=*/false);
12299 return;
12300 }
12301
12302 // Private address of the lastprivate conditional in the current context.
12303 // priv_a
12304 LValue LVal = CGF.EmitLValue(FoundE);
12305 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal,
12306 FoundE->getExprLoc());
12307}
12308
12309void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional(
12310 CodeGenFunction &CGF, const OMPExecutableDirective &D,
12311 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) {
12312 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
12313 return;
12314 auto Range = llvm::reverse(LastprivateConditionalStack);
12315 auto It = llvm::find_if(
12316 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; });
12317 if (It == Range.end() || It->Fn != CGF.CurFn)
12318 return;
12319 auto LPCI = LastprivateConditionalToTypes.find(It->Fn);
12320 assert(LPCI != LastprivateConditionalToTypes.end() &&(static_cast <bool> (LPCI != LastprivateConditionalToTypes
.end() && "Lastprivates must be registered already.")
? void (0) : __assert_fail ("LPCI != LastprivateConditionalToTypes.end() && \"Lastprivates must be registered already.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12321, __extension__
__PRETTY_FUNCTION__))
12321 "Lastprivates must be registered already.")(static_cast <bool> (LPCI != LastprivateConditionalToTypes
.end() && "Lastprivates must be registered already.")
? void (0) : __assert_fail ("LPCI != LastprivateConditionalToTypes.end() && \"Lastprivates must be registered already.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12321, __extension__
__PRETTY_FUNCTION__))
;
12322 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
12323 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind());
12324 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
12325 for (const auto &Pair : It->DeclToUniqueName) {
12326 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl());
12327 if (!CS->capturesVariable(VD) || IgnoredDecls.contains(VD))
12328 continue;
12329 auto I = LPCI->getSecond().find(Pair.first);
12330 assert(I != LPCI->getSecond().end() &&(static_cast <bool> (I != LPCI->getSecond().end() &&
"Lastprivate must be rehistered already.") ? void (0) : __assert_fail
("I != LPCI->getSecond().end() && \"Lastprivate must be rehistered already.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12331, __extension__
__PRETTY_FUNCTION__))
12331 "Lastprivate must be rehistered already.")(static_cast <bool> (I != LPCI->getSecond().end() &&
"Lastprivate must be rehistered already.") ? void (0) : __assert_fail
("I != LPCI->getSecond().end() && \"Lastprivate must be rehistered already.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12331, __extension__
__PRETTY_FUNCTION__))
;
12332 // bool Cmp = priv_a.Fired != 0;
12333 LValue BaseLVal = std::get<3>(I->getSecond());
12334 LValue FiredLVal =
12335 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond()));
12336 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc());
12337 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res);
12338 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then");
12339 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done");
12340 // if (Cmp) {
12341 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
12342 CGF.EmitBlock(ThenBB);
12343 Address Addr = CGF.GetAddrOfLocalVar(VD);
12344 LValue LVal;
12345 if (VD->getType()->isReferenceType())
12346 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
12347 AlignmentSource::Decl);
12348 else
12349 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(),
12350 AlignmentSource::Decl);
12351 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal,
12352 D.getBeginLoc());
12353 auto AL = ApplyDebugLocation::CreateArtificial(CGF);
12354 CGF.EmitBlock(DoneBB, /*IsFinal=*/true);
12355 // }
12356 }
12357}
12358
12359void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate(
12360 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD,
12361 SourceLocation Loc) {
12362 if (CGF.getLangOpts().OpenMP < 50)
12363 return;
12364 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD);
12365 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() &&(static_cast <bool> (It != LastprivateConditionalStack.
back().DeclToUniqueName.end() && "Unknown lastprivate conditional variable."
) ? void (0) : __assert_fail ("It != LastprivateConditionalStack.back().DeclToUniqueName.end() && \"Unknown lastprivate conditional variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12366, __extension__
__PRETTY_FUNCTION__))
12366 "Unknown lastprivate conditional variable.")(static_cast <bool> (It != LastprivateConditionalStack.
back().DeclToUniqueName.end() && "Unknown lastprivate conditional variable."
) ? void (0) : __assert_fail ("It != LastprivateConditionalStack.back().DeclToUniqueName.end() && \"Unknown lastprivate conditional variable.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12366, __extension__
__PRETTY_FUNCTION__))
;
12367 StringRef UniqueName = It->second;
12368 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName);
12369 // The variable was not updated in the region - exit.
12370 if (!GV)
12371 return;
12372 LValue LPLVal = CGF.MakeAddrLValue(
12373 Address(GV, GV->getValueType(), PrivLVal.getAlignment()),
12374 PrivLVal.getType().getNonReferenceType());
12375 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc);
12376 CGF.EmitStoreOfScalar(Res, PrivLVal);
12377}
12378
12379llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
12380 CodeGenFunction &CGF, const OMPExecutableDirective &D,
12381 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
12382 const RegionCodeGenTy &CodeGen) {
12383 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12383)
;
12384}
12385
12386llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
12387 CodeGenFunction &CGF, const OMPExecutableDirective &D,
12388 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
12389 const RegionCodeGenTy &CodeGen) {
12390 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12390)
;
12391}
12392
12393llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
12394 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
12395 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
12396 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
12397 bool Tied, unsigned &NumberOfParts) {
12398 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12398)
;
12399}
12400
12401void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
12402 SourceLocation Loc,
12403 llvm::Function *OutlinedFn,
12404 ArrayRef<llvm::Value *> CapturedVars,
12405 const Expr *IfCond,
12406 llvm::Value *NumThreads) {
12407 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12407)
;
12408}
12409
12410void CGOpenMPSIMDRuntime::emitCriticalRegion(
12411 CodeGenFunction &CGF, StringRef CriticalName,
12412 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
12413 const Expr *Hint) {
12414 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12414)
;
12415}
12416
12417void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
12418 const RegionCodeGenTy &MasterOpGen,
12419 SourceLocation Loc) {
12420 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12420)
;
12421}
12422
12423void CGOpenMPSIMDRuntime::emitMaskedRegion(CodeGenFunction &CGF,
12424 const RegionCodeGenTy &MasterOpGen,
12425 SourceLocation Loc,
12426 const Expr *Filter) {
12427 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12427)
;
12428}
12429
12430void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
12431 SourceLocation Loc) {
12432 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12432)
;
12433}
12434
12435void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
12436 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
12437 SourceLocation Loc) {
12438 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12438)
;
12439}
12440
12441void CGOpenMPSIMDRuntime::emitSingleRegion(
12442 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
12443 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
12444 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
12445 ArrayRef<const Expr *> AssignmentOps) {
12446 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12446)
;
12447}
12448
12449void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
12450 const RegionCodeGenTy &OrderedOpGen,
12451 SourceLocation Loc,
12452 bool IsThreads) {
12453 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12453)
;
12454}
12455
12456void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
12457 SourceLocation Loc,
12458 OpenMPDirectiveKind Kind,
12459 bool EmitChecks,
12460 bool ForceSimpleCall) {
12461 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12461)
;
12462}
12463
12464void CGOpenMPSIMDRuntime::emitForDispatchInit(
12465 CodeGenFunction &CGF, SourceLocation Loc,
12466 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
12467 bool Ordered, const DispatchRTInput &DispatchValues) {
12468 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12468)
;
12469}
12470
12471void CGOpenMPSIMDRuntime::emitForStaticInit(
12472 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
12473 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
12474 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12474)
;
12475}
12476
12477void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
12478 CodeGenFunction &CGF, SourceLocation Loc,
12479 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
12480 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12480)
;
12481}
12482
12483void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
12484 SourceLocation Loc,
12485 unsigned IVSize,
12486 bool IVSigned) {
12487 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12487)
;
12488}
12489
12490void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
12491 SourceLocation Loc,
12492 OpenMPDirectiveKind DKind) {
12493 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12493)
;
12494}
12495
12496llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
12497 SourceLocation Loc,
12498 unsigned IVSize, bool IVSigned,
12499 Address IL, Address LB,
12500 Address UB, Address ST) {
12501 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12501)
;
12502}
12503
12504void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
12505 llvm::Value *NumThreads,
12506 SourceLocation Loc) {
12507 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12507)
;
12508}
12509
12510void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
12511 ProcBindKind ProcBind,
12512 SourceLocation Loc) {
12513 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12513)
;
12514}
12515
12516Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
12517 const VarDecl *VD,
12518 Address VDAddr,
12519 SourceLocation Loc) {
12520 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12520)
;
12521}
12522
12523llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
12524 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
12525 CodeGenFunction *CGF) {
12526 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12526)
;
12527}
12528
12529Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
12530 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
12531 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12531)
;
12532}
12533
12534void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
12535 ArrayRef<const Expr *> Vars,
12536 SourceLocation Loc,
12537 llvm::AtomicOrdering AO) {
12538 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12538)
;
12539}
12540
12541void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
12542 const OMPExecutableDirective &D,
12543 llvm::Function *TaskFunction,
12544 QualType SharedsTy, Address Shareds,
12545 const Expr *IfCond,
12546 const OMPTaskDataTy &Data) {
12547 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12547)
;
12548}
12549
12550void CGOpenMPSIMDRuntime::emitTaskLoopCall(
12551 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
12552 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
12553 const Expr *IfCond, const OMPTaskDataTy &Data) {
12554 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12554)
;
12555}
12556
12557void CGOpenMPSIMDRuntime::emitReduction(
12558 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
12559 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
12560 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
12561 assert(Options.SimpleReduction && "Only simple reduction is expected.")(static_cast <bool> (Options.SimpleReduction &&
"Only simple reduction is expected.") ? void (0) : __assert_fail
("Options.SimpleReduction && \"Only simple reduction is expected.\""
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12561, __extension__
__PRETTY_FUNCTION__))
;
12562 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
12563 ReductionOps, Options);
12564}
12565
12566llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
12567 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
12568 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
12569 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12569)
;
12570}
12571
12572void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF,
12573 SourceLocation Loc,
12574 bool IsWorksharingReduction) {
12575 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12575)
;
12576}
12577
12578void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
12579 SourceLocation Loc,
12580 ReductionCodeGen &RCG,
12581 unsigned N) {
12582 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12582)
;
12583}
12584
12585Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
12586 SourceLocation Loc,
12587 llvm::Value *ReductionsPtr,
12588 LValue SharedLVal) {
12589 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12589)
;
12590}
12591
12592void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
12593 SourceLocation Loc,
12594 const OMPTaskDataTy &Data) {
12595 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12595)
;
12596}
12597
12598void CGOpenMPSIMDRuntime::emitCancellationPointCall(
12599 CodeGenFunction &CGF, SourceLocation Loc,
12600 OpenMPDirectiveKind CancelRegion) {
12601 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12601)
;
12602}
12603
12604void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
12605 SourceLocation Loc, const Expr *IfCond,
12606 OpenMPDirectiveKind CancelRegion) {
12607 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12607)
;
12608}
12609
12610void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
12611 const OMPExecutableDirective &D, StringRef ParentName,
12612 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
12613 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
12614 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12614)
;
12615}
12616
12617void CGOpenMPSIMDRuntime::emitTargetCall(
12618 CodeGenFunction &CGF, const OMPExecutableDirective &D,
12619 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
12620 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device,
12621 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
12622 const OMPLoopDirective &D)>
12623 SizeEmitter) {
12624 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12624)
;
12625}
12626
12627bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
12628 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12628)
;
12629}
12630
12631bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
12632 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12632)
;
12633}
12634
12635bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
12636 return false;
12637}
12638
12639void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
12640 const OMPExecutableDirective &D,
12641 SourceLocation Loc,
12642 llvm::Function *OutlinedFn,
12643 ArrayRef<llvm::Value *> CapturedVars) {
12644 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12644)
;
12645}
12646
12647void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
12648 const Expr *NumTeams,
12649 const Expr *ThreadLimit,
12650 SourceLocation Loc) {
12651 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12651)
;
12652}
12653
12654void CGOpenMPSIMDRuntime::emitTargetDataCalls(
12655 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
12656 const Expr *Device, const RegionCodeGenTy &CodeGen,
12657 CGOpenMPRuntime::TargetDataInfo &Info) {
12658 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12658)
;
12659}
12660
12661void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
12662 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
12663 const Expr *Device) {
12664 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12664)
;
12665}
12666
12667void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
12668 const OMPLoopDirective &D,
12669 ArrayRef<Expr *> NumIterations) {
12670 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12670)
;
12671}
12672
12673void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
12674 const OMPDependClause *C) {
12675 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12675)
;
12676}
12677
12678const VarDecl *
12679CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
12680 const VarDecl *NativeParam) const {
12681 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12681)
;
12682}
12683
12684Address
12685CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
12686 const VarDecl *NativeParam,
12687 const VarDecl *TargetParam) const {
12688 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "clang/lib/CodeGen/CGOpenMPRuntime.cpp", 12688)
;
12689}

/build/source/llvm/include/llvm/ADT/PointerUnion.h

1//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
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/// \file
10/// This file defines the PointerUnion class, which is a discriminated union of
11/// pointer types.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_ADT_POINTERUNION_H
16#define LLVM_ADT_POINTERUNION_H
17
18#include "llvm/ADT/DenseMapInfo.h"
19#include "llvm/ADT/PointerIntPair.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/Support/Casting.h"
22#include "llvm/Support/PointerLikeTypeTraits.h"
23#include <algorithm>
24#include <cassert>
25#include <cstddef>
26#include <cstdint>
27
28namespace llvm {
29
30namespace pointer_union_detail {
31 /// Determine the number of bits required to store integers with values < n.
32 /// This is ceil(log2(n)).
33 constexpr int bitsRequired(unsigned n) {
34 return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0;
35 }
36
37 template <typename... Ts> constexpr int lowBitsAvailable() {
38 return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...});
39 }
40
41 /// Find the first type in a list of types.
42 template <typename T, typename...> struct GetFirstType {
43 using type = T;
44 };
45
46 /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
47 /// for the template arguments.
48 template <typename ...PTs> class PointerUnionUIntTraits {
49 public:
50 static inline void *getAsVoidPointer(void *P) { return P; }
51 static inline void *getFromVoidPointer(void *P) { return P; }
52 static constexpr int NumLowBitsAvailable = lowBitsAvailable<PTs...>();
53 };
54
55 template <typename Derived, typename ValTy, int I, typename ...Types>
56 class PointerUnionMembers;
57
58 template <typename Derived, typename ValTy, int I>
59 class PointerUnionMembers<Derived, ValTy, I> {
60 protected:
61 ValTy Val;
62 PointerUnionMembers() = default;
63 PointerUnionMembers(ValTy Val) : Val(Val) {}
64
65 friend struct PointerLikeTypeTraits<Derived>;
66 };
67
68 template <typename Derived, typename ValTy, int I, typename Type,
69 typename ...Types>
70 class PointerUnionMembers<Derived, ValTy, I, Type, Types...>
71 : public PointerUnionMembers<Derived, ValTy, I + 1, Types...> {
72 using Base = PointerUnionMembers<Derived, ValTy, I + 1, Types...>;
73 public:
74 using Base::Base;
75 PointerUnionMembers() = default;
76 PointerUnionMembers(Type V)
77 : Base(ValTy(const_cast<void *>(
78 PointerLikeTypeTraits<Type>::getAsVoidPointer(V)),
79 I)) {}
80
81 using Base::operator=;
82 Derived &operator=(Type V) {
83 this->Val = ValTy(
84 const_cast<void *>(PointerLikeTypeTraits<Type>::getAsVoidPointer(V)),
85 I);
86 return static_cast<Derived &>(*this);
87 };
88 };
89}
90
91// This is a forward declaration of CastInfoPointerUnionImpl
92// Refer to its definition below for further details
93template <typename... PTs> struct CastInfoPointerUnionImpl;
94/// A discriminated union of two or more pointer types, with the discriminator
95/// in the low bit of the pointer.
96///
97/// This implementation is extremely efficient in space due to leveraging the
98/// low bits of the pointer, while exposing a natural and type-safe API.
99///
100/// Common use patterns would be something like this:
101/// PointerUnion<int*, float*> P;
102/// P = (int*)0;
103/// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0"
104/// X = P.get<int*>(); // ok.
105/// Y = P.get<float*>(); // runtime assertion failure.
106/// Z = P.get<double*>(); // compile time failure.
107/// P = (float*)0;
108/// Y = P.get<float*>(); // ok.
109/// X = P.get<int*>(); // runtime assertion failure.
110/// PointerUnion<int*, int*> Q; // compile time failure.
111template <typename... PTs>
112class PointerUnion
113 : public pointer_union_detail::PointerUnionMembers<
114 PointerUnion<PTs...>,
115 PointerIntPair<
116 void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int,
117 pointer_union_detail::PointerUnionUIntTraits<PTs...>>,
118 0, PTs...> {
119 static_assert(TypesAreDistinct<PTs...>::value,
120 "PointerUnion alternative types cannot be repeated");
121 // The first type is special because we want to directly cast a pointer to a
122 // default-initialized union to a pointer to the first type. But we don't
123 // want PointerUnion to be a 'template <typename First, typename ...Rest>'
124 // because it's much more convenient to have a name for the whole pack. So
125 // split off the first type here.
126 using First = TypeAtIndex<0, PTs...>;
127 using Base = typename PointerUnion::PointerUnionMembers;
128
129 /// This is needed to give the CastInfo implementation below access
130 /// to protected members.
131 /// Refer to its definition for further details.
132 friend struct CastInfoPointerUnionImpl<PTs...>;
133
134public:
135 PointerUnion() = default;
136
137 PointerUnion(std::nullptr_t) : PointerUnion() {}
138 using Base::Base;
139
140 /// Test if the pointer held in the union is null, regardless of
141 /// which type it is.
142 bool isNull() const { return !this->Val.getPointer(); }
143
144 explicit operator bool() const { return !isNull(); }
145
146 // FIXME: Replace the uses of is(), get() and dyn_cast() with
147 // isa<T>, cast<T> and the llvm::dyn_cast<T>
148
149 /// Test if the Union currently holds the type matching T.
150 template <typename T> inline bool is() const { return isa<T>(*this); }
151
152 /// Returns the value of the specified pointer type.
153 ///
154 /// If the specified pointer type is incorrect, assert.
155 template <typename T> inline T get() const {
156 assert(isa<T>(*this) && "Invalid accessor called")(static_cast <bool> (isa<T>(*this) && "Invalid accessor called"
) ? void (0) : __assert_fail ("isa<T>(*this) && \"Invalid accessor called\""
, "llvm/include/llvm/ADT/PointerUnion.h", 156, __extension__ __PRETTY_FUNCTION__
))
;
157 return cast<T>(*this);
158 }
159
160 /// Returns the current pointer if it is of the specified pointer type,
161 /// otherwise returns null.
162 template <typename T> inline T dyn_cast() const {
163 return llvm::dyn_cast_if_present<T>(*this);
17
Calling 'dyn_cast_if_present<unsigned int *, llvm::PointerUnion<unsigned int *, clang::CodeGen::LValue *>>'
35
Returning from 'dyn_cast_if_present<unsigned int *, llvm::PointerUnion<unsigned int *, clang::CodeGen::LValue *>>'
36
Returning pointer, which participates in a condition later
41
Calling 'dyn_cast_if_present<unsigned int *, llvm::PointerUnion<unsigned int *, clang::CodeGen::LValue *>>'
51
Returning from 'dyn_cast_if_present<unsigned int *, llvm::PointerUnion<unsigned int *, clang::CodeGen::LValue *>>'
52
Returning null pointer, which participates in a condition later
164 }
165
166 /// If the union is set to the first pointer type get an address pointing to
167 /// it.
168 First const *getAddrOfPtr1() const {
169 return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
170 }
171
172 /// If the union is set to the first pointer type get an address pointing to
173 /// it.
174 First *getAddrOfPtr1() {
175 assert(isa<First>(*this) && "Val is not the first pointer")(static_cast <bool> (isa<First>(*this) &&
"Val is not the first pointer") ? void (0) : __assert_fail (
"isa<First>(*this) && \"Val is not the first pointer\""
, "llvm/include/llvm/ADT/PointerUnion.h", 175, __extension__ __PRETTY_FUNCTION__
))
;
176 assert((static_cast <bool> (PointerLikeTypeTraits<First>
::getAsVoidPointer(cast<First>(*this)) == this->Val.
getPointer() && "Can't get the address because PointerLikeTypeTraits changes the ptr"
) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\""
, "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__
))
177 PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) ==(static_cast <bool> (PointerLikeTypeTraits<First>
::getAsVoidPointer(cast<First>(*this)) == this->Val.
getPointer() && "Can't get the address because PointerLikeTypeTraits changes the ptr"
) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\""
, "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__
))
178 this->Val.getPointer() &&(static_cast <bool> (PointerLikeTypeTraits<First>
::getAsVoidPointer(cast<First>(*this)) == this->Val.
getPointer() && "Can't get the address because PointerLikeTypeTraits changes the ptr"
) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\""
, "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__
))
179 "Can't get the address because PointerLikeTypeTraits changes the ptr")(static_cast <bool> (PointerLikeTypeTraits<First>
::getAsVoidPointer(cast<First>(*this)) == this->Val.
getPointer() && "Can't get the address because PointerLikeTypeTraits changes the ptr"
) ? void (0) : __assert_fail ("PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) == this->Val.getPointer() && \"Can't get the address because PointerLikeTypeTraits changes the ptr\""
, "llvm/include/llvm/ADT/PointerUnion.h", 179, __extension__ __PRETTY_FUNCTION__
))
;
180 return const_cast<First *>(
181 reinterpret_cast<const First *>(this->Val.getAddrOfPointer()));
182 }
183
184 /// Assignment from nullptr which just clears the union.
185 const PointerUnion &operator=(std::nullptr_t) {
186 this->Val.initWithPointer(nullptr);
187 return *this;
188 }
189
190 /// Assignment from elements of the union.
191 using Base::operator=;
192
193 void *getOpaqueValue() const { return this->Val.getOpaqueValue(); }
194 static inline PointerUnion getFromOpaqueValue(void *VP) {
195 PointerUnion V;
196 V.Val = decltype(V.Val)::getFromOpaqueValue(VP);
197 return V;
198 }
199};
200
201template <typename ...PTs>
202bool operator==(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) {
203 return lhs.getOpaqueValue() == rhs.getOpaqueValue();
204}
205
206template <typename ...PTs>
207bool operator!=(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) {
208 return lhs.getOpaqueValue() != rhs.getOpaqueValue();
209}
210
211template <typename ...PTs>
212bool operator<(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) {
213 return lhs.getOpaqueValue() < rhs.getOpaqueValue();
214}
215
216/// We can't (at least, at this moment with C++14) declare CastInfo
217/// as a friend of PointerUnion like this:
218/// ```
219/// template<typename To>
220/// friend struct CastInfo<To, PointerUnion<PTs...>>;
221/// ```
222/// The compiler complains 'Partial specialization cannot be declared as a
223/// friend'.
224/// So we define this struct to be a bridge between CastInfo and
225/// PointerUnion.
226template <typename... PTs> struct CastInfoPointerUnionImpl {
227 using From = PointerUnion<PTs...>;
228
229 template <typename To> static inline bool isPossible(From &F) {
230 return F.Val.getInt() == FirstIndexOfType<To, PTs...>::value;
231 }
232
233 template <typename To> static To doCast(From &F) {
234 assert(isPossible<To>(F) && "cast to an incompatible type !")(static_cast <bool> (isPossible<To>(F) &&
"cast to an incompatible type !") ? void (0) : __assert_fail
("isPossible<To>(F) && \"cast to an incompatible type !\""
, "llvm/include/llvm/ADT/PointerUnion.h", 234, __extension__ __PRETTY_FUNCTION__
))
;
25
'?' condition is true
235 return PointerLikeTypeTraits<To>::getFromVoidPointer(F.Val.getPointer());
26
Returning pointer, which participates in a condition later
236 }
237};
238
239// Specialization of CastInfo for PointerUnion
240template <typename To, typename... PTs>
241struct CastInfo<To, PointerUnion<PTs...>>
242 : public DefaultDoCastIfPossible<To, PointerUnion<PTs...>,
243 CastInfo<To, PointerUnion<PTs...>>> {
244 using From = PointerUnion<PTs...>;
245 using Impl = CastInfoPointerUnionImpl<PTs...>;
246
247 static inline bool isPossible(From &f) {
248 return Impl::template isPossible<To>(f);
249 }
250
251 static To doCast(From &f) { return Impl::template doCast<To>(f); }
24
Calling 'CastInfoPointerUnionImpl::doCast'
27
Returning from 'CastInfoPointerUnionImpl::doCast'
28
Returning pointer, which participates in a condition later
252
253 static inline To castFailed() { return To(); }
46
Returning null pointer, which participates in a condition later
254};
255
256template <typename To, typename... PTs>
257struct CastInfo<To, const PointerUnion<PTs...>>
258 : public ConstStrippingForwardingCast<To, const PointerUnion<PTs...>,
259 CastInfo<To, PointerUnion<PTs...>>> {
260};
261
262// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
263// # low bits available = min(PT1bits,PT2bits)-1.
264template <typename ...PTs>
265struct PointerLikeTypeTraits<PointerUnion<PTs...>> {
266 static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) {
267 return P.getOpaqueValue();
268 }
269
270 static inline PointerUnion<PTs...> getFromVoidPointer(void *P) {
271 return PointerUnion<PTs...>::getFromOpaqueValue(P);
272 }
273
274 // The number of bits available are the min of the pointer types minus the
275 // bits needed for the discriminator.
276 static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<decltype(
277 PointerUnion<PTs...>::Val)>::NumLowBitsAvailable;
278};
279
280// Teach DenseMap how to use PointerUnions as keys.
281template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> {
282 using Union = PointerUnion<PTs...>;
283 using FirstInfo =
284 DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>;
285
286 static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); }
287
288 static inline Union getTombstoneKey() {
289 return Union(FirstInfo::getTombstoneKey());
290 }
291
292 static unsigned getHashValue(const Union &UnionVal) {
293 intptr_t key = (intptr_t)UnionVal.getOpaqueValue();
294 return DenseMapInfo<intptr_t>::getHashValue(key);
295 }
296
297 static bool isEqual(const Union &LHS, const Union &RHS) {
298 return LHS == RHS;
299 }
300};
301
302} // end namespace llvm
303
304#endif // LLVM_ADT_POINTERUNION_H

/build/source/llvm/include/llvm/Support/Casting.h

1//===- llvm/Support/Casting.h - Allow flexible, checked, casts --*- C++ -*-===//
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 file defines the isa<X>(), cast<X>(), dyn_cast<X>(),
10// cast_if_present<X>(), and dyn_cast_if_present<X>() templates.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_SUPPORT_CASTING_H
15#define LLVM_SUPPORT_CASTING_H
16
17#include "llvm/Support/Compiler.h"
18#include "llvm/Support/type_traits.h"
19#include <cassert>
20#include <memory>
21#include <optional>
22#include <type_traits>
23
24namespace llvm {
25
26//===----------------------------------------------------------------------===//
27// simplify_type
28//===----------------------------------------------------------------------===//
29
30/// Define a template that can be specialized by smart pointers to reflect the
31/// fact that they are automatically dereferenced, and are not involved with the
32/// template selection process... the default implementation is a noop.
33// TODO: rename this and/or replace it with other cast traits.
34template <typename From> struct simplify_type {
35 using SimpleType = From; // The real type this represents...
36
37 // An accessor to get the real value...
38 static SimpleType &getSimplifiedValue(From &Val) { return Val; }
39};
40
41template <typename From> struct simplify_type<const From> {
42 using NonConstSimpleType = typename simplify_type<From>::SimpleType;
43 using SimpleType = typename add_const_past_pointer<NonConstSimpleType>::type;
44 using RetType =
45 typename add_lvalue_reference_if_not_pointer<SimpleType>::type;
46
47 static RetType getSimplifiedValue(const From &Val) {
48 return simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val));
49 }
50};
51
52// TODO: add this namespace once everyone is switched to using the new
53// interface.
54// namespace detail {
55
56//===----------------------------------------------------------------------===//
57// isa_impl
58//===----------------------------------------------------------------------===//
59
60// The core of the implementation of isa<X> is here; To and From should be
61// the names of classes. This template can be specialized to customize the
62// implementation of isa<> without rewriting it from scratch.
63template <typename To, typename From, typename Enabler = void> struct isa_impl {
64 static inline bool doit(const From &Val) { return To::classof(&Val); }
65};
66
67// Always allow upcasts, and perform no dynamic check for them.
68template <typename To, typename From>
69struct isa_impl<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> {
70 static inline bool doit(const From &) { return true; }
71};
72
73template <typename To, typename From> struct isa_impl_cl {
74 static inline bool doit(const From &Val) {
75 return isa_impl<To, From>::doit(Val);
76 }
77};
78
79template <typename To, typename From> struct isa_impl_cl<To, const From> {
80 static inline bool doit(const From &Val) {
81 return isa_impl<To, From>::doit(Val);
82 }
83};
84
85template <typename To, typename From>
86struct isa_impl_cl<To, const std::unique_ptr<From>> {
87 static inline bool doit(const std::unique_ptr<From> &Val) {
88 assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer"
) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\""
, "llvm/include/llvm/Support/Casting.h", 88, __extension__ __PRETTY_FUNCTION__
))
;
89 return isa_impl_cl<To, From>::doit(*Val);
90 }
91};
92
93template <typename To, typename From> struct isa_impl_cl<To, From *> {
94 static inline bool doit(const From *Val) {
95 assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer"
) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\""
, "llvm/include/llvm/Support/Casting.h", 95, __extension__ __PRETTY_FUNCTION__
))
;
96 return isa_impl<To, From>::doit(*Val);
97 }
98};
99
100template <typename To, typename From> struct isa_impl_cl<To, From *const> {
101 static inline bool doit(const From *Val) {
102 assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer"
) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\""
, "llvm/include/llvm/Support/Casting.h", 102, __extension__ __PRETTY_FUNCTION__
))
;
103 return isa_impl<To, From>::doit(*Val);
104 }
105};
106
107template <typename To, typename From> struct isa_impl_cl<To, const From *> {
108 static inline bool doit(const From *Val) {
109 assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer"
) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\""
, "llvm/include/llvm/Support/Casting.h", 109, __extension__ __PRETTY_FUNCTION__
))
;
110 return isa_impl<To, From>::doit(*Val);
111 }
112};
113
114template <typename To, typename From>
115struct isa_impl_cl<To, const From *const> {
116 static inline bool doit(const From *Val) {
117 assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer"
) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\""
, "llvm/include/llvm/Support/Casting.h", 117, __extension__ __PRETTY_FUNCTION__
))
;
118 return isa_impl<To, From>::doit(*Val);
119 }
120};
121
122template <typename To, typename From, typename SimpleFrom>
123struct isa_impl_wrap {
124 // When From != SimplifiedType, we can simplify the type some more by using
125 // the simplify_type template.
126 static bool doit(const From &Val) {
127 return isa_impl_wrap<To, SimpleFrom,
128 typename simplify_type<SimpleFrom>::SimpleType>::
129 doit(simplify_type<const From>::getSimplifiedValue(Val));
130 }
131};
132
133template <typename To, typename FromTy>
134struct isa_impl_wrap<To, FromTy, FromTy> {
135 // When From == SimpleType, we are as simple as we are going to get.
136 static bool doit(const FromTy &Val) {
137 return isa_impl_cl<To, FromTy>::doit(Val);
138 }
139};
140
141//===----------------------------------------------------------------------===//
142// cast_retty + cast_retty_impl
143//===----------------------------------------------------------------------===//
144
145template <class To, class From> struct cast_retty;
146
147// Calculate what type the 'cast' function should return, based on a requested
148// type of To and a source type of From.
149template <class To, class From> struct cast_retty_impl {
150 using ret_type = To &; // Normal case, return Ty&
151};
152template <class To, class From> struct cast_retty_impl<To, const From> {
153 using ret_type = const To &; // Normal case, return Ty&
154};
155
156template <class To, class From> struct cast_retty_impl<To, From *> {
157 using ret_type = To *; // Pointer arg case, return Ty*
158};
159
160template <class To, class From> struct cast_retty_impl<To, const From *> {
161 using ret_type = const To *; // Constant pointer arg case, return const Ty*
162};
163
164template <class To, class From> struct cast_retty_impl<To, const From *const> {
165 using ret_type = const To *; // Constant pointer arg case, return const Ty*
166};
167
168template <class To, class From>
169struct cast_retty_impl<To, std::unique_ptr<From>> {
170private:
171 using PointerType = typename cast_retty_impl<To, From *>::ret_type;
172 using ResultType = std::remove_pointer_t<PointerType>;
173
174public:
175 using ret_type = std::unique_ptr<ResultType>;
176};
177
178template <class To, class From, class SimpleFrom> struct cast_retty_wrap {
179 // When the simplified type and the from type are not the same, use the type
180 // simplifier to reduce the type, then reuse cast_retty_impl to get the
181 // resultant type.
182 using ret_type = typename cast_retty<To, SimpleFrom>::ret_type;
183};
184
185template <class To, class FromTy> struct cast_retty_wrap<To, FromTy, FromTy> {
186 // When the simplified type is equal to the from type, use it directly.
187 using ret_type = typename cast_retty_impl<To, FromTy>::ret_type;
188};
189
190template <class To, class From> struct cast_retty {
191 using ret_type = typename cast_retty_wrap<
192 To, From, typename simplify_type<From>::SimpleType>::ret_type;
193};
194
195//===----------------------------------------------------------------------===//
196// cast_convert_val
197//===----------------------------------------------------------------------===//
198
199// Ensure the non-simple values are converted using the simplify_type template
200// that may be specialized by smart pointers...
201//
202template <class To, class From, class SimpleFrom> struct cast_convert_val {
203 // This is not a simple type, use the template to simplify it...
204 static typename cast_retty<To, From>::ret_type doit(const From &Val) {
205 return cast_convert_val<To, SimpleFrom,
206 typename simplify_type<SimpleFrom>::SimpleType>::
207 doit(simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val)));
208 }
209};
210
211template <class To, class FromTy> struct cast_convert_val<To, FromTy, FromTy> {
212 // If it's a reference, switch to a pointer to do the cast and then deref it.
213 static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) {
214 return *(std::remove_reference_t<typename cast_retty<To, FromTy>::ret_type>
215 *)&const_cast<FromTy &>(Val);
216 }
217};
218
219template <class To, class FromTy>
220struct cast_convert_val<To, FromTy *, FromTy *> {
221 // If it's a pointer, we can use c-style casting directly.
222 static typename cast_retty<To, FromTy *>::ret_type doit(const FromTy *Val) {
223 return (typename cast_retty<To, FromTy *>::ret_type) const_cast<FromTy *>(
224 Val);
225 }
226};
227
228//===----------------------------------------------------------------------===//
229// is_simple_type
230//===----------------------------------------------------------------------===//
231
232template <class X> struct is_simple_type {
233 static const bool value =
234 std::is_same_v<X, typename simplify_type<X>::SimpleType>;
235};
236
237// } // namespace detail
238
239//===----------------------------------------------------------------------===//
240// CastIsPossible
241//===----------------------------------------------------------------------===//
242
243/// This struct provides a way to check if a given cast is possible. It provides
244/// a static function called isPossible that is used to check if a cast can be
245/// performed. It should be overridden like this:
246///
247/// template<> struct CastIsPossible<foo, bar> {
248/// static inline bool isPossible(const bar &b) {
249/// return bar.isFoo();
250/// }
251/// };
252template <typename To, typename From, typename Enable = void>
253struct CastIsPossible {
254 static inline bool isPossible(const From &f) {
255 return isa_impl_wrap<
256 To, const From,
257 typename simplify_type<const From>::SimpleType>::doit(f);
258 }
259};
260
261// Needed for optional unwrapping. This could be implemented with isa_impl, but
262// we want to implement things in the new method and move old implementations
263// over. In fact, some of the isa_impl templates should be moved over to
264// CastIsPossible.
265template <typename To, typename From>
266struct CastIsPossible<To, std::optional<From>> {
267 static inline bool isPossible(const std::optional<From> &f) {
268 assert(f && "CastIsPossible::isPossible called on a nullopt!")(static_cast <bool> (f && "CastIsPossible::isPossible called on a nullopt!"
) ? void (0) : __assert_fail ("f && \"CastIsPossible::isPossible called on a nullopt!\""
, "llvm/include/llvm/Support/Casting.h", 268, __extension__ __PRETTY_FUNCTION__
))
;
269 return isa_impl_wrap<
270 To, const From,
271 typename simplify_type<const From>::SimpleType>::doit(*f);
272 }
273};
274
275/// Upcasting (from derived to base) and casting from a type to itself should
276/// always be possible.
277template <typename To, typename From>
278struct CastIsPossible<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> {
279 static inline bool isPossible(const From &f) { return true; }
280};
281
282//===----------------------------------------------------------------------===//
283// Cast traits
284//===----------------------------------------------------------------------===//
285
286/// All of these cast traits are meant to be implementations for useful casts
287/// that users may want to use that are outside the standard behavior. An
288/// example of how to use a special cast called `CastTrait` is:
289///
290/// template<> struct CastInfo<foo, bar> : public CastTrait<foo, bar> {};
291///
292/// Essentially, if your use case falls directly into one of the use cases
293/// supported by a given cast trait, simply inherit your special CastInfo
294/// directly from one of these to avoid having to reimplement the boilerplate
295/// `isPossible/castFailed/doCast/doCastIfPossible`. A cast trait can also
296/// provide a subset of those functions.
297
298/// This cast trait just provides castFailed for the specified `To` type to make
299/// CastInfo specializations more declarative. In order to use this, the target
300/// result type must be `To` and `To` must be constructible from `nullptr`.
301template <typename To> struct NullableValueCastFailed {
302 static To castFailed() { return To(nullptr); }
303};
304
305/// This cast trait just provides the default implementation of doCastIfPossible
306/// to make CastInfo specializations more declarative. The `Derived` template
307/// parameter *must* be provided for forwarding castFailed and doCast.
308template <typename To, typename From, typename Derived>
309struct DefaultDoCastIfPossible {
310 static To doCastIfPossible(From f) {
311 if (!Derived::isPossible(f))
22
Taking false branch
312 return Derived::castFailed();
313 return Derived::doCast(f);
23
Calling 'CastInfo::doCast'
29
Returning from 'CastInfo::doCast'
30
Returning pointer, which participates in a condition later
314 }
315};
316
317namespace detail {
318/// A helper to derive the type to use with `Self` for cast traits, when the
319/// provided CRTP derived type is allowed to be void.
320template <typename OptionalDerived, typename Default>
321using SelfType = std::conditional_t<std::is_same_v<OptionalDerived, void>,
322 Default, OptionalDerived>;
323} // namespace detail
324
325/// This cast trait provides casting for the specific case of casting to a
326/// value-typed object from a pointer-typed object. Note that `To` must be
327/// nullable/constructible from a pointer to `From` to use this cast.
328template <typename To, typename From, typename Derived = void>
329struct ValueFromPointerCast
330 : public CastIsPossible<To, From *>,
331 public NullableValueCastFailed<To>,
332 public DefaultDoCastIfPossible<
333 To, From *,
334 detail::SelfType<Derived, ValueFromPointerCast<To, From>>> {
335 static inline To doCast(From *f) { return To(f); }
336};
337
338/// This cast trait provides std::unique_ptr casting. It has the semantics of
339/// moving the contents of the input unique_ptr into the output unique_ptr
340/// during the cast. It's also a good example of how to implement a move-only
341/// cast.
342template <typename To, typename From, typename Derived = void>
343struct UniquePtrCast : public CastIsPossible<To, From *> {
344 using Self = detail::SelfType<Derived, UniquePtrCast<To, From>>;
345 using CastResultType = std::unique_ptr<
346 std::remove_reference_t<typename cast_retty<To, From>::ret_type>>;
347
348 static inline CastResultType doCast(std::unique_ptr<From> &&f) {
349 return CastResultType((typename CastResultType::element_type *)f.release());
350 }
351
352 static inline CastResultType castFailed() { return CastResultType(nullptr); }
353
354 static inline CastResultType doCastIfPossible(std::unique_ptr<From> &&f) {
355 if (!Self::isPossible(f))
356 return castFailed();
357 return doCast(f);
358 }
359};
360
361/// This cast trait provides std::optional<T> casting. This means that if you
362/// have a value type, you can cast it to another value type and have dyn_cast
363/// return an std::optional<T>.
364template <typename To, typename From, typename Derived = void>
365struct OptionalValueCast
366 : public CastIsPossible<To, From>,
367 public DefaultDoCastIfPossible<
368 std::optional<To>, From,
369 detail::SelfType<Derived, OptionalValueCast<To, From>>> {
370 static inline std::optional<To> castFailed() { return std::optional<To>{}; }
371
372 static inline std::optional<To> doCast(const From &f) { return To(f); }
373};
374
375/// Provides a cast trait that strips `const` from types to make it easier to
376/// implement a const-version of a non-const cast. It just removes boilerplate
377/// and reduces the amount of code you as the user need to implement. You can
378/// use it like this:
379///
380/// template<> struct CastInfo<foo, bar> {
381/// ...verbose implementation...
382/// };
383///
384/// template<> struct CastInfo<foo, const bar> : public
385/// ConstStrippingForwardingCast<foo, const bar, CastInfo<foo, bar>> {};
386///
387template <typename To, typename From, typename ForwardTo>
388struct ConstStrippingForwardingCast {
389 // Remove the pointer if it exists, then we can get rid of consts/volatiles.
390 using DecayedFrom = std::remove_cv_t<std::remove_pointer_t<From>>;
391 // Now if it's a pointer, add it back. Otherwise, we want a ref.
392 using NonConstFrom =
393 std::conditional_t<std::is_pointer_v<From>, DecayedFrom *, DecayedFrom &>;
394
395 static inline bool isPossible(const From &f) {
396 return ForwardTo::isPossible(const_cast<NonConstFrom>(f));
397 }
398
399 static inline decltype(auto) castFailed() { return ForwardTo::castFailed(); }
45
Calling 'CastInfo::castFailed'
47
Returning from 'CastInfo::castFailed'
48
Returning null pointer, which participates in a condition later
400
401 static inline decltype(auto) doCast(const From &f) {
402 return ForwardTo::doCast(const_cast<NonConstFrom>(f));
403 }
404
405 static inline decltype(auto) doCastIfPossible(const From &f) {
406 return ForwardTo::doCastIfPossible(const_cast<NonConstFrom>(f));
21
Calling 'DefaultDoCastIfPossible::doCastIfPossible'
31
Returning from 'DefaultDoCastIfPossible::doCastIfPossible'
32
Returning pointer, which participates in a condition later
407 }
408};
409
410/// Provides a cast trait that uses a defined pointer to pointer cast as a base
411/// for reference-to-reference casts. Note that it does not provide castFailed
412/// and doCastIfPossible because a pointer-to-pointer cast would likely just
413/// return `nullptr` which could cause nullptr dereference. You can use it like
414/// this:
415///
416/// template <> struct CastInfo<foo, bar *> { ... verbose implementation... };
417///
418/// template <>
419/// struct CastInfo<foo, bar>
420/// : public ForwardToPointerCast<foo, bar, CastInfo<foo, bar *>> {};
421///
422template <typename To, typename From, typename ForwardTo>
423struct ForwardToPointerCast {
424 static inline bool isPossible(const From &f) {
425 return ForwardTo::isPossible(&f);
426 }
427
428 static inline decltype(auto) doCast(const From &f) {
429 return *ForwardTo::doCast(&f);
430 }
431};
432
433//===----------------------------------------------------------------------===//
434// CastInfo
435//===----------------------------------------------------------------------===//
436
437/// This struct provides a method for customizing the way a cast is performed.
438/// It inherits from CastIsPossible, to support the case of declaring many
439/// CastIsPossible specializations without having to specialize the full
440/// CastInfo.
441///
442/// In order to specialize different behaviors, specify different functions in
443/// your CastInfo specialization.
444/// For isa<> customization, provide:
445///
446/// `static bool isPossible(const From &f)`
447///
448/// For cast<> customization, provide:
449///
450/// `static To doCast(const From &f)`
451///
452/// For dyn_cast<> and the *_if_present<> variants' customization, provide:
453///
454/// `static To castFailed()` and `static To doCastIfPossible(const From &f)`
455///
456/// Your specialization might look something like this:
457///
458/// template<> struct CastInfo<foo, bar> : public CastIsPossible<foo, bar> {
459/// static inline foo doCast(const bar &b) {
460/// return foo(const_cast<bar &>(b));
461/// }
462/// static inline foo castFailed() { return foo(); }
463/// static inline foo doCastIfPossible(const bar &b) {
464/// if (!CastInfo<foo, bar>::isPossible(b))
465/// return castFailed();
466/// return doCast(b);
467/// }
468/// };
469
470// The default implementations of CastInfo don't use cast traits for now because
471// we need to specify types all over the place due to the current expected
472// casting behavior and the way cast_retty works. New use cases can and should
473// take advantage of the cast traits whenever possible!
474
475template <typename To, typename From, typename Enable = void>
476struct CastInfo : public CastIsPossible<To, From> {
477 using Self = CastInfo<To, From, Enable>;
478
479 using CastReturnType = typename cast_retty<To, From>::ret_type;
480
481 static inline CastReturnType doCast(const From &f) {
482 return cast_convert_val<
483 To, From,
484 typename simplify_type<From>::SimpleType>::doit(const_cast<From &>(f));
485 }
486
487 // This assumes that you can construct the cast return type from `nullptr`.
488 // This is largely to support legacy use cases - if you don't want this
489 // behavior you should specialize CastInfo for your use case.
490 static inline CastReturnType castFailed() { return CastReturnType(nullptr); }
491
492 static inline CastReturnType doCastIfPossible(const From &f) {
493 if (!Self::isPossible(f))
494 return castFailed();
495 return doCast(f);
496 }
497};
498
499/// This struct provides an overload for CastInfo where From has simplify_type
500/// defined. This simply forwards to the appropriate CastInfo with the
501/// simplified type/value, so you don't have to implement both.
502template <typename To, typename From>
503struct CastInfo<To, From, std::enable_if_t<!is_simple_type<From>::value>> {
504 using Self = CastInfo<To, From>;
505 using SimpleFrom = typename simplify_type<From>::SimpleType;
506 using SimplifiedSelf = CastInfo<To, SimpleFrom>;
507
508 static inline bool isPossible(From &f) {
509 return SimplifiedSelf::isPossible(
510 simplify_type<From>::getSimplifiedValue(f));
511 }
512
513 static inline decltype(auto) doCast(From &f) {
514 return SimplifiedSelf::doCast(simplify_type<From>::getSimplifiedValue(f));
515 }
516
517 static inline decltype(auto) castFailed() {
518 return SimplifiedSelf::castFailed();
519 }
520
521 static inline decltype(auto) doCastIfPossible(From &f) {
522 return SimplifiedSelf::doCastIfPossible(
523 simplify_type<From>::getSimplifiedValue(f));
524 }
525};
526
527//===----------------------------------------------------------------------===//
528// Pre-specialized CastInfo
529//===----------------------------------------------------------------------===//
530
531/// Provide a CastInfo specialized for std::unique_ptr.
532template <typename To, typename From>
533struct CastInfo<To, std::unique_ptr<From>> : public UniquePtrCast<To, From> {};
534
535/// Provide a CastInfo specialized for std::optional<From>. It's assumed that if
536/// the input is std::optional<From> that the output can be std::optional<To>.
537/// If that's not the case, specialize CastInfo for your use case.
538template <typename To, typename From>
539struct CastInfo<To, std::optional<From>> : public OptionalValueCast<To, From> {
540};
541
542/// isa<X> - Return true if the parameter to the template is an instance of one
543/// of the template type arguments. Used like this:
544///
545/// if (isa<Type>(myVal)) { ... }
546/// if (isa<Type0, Type1, Type2>(myVal)) { ... }
547template <typename To, typename From>
548[[nodiscard]] inline bool isa(const From &Val) {
549 return CastInfo<To, const From>::isPossible(Val);
550}
551
552template <typename First, typename Second, typename... Rest, typename From>
553[[nodiscard]] inline bool isa(const From &Val) {
554 return isa<First>(Val) || isa<Second, Rest...>(Val);
555}
556
557/// cast<X> - Return the argument parameter cast to the specified type. This
558/// casting operator asserts that the type is correct, so it does not return
559/// null on failure. It does not allow a null argument (use cast_if_present for
560/// that). It is typically used like this:
561///
562/// cast<Instruction>(myVal)->getParent()
563
564template <typename To, typename From>
565[[nodiscard]] inline decltype(auto) cast(const From &Val) {
566 assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!"
) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\""
, "llvm/include/llvm/Support/Casting.h", 566, __extension__ __PRETTY_FUNCTION__
))
;
567 return CastInfo<To, const From>::doCast(Val);
568}
569
570template <typename To, typename From>
571[[nodiscard]] inline decltype(auto) cast(From &Val) {
572 assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!"
) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\""
, "llvm/include/llvm/Support/Casting.h", 572, __extension__ __PRETTY_FUNCTION__
))
;
573 return CastInfo<To, From>::doCast(Val);
574}
575
576template <typename To, typename From>
577[[nodiscard]] inline decltype(auto) cast(From *Val) {
578 assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!"
) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\""
, "llvm/include/llvm/Support/Casting.h", 578, __extension__ __PRETTY_FUNCTION__
))
;
579 return CastInfo<To, From *>::doCast(Val);
580}
581
582template <typename To, typename From>
583[[nodiscard]] inline decltype(auto) cast(std::unique_ptr<From> &&Val) {
584 assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!"
) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\""
, "llvm/include/llvm/Support/Casting.h", 584, __extension__ __PRETTY_FUNCTION__
))
;
585 return CastInfo<To, std::unique_ptr<From>>::doCast(std::move(Val));
586}
587
588//===----------------------------------------------------------------------===//
589// ValueIsPresent
590//===----------------------------------------------------------------------===//
591
592template <typename T>
593constexpr bool IsNullable =
594 std::is_pointer_v<T> || std::is_constructible_v<T, std::nullptr_t>;
595
596/// ValueIsPresent provides a way to check if a value is, well, present. For
597/// pointers, this is the equivalent of checking against nullptr, for Optionals
598/// this is the equivalent of checking hasValue(). It also provides a method for
599/// unwrapping a value (think calling .value() on an optional).
600
601// Generic values can't *not* be present.
602template <typename T, typename Enable = void> struct ValueIsPresent {
603 using UnwrappedType = T;
604 static inline bool isPresent(const T &t) { return true; }
605 static inline decltype(auto) unwrapValue(T &t) { return t; }
606};
607
608// Optional provides its own way to check if something is present.
609template <typename T> struct ValueIsPresent<std::optional<T>> {
610 using UnwrappedType = T;
611 static inline bool isPresent(const std::optional<T> &t) {
612 return t.has_value();
613 }
614 static inline decltype(auto) unwrapValue(std::optional<T> &t) { return *t; }
615};
616
617// If something is "nullable" then we just compare it to nullptr to see if it
618// exists.
619template <typename T>
620struct ValueIsPresent<T, std::enable_if_t<IsNullable<T>>> {
621 using UnwrappedType = T;
622 static inline bool isPresent(const T &t) { return t != T(nullptr); }
623 static inline decltype(auto) unwrapValue(T &t) { return t; }
624};
625
626namespace detail {
627// Convenience function we can use to check if a value is present. Because of
628// simplify_type, we have to call it on the simplified type for now.
629template <typename T> inline bool isPresent(const T &t) {
630 return ValueIsPresent<typename simplify_type<T>::SimpleType>::isPresent(
631 simplify_type<T>::getSimplifiedValue(const_cast<T &>(t)));
632}
633
634// Convenience function we can use to unwrap a value.
635template <typename T> inline decltype(auto) unwrapValue(T &t) {
636 return ValueIsPresent<T>::unwrapValue(t);
637}
638} // namespace detail
639
640/// dyn_cast<X> - Return the argument parameter cast to the specified type. This
641/// casting operator returns null if the argument is of the wrong type, so it
642/// can be used to test for a type as well as cast if successful. The value
643/// passed in must be present, if not, use dyn_cast_if_present. This should be
644/// used in the context of an if statement like this:
645///
646/// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
647
648template <typename To, typename From>
649[[nodiscard]] inline decltype(auto) dyn_cast(const From &Val) {
650 assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value"
) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\""
, "llvm/include/llvm/Support/Casting.h", 650, __extension__ __PRETTY_FUNCTION__
))
;
651 return CastInfo<To, const From>::doCastIfPossible(Val);
652}
653
654template <typename To, typename From>
655[[nodiscard]] inline decltype(auto) dyn_cast(From &Val) {
656 assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value"
) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\""
, "llvm/include/llvm/Support/Casting.h", 656, __extension__ __PRETTY_FUNCTION__
))
;
657 return CastInfo<To, From>::doCastIfPossible(Val);
658}
659
660template <typename To, typename From>
661[[nodiscard]] inline decltype(auto) dyn_cast(From *Val) {
662 assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value"
) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\""
, "llvm/include/llvm/Support/Casting.h", 662, __extension__ __PRETTY_FUNCTION__
))
;
663 return CastInfo<To, From *>::doCastIfPossible(Val);
664}
665
666template <typename To, typename From>
667[[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) {
668 assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value"
) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\""
, "llvm/include/llvm/Support/Casting.h", 668, __extension__ __PRETTY_FUNCTION__
))
;
669 return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(
670 std::forward<std::unique_ptr<From> &&>(Val));
671}
672
673/// isa_and_present<X> - Functionally identical to isa, except that a null value
674/// is accepted.
675template <typename... X, class Y>
676[[nodiscard]] inline bool isa_and_present(const Y &Val) {
677 if (!detail::isPresent(Val))
678 return false;
679 return isa<X...>(Val);
680}
681
682template <typename... X, class Y>
683[[nodiscard]] inline bool isa_and_nonnull(const Y &Val) {
684 return isa_and_present<X...>(Val);
685}
686
687/// cast_if_present<X> - Functionally identical to cast, except that a null
688/// value is accepted.
689template <class X, class Y>
690[[nodiscard]] inline auto cast_if_present(const Y &Val) {
691 if (!detail::isPresent(Val))
692 return CastInfo<X, const Y>::castFailed();
693 assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!"
) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\""
, "llvm/include/llvm/Support/Casting.h", 693, __extension__ __PRETTY_FUNCTION__
))
;
694 return cast<X>(detail::unwrapValue(Val));
695}
696
697template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y &Val) {
698 if (!detail::isPresent(Val))
699 return CastInfo<X, Y>::castFailed();
700 assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!"
) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\""
, "llvm/include/llvm/Support/Casting.h", 700, __extension__ __PRETTY_FUNCTION__
))
;
701 return cast<X>(detail::unwrapValue(Val));
702}
703
704template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y *Val) {
705 if (!detail::isPresent(Val))
706 return CastInfo<X, Y *>::castFailed();
707 assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!"
) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\""
, "llvm/include/llvm/Support/Casting.h", 707, __extension__ __PRETTY_FUNCTION__
))
;
708 return cast<X>(detail::unwrapValue(Val));
709}
710
711template <class X, class Y>
712[[nodiscard]] inline auto cast_if_present(std::unique_ptr<Y> &&Val) {
713 if (!detail::isPresent(Val))
714 return UniquePtrCast<X, Y>::castFailed();
715 return UniquePtrCast<X, Y>::doCast(std::move(Val));
716}
717
718// Provide a forwarding from cast_or_null to cast_if_present for current
719// users. This is deprecated and will be removed in a future patch, use
720// cast_if_present instead.
721template <class X, class Y> auto cast_or_null(const Y &Val) {
722 return cast_if_present<X>(Val);
723}
724
725template <class X, class Y> auto cast_or_null(Y &Val) {
726 return cast_if_present<X>(Val);
727}
728
729template <class X, class Y> auto cast_or_null(Y *Val) {
730 return cast_if_present<X>(Val);
731}
732
733template <class X, class Y> auto cast_or_null(std::unique_ptr<Y> &&Val) {
734 return cast_if_present<X>(std::move(Val));
735}
736
737/// dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a
738/// null (or none in the case of optionals) value is accepted.
739template <class X, class Y> auto dyn_cast_if_present(const Y &Val) {
740 if (!detail::isPresent(Val))
18
Assuming the condition is false
19
Taking false branch
42
Assuming the condition is true
43
Taking true branch
741 return CastInfo<X, const Y>::castFailed();
44
Calling 'ConstStrippingForwardingCast::castFailed'
49
Returning from 'ConstStrippingForwardingCast::castFailed'
50
Returning null pointer, which participates in a condition later
742 return CastInfo<X, const Y>::doCastIfPossible(detail::unwrapValue(Val));
20
Calling 'ConstStrippingForwardingCast::doCastIfPossible'
33
Returning from 'ConstStrippingForwardingCast::doCastIfPossible'
34
Returning pointer, which participates in a condition later
743}
744
745template <class X, class Y> auto dyn_cast_if_present(Y &Val) {
746 if (!detail::isPresent(Val))
747 return CastInfo<X, Y>::castFailed();
748 return CastInfo<X, Y>::doCastIfPossible(detail::unwrapValue(Val));
749}
750
751template <class X, class Y> auto dyn_cast_if_present(Y *Val) {
752 if (!detail::isPresent(Val))
753 return CastInfo<X, Y *>::castFailed();
754 return CastInfo<X, Y *>::doCastIfPossible(detail::unwrapValue(Val));
755}
756
757// Forwards to dyn_cast_if_present to avoid breaking current users. This is
758// deprecated and will be removed in a future patch, use
759// cast_if_present instead.
760template <class X, class Y> auto dyn_cast_or_null(const Y &Val) {
761 return dyn_cast_if_present<X>(Val);
762}
763
764template <class X, class Y> auto dyn_cast_or_null(Y &Val) {
765 return dyn_cast_if_present<X>(Val);
766}
767
768template <class X, class Y> auto dyn_cast_or_null(Y *Val) {
769 return dyn_cast_if_present<X>(Val);
770}
771
772/// unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>,
773/// taking ownership of the input pointer iff isa<X>(Val) is true. If the
774/// cast is successful, From refers to nullptr on exit and the casted value
775/// is returned. If the cast is unsuccessful, the function returns nullptr
776/// and From is unchanged.
777template <class X, class Y>
778[[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
779unique_dyn_cast(std::unique_ptr<Y> &Val) {
780 if (!isa<X>(Val))
781 return nullptr;
782 return cast<X>(std::move(Val));
783}
784
785template <class X, class Y>
786[[nodiscard]] inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) {
787 return unique_dyn_cast<X, Y>(Val);
788}
789
790// unique_dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast,
791// except that a null value is accepted.
792template <class X, class Y>
793[[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
794unique_dyn_cast_or_null(std::unique_ptr<Y> &Val) {
795 if (!Val)
796 return nullptr;
797 return unique_dyn_cast<X, Y>(Val);
798}
799
800template <class X, class Y>
801[[nodiscard]] inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) {
802 return unique_dyn_cast_or_null<X, Y>(Val);
803}
804
805} // end namespace llvm
806
807#endif // LLVM_SUPPORT_CASTING_H