Bug Summary

File:clang/lib/CodeGen/CGOpenMPRuntime.cpp
Warning:line 8543, column 15
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 -disable-llvm-verifier -discard-value-names -main-file-name CGOpenMPRuntime.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-12/lib/clang/12.0.0 -D CLANG_VENDOR="Debian " -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/build-llvm/tools/clang/lib/CodeGen -I /build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen -I /build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/include -I /build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/build-llvm/include -I /build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/llvm/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-12/lib/clang/12.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/build-llvm/tools/clang/lib/CodeGen -fdebug-prefix-map=/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191=. -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -o /tmp/scan-build-2020-11-21-121427-42170-1 -x c++ /build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp

/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/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 "clang/AST/Attr.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/OpenMPClause.h"
21#include "clang/AST/StmtOpenMP.h"
22#include "clang/AST/StmtVisitor.h"
23#include "clang/Basic/BitmaskEnum.h"
24#include "clang/Basic/FileManager.h"
25#include "clang/Basic/OpenMPKinds.h"
26#include "clang/Basic/SourceManager.h"
27#include "clang/CodeGen/ConstantInitBuilder.h"
28#include "llvm/ADT/ArrayRef.h"
29#include "llvm/ADT/SetOperations.h"
30#include "llvm/ADT/StringExtras.h"
31#include "llvm/Bitcode/BitcodeReader.h"
32#include "llvm/IR/Constants.h"
33#include "llvm/IR/DerivedTypes.h"
34#include "llvm/IR/GlobalValue.h"
35#include "llvm/IR/Value.h"
36#include "llvm/Support/AtomicOrdering.h"
37#include "llvm/Support/Format.h"
38#include "llvm/Support/raw_ostream.h"
39#include <cassert>
40#include <numeric>
41
42using namespace clang;
43using namespace CodeGen;
44using namespace llvm::omp;
45
46namespace {
47/// Base class for handling code generation inside OpenMP regions.
48class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
49public:
50 /// Kinds of OpenMP regions used in codegen.
51 enum CGOpenMPRegionKind {
52 /// Region with outlined function for standalone 'parallel'
53 /// directive.
54 ParallelOutlinedRegion,
55 /// Region with outlined function for standalone 'task' directive.
56 TaskOutlinedRegion,
57 /// Region for constructs that do not require function outlining,
58 /// like 'for', 'sections', 'atomic' etc. directives.
59 InlinedRegion,
60 /// Region with outlined function for standalone 'target' directive.
61 TargetRegion,
62 };
63
64 CGOpenMPRegionInfo(const CapturedStmt &CS,
65 const CGOpenMPRegionKind RegionKind,
66 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
67 bool HasCancel)
68 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
69 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
70
71 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
72 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
73 bool HasCancel)
74 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
75 Kind(Kind), HasCancel(HasCancel) {}
76
77 /// Get a variable or parameter for storing global thread id
78 /// inside OpenMP construct.
79 virtual const VarDecl *getThreadIDVariable() const = 0;
80
81 /// Emit the captured statement body.
82 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
83
84 /// Get an LValue for the current ThreadID variable.
85 /// \return LValue for thread id variable. This LValue always has type int32*.
86 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
87
88 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
89
90 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
91
92 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
93
94 bool hasCancel() const { return HasCancel; }
95
96 static bool classof(const CGCapturedStmtInfo *Info) {
97 return Info->getKind() == CR_OpenMP;
98 }
99
100 ~CGOpenMPRegionInfo() override = default;
101
102protected:
103 CGOpenMPRegionKind RegionKind;
104 RegionCodeGenTy CodeGen;
105 OpenMPDirectiveKind Kind;
106 bool HasCancel;
107};
108
109/// API for captured statement code generation in OpenMP constructs.
110class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
111public:
112 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
113 const RegionCodeGenTy &CodeGen,
114 OpenMPDirectiveKind Kind, bool HasCancel,
115 StringRef HelperName)
116 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
117 HasCancel),
118 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
119 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.")((ThreadIDVar != nullptr && "No ThreadID in OpenMP region."
) ? static_cast<void> (0) : __assert_fail ("ThreadIDVar != nullptr && \"No ThreadID in OpenMP region.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 119, __PRETTY_FUNCTION__))
;
120 }
121
122 /// Get a variable or parameter for storing global thread id
123 /// inside OpenMP construct.
124 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
125
126 /// Get the name of the capture helper.
127 StringRef getHelperName() const override { return HelperName; }
128
129 static bool classof(const CGCapturedStmtInfo *Info) {
130 return CGOpenMPRegionInfo::classof(Info) &&
131 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
132 ParallelOutlinedRegion;
133 }
134
135private:
136 /// A variable or parameter storing global thread id for OpenMP
137 /// constructs.
138 const VarDecl *ThreadIDVar;
139 StringRef HelperName;
140};
141
142/// API for captured statement code generation in OpenMP constructs.
143class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
144public:
145 class UntiedTaskActionTy final : public PrePostActionTy {
146 bool Untied;
147 const VarDecl *PartIDVar;
148 const RegionCodeGenTy UntiedCodeGen;
149 llvm::SwitchInst *UntiedSwitch = nullptr;
150
151 public:
152 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
153 const RegionCodeGenTy &UntiedCodeGen)
154 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
155 void Enter(CodeGenFunction &CGF) override {
156 if (Untied) {
157 // Emit task switching point.
158 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
159 CGF.GetAddrOfLocalVar(PartIDVar),
160 PartIDVar->getType()->castAs<PointerType>());
161 llvm::Value *Res =
162 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation());
163 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done.");
164 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
165 CGF.EmitBlock(DoneBB);
166 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
167 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
168 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
169 CGF.Builder.GetInsertBlock());
170 emitUntiedSwitch(CGF);
171 }
172 }
173 void emitUntiedSwitch(CodeGenFunction &CGF) const {
174 if (Untied) {
175 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
176 CGF.GetAddrOfLocalVar(PartIDVar),
177 PartIDVar->getType()->castAs<PointerType>());
178 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
179 PartIdLVal);
180 UntiedCodeGen(CGF);
181 CodeGenFunction::JumpDest CurPoint =
182 CGF.getJumpDestInCurrentScope(".untied.next.");
183 CGF.EmitBranch(CGF.ReturnBlock.getBlock());
184 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
185 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
186 CGF.Builder.GetInsertBlock());
187 CGF.EmitBranchThroughCleanup(CurPoint);
188 CGF.EmitBlock(CurPoint.getBlock());
189 }
190 }
191 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
192 };
193 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
194 const VarDecl *ThreadIDVar,
195 const RegionCodeGenTy &CodeGen,
196 OpenMPDirectiveKind Kind, bool HasCancel,
197 const UntiedTaskActionTy &Action)
198 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
199 ThreadIDVar(ThreadIDVar), Action(Action) {
200 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.")((ThreadIDVar != nullptr && "No ThreadID in OpenMP region."
) ? static_cast<void> (0) : __assert_fail ("ThreadIDVar != nullptr && \"No ThreadID in OpenMP region.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 200, __PRETTY_FUNCTION__))
;
201 }
202
203 /// Get a variable or parameter for storing global thread id
204 /// inside OpenMP construct.
205 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
206
207 /// Get an LValue for the current ThreadID variable.
208 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
209
210 /// Get the name of the capture helper.
211 StringRef getHelperName() const override { return ".omp_outlined."; }
212
213 void emitUntiedSwitch(CodeGenFunction &CGF) override {
214 Action.emitUntiedSwitch(CGF);
215 }
216
217 static bool classof(const CGCapturedStmtInfo *Info) {
218 return CGOpenMPRegionInfo::classof(Info) &&
219 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
220 TaskOutlinedRegion;
221 }
222
223private:
224 /// A variable or parameter storing global thread id for OpenMP
225 /// constructs.
226 const VarDecl *ThreadIDVar;
227 /// Action for emitting code for untied tasks.
228 const UntiedTaskActionTy &Action;
229};
230
231/// API for inlined captured statement code generation in OpenMP
232/// constructs.
233class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
234public:
235 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
236 const RegionCodeGenTy &CodeGen,
237 OpenMPDirectiveKind Kind, bool HasCancel)
238 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
239 OldCSI(OldCSI),
240 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
241
242 // Retrieve the value of the context parameter.
243 llvm::Value *getContextValue() const override {
244 if (OuterRegionInfo)
245 return OuterRegionInfo->getContextValue();
246 llvm_unreachable("No context value for inlined OpenMP region")::llvm::llvm_unreachable_internal("No context value for inlined OpenMP region"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 246)
;
247 }
248
249 void setContextValue(llvm::Value *V) override {
250 if (OuterRegionInfo) {
251 OuterRegionInfo->setContextValue(V);
252 return;
253 }
254 llvm_unreachable("No context value for inlined OpenMP region")::llvm::llvm_unreachable_internal("No context value for inlined OpenMP region"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 254)
;
255 }
256
257 /// Lookup the captured field decl for a variable.
258 const FieldDecl *lookup(const VarDecl *VD) const override {
259 if (OuterRegionInfo)
260 return OuterRegionInfo->lookup(VD);
261 // If there is no outer outlined region,no need to lookup in a list of
262 // captured variables, we can use the original one.
263 return nullptr;
264 }
265
266 FieldDecl *getThisFieldDecl() const override {
267 if (OuterRegionInfo)
268 return OuterRegionInfo->getThisFieldDecl();
269 return nullptr;
270 }
271
272 /// Get a variable or parameter for storing global thread id
273 /// inside OpenMP construct.
274 const VarDecl *getThreadIDVariable() const override {
275 if (OuterRegionInfo)
276 return OuterRegionInfo->getThreadIDVariable();
277 return nullptr;
278 }
279
280 /// Get an LValue for the current ThreadID variable.
281 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override {
282 if (OuterRegionInfo)
283 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
284 llvm_unreachable("No LValue for inlined OpenMP construct")::llvm::llvm_unreachable_internal("No LValue for inlined OpenMP construct"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 284)
;
285 }
286
287 /// Get the name of the capture helper.
288 StringRef getHelperName() const override {
289 if (auto *OuterRegionInfo = getOldCSI())
290 return OuterRegionInfo->getHelperName();
291 llvm_unreachable("No helper name for inlined OpenMP construct")::llvm::llvm_unreachable_internal("No helper name for inlined OpenMP construct"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 291)
;
292 }
293
294 void emitUntiedSwitch(CodeGenFunction &CGF) override {
295 if (OuterRegionInfo)
296 OuterRegionInfo->emitUntiedSwitch(CGF);
297 }
298
299 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
300
301 static bool classof(const CGCapturedStmtInfo *Info) {
302 return CGOpenMPRegionInfo::classof(Info) &&
303 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
304 }
305
306 ~CGOpenMPInlinedRegionInfo() override = default;
307
308private:
309 /// CodeGen info about outer OpenMP region.
310 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
311 CGOpenMPRegionInfo *OuterRegionInfo;
312};
313
314/// API for captured statement code generation in OpenMP target
315/// constructs. For this captures, implicit parameters are used instead of the
316/// captured fields. The name of the target region has to be unique in a given
317/// application so it is provided by the client, because only the client has
318/// the information to generate that.
319class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
320public:
321 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
322 const RegionCodeGenTy &CodeGen, StringRef HelperName)
323 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
324 /*HasCancel=*/false),
325 HelperName(HelperName) {}
326
327 /// This is unused for target regions because each starts executing
328 /// with a single thread.
329 const VarDecl *getThreadIDVariable() const override { return nullptr; }
330
331 /// Get the name of the capture helper.
332 StringRef getHelperName() const override { return HelperName; }
333
334 static bool classof(const CGCapturedStmtInfo *Info) {
335 return CGOpenMPRegionInfo::classof(Info) &&
336 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
337 }
338
339private:
340 StringRef HelperName;
341};
342
343static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
344 llvm_unreachable("No codegen for expressions")::llvm::llvm_unreachable_internal("No codegen for expressions"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 344)
;
345}
346/// API for generation of expressions captured in a innermost OpenMP
347/// region.
348class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
349public:
350 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
351 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
352 OMPD_unknown,
353 /*HasCancel=*/false),
354 PrivScope(CGF) {
355 // Make sure the globals captured in the provided statement are local by
356 // using the privatization logic. We assume the same variable is not
357 // captured more than once.
358 for (const auto &C : CS.captures()) {
359 if (!C.capturesVariable() && !C.capturesVariableByCopy())
360 continue;
361
362 const VarDecl *VD = C.getCapturedVar();
363 if (VD->isLocalVarDeclOrParm())
364 continue;
365
366 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
367 /*RefersToEnclosingVariableOrCapture=*/false,
368 VD->getType().getNonReferenceType(), VK_LValue,
369 C.getLocation());
370 PrivScope.addPrivate(
371 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); });
372 }
373 (void)PrivScope.Privatize();
374 }
375
376 /// Lookup the captured field decl for a variable.
377 const FieldDecl *lookup(const VarDecl *VD) const override {
378 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
379 return FD;
380 return nullptr;
381 }
382
383 /// Emit the captured statement body.
384 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
385 llvm_unreachable("No body for expressions")::llvm::llvm_unreachable_internal("No body for expressions", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 385)
;
386 }
387
388 /// Get a variable or parameter for storing global thread id
389 /// inside OpenMP construct.
390 const VarDecl *getThreadIDVariable() const override {
391 llvm_unreachable("No thread id for expressions")::llvm::llvm_unreachable_internal("No thread id for expressions"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 391)
;
392 }
393
394 /// Get the name of the capture helper.
395 StringRef getHelperName() const override {
396 llvm_unreachable("No helper name for expressions")::llvm::llvm_unreachable_internal("No helper name for expressions"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 396)
;
397 }
398
399 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
400
401private:
402 /// Private scope to capture global variables.
403 CodeGenFunction::OMPPrivateScope PrivScope;
404};
405
406/// RAII for emitting code of OpenMP constructs.
407class InlinedOpenMPRegionRAII {
408 CodeGenFunction &CGF;
409 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
410 FieldDecl *LambdaThisCaptureField = nullptr;
411 const CodeGen::CGBlockInfo *BlockInfo = nullptr;
412
413public:
414 /// Constructs region for combined constructs.
415 /// \param CodeGen Code generation sequence for combined directives. Includes
416 /// a list of functions used for code generation of implicitly inlined
417 /// regions.
418 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
419 OpenMPDirectiveKind Kind, bool HasCancel)
420 : CGF(CGF) {
421 // Start emission for the construct.
422 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
423 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
424 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
425 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
426 CGF.LambdaThisCaptureField = nullptr;
427 BlockInfo = CGF.BlockInfo;
428 CGF.BlockInfo = nullptr;
429 }
430
431 ~InlinedOpenMPRegionRAII() {
432 // Restore original CapturedStmtInfo only if we're done with code emission.
433 auto *OldCSI =
434 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
435 delete CGF.CapturedStmtInfo;
436 CGF.CapturedStmtInfo = OldCSI;
437 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
438 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
439 CGF.BlockInfo = BlockInfo;
440 }
441};
442
443/// Values for bit flags used in the ident_t to describe the fields.
444/// All enumeric elements are named and described in accordance with the code
445/// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
446enum OpenMPLocationFlags : unsigned {
447 /// Use trampoline for internal microtask.
448 OMP_IDENT_IMD = 0x01,
449 /// Use c-style ident structure.
450 OMP_IDENT_KMPC = 0x02,
451 /// Atomic reduction option for kmpc_reduce.
452 OMP_ATOMIC_REDUCE = 0x10,
453 /// Explicit 'barrier' directive.
454 OMP_IDENT_BARRIER_EXPL = 0x20,
455 /// Implicit barrier in code.
456 OMP_IDENT_BARRIER_IMPL = 0x40,
457 /// Implicit barrier in 'for' directive.
458 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
459 /// Implicit barrier in 'sections' directive.
460 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
461 /// Implicit barrier in 'single' directive.
462 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
463 /// Call of __kmp_for_static_init for static loop.
464 OMP_IDENT_WORK_LOOP = 0x200,
465 /// Call of __kmp_for_static_init for sections.
466 OMP_IDENT_WORK_SECTIONS = 0x400,
467 /// Call of __kmp_for_static_init for distribute.
468 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
469 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_IDENT_WORK_DISTRIBUTE
470};
471
472namespace {
473LLVM_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^=
;
474/// Values for bit flags for marking which requires clauses have been used.
475enum OpenMPOffloadingRequiresDirFlags : int64_t {
476 /// flag undefined.
477 OMP_REQ_UNDEFINED = 0x000,
478 /// no requires clause present.
479 OMP_REQ_NONE = 0x001,
480 /// reverse_offload clause.
481 OMP_REQ_REVERSE_OFFLOAD = 0x002,
482 /// unified_address clause.
483 OMP_REQ_UNIFIED_ADDRESS = 0x004,
484 /// unified_shared_memory clause.
485 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
486 /// dynamic_allocators clause.
487 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
488 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_REQ_DYNAMIC_ALLOCATORS
489};
490
491enum OpenMPOffloadingReservedDeviceIDs {
492 /// Device ID if the device was not defined, runtime should get it
493 /// from environment variables in the spec.
494 OMP_DEVICEID_UNDEF = -1,
495};
496} // anonymous namespace
497
498/// Describes ident structure that describes a source location.
499/// All descriptions are taken from
500/// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
501/// Original structure:
502/// typedef struct ident {
503/// kmp_int32 reserved_1; /**< might be used in Fortran;
504/// see above */
505/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
506/// KMP_IDENT_KMPC identifies this union
507/// member */
508/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
509/// see above */
510///#if USE_ITT_BUILD
511/// /* but currently used for storing
512/// region-specific ITT */
513/// /* contextual information. */
514///#endif /* USE_ITT_BUILD */
515/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
516/// C++ */
517/// char const *psource; /**< String describing the source location.
518/// The string is composed of semi-colon separated
519// fields which describe the source file,
520/// the function and a pair of line numbers that
521/// delimit the construct.
522/// */
523/// } ident_t;
524enum IdentFieldIndex {
525 /// might be used in Fortran
526 IdentField_Reserved_1,
527 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
528 IdentField_Flags,
529 /// Not really used in Fortran any more
530 IdentField_Reserved_2,
531 /// Source[4] in Fortran, do not use for C++
532 IdentField_Reserved_3,
533 /// String describing the source location. The string is composed of
534 /// semi-colon separated fields which describe the source file, the function
535 /// and a pair of line numbers that delimit the construct.
536 IdentField_PSource
537};
538
539/// Schedule types for 'omp for' loops (these enumerators are taken from
540/// the enum sched_type in kmp.h).
541enum OpenMPSchedType {
542 /// Lower bound for default (unordered) versions.
543 OMP_sch_lower = 32,
544 OMP_sch_static_chunked = 33,
545 OMP_sch_static = 34,
546 OMP_sch_dynamic_chunked = 35,
547 OMP_sch_guided_chunked = 36,
548 OMP_sch_runtime = 37,
549 OMP_sch_auto = 38,
550 /// static with chunk adjustment (e.g., simd)
551 OMP_sch_static_balanced_chunked = 45,
552 /// Lower bound for 'ordered' versions.
553 OMP_ord_lower = 64,
554 OMP_ord_static_chunked = 65,
555 OMP_ord_static = 66,
556 OMP_ord_dynamic_chunked = 67,
557 OMP_ord_guided_chunked = 68,
558 OMP_ord_runtime = 69,
559 OMP_ord_auto = 70,
560 OMP_sch_default = OMP_sch_static,
561 /// dist_schedule types
562 OMP_dist_sch_static_chunked = 91,
563 OMP_dist_sch_static = 92,
564 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
565 /// Set if the monotonic schedule modifier was present.
566 OMP_sch_modifier_monotonic = (1 << 29),
567 /// Set if the nonmonotonic schedule modifier was present.
568 OMP_sch_modifier_nonmonotonic = (1 << 30),
569};
570
571/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
572/// region.
573class CleanupTy final : public EHScopeStack::Cleanup {
574 PrePostActionTy *Action;
575
576public:
577 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
578 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
579 if (!CGF.HaveInsertPoint())
580 return;
581 Action->Exit(CGF);
582 }
583};
584
585} // anonymous namespace
586
587void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
588 CodeGenFunction::RunCleanupsScope Scope(CGF);
589 if (PrePostAction
14.1
Field 'PrePostAction' is null
14.1
Field 'PrePostAction' is null
) {
15
Taking false branch
590 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
591 Callback(CodeGen, CGF, *PrePostAction);
592 } else {
593 PrePostActionTy Action;
594 Callback(CodeGen, CGF, Action);
16
Calling 'RegionCodeGenTy::CallbackFn'
595 }
596}
597
598/// Check if the combiner is a call to UDR combiner and if it is so return the
599/// UDR decl used for reduction.
600static const OMPDeclareReductionDecl *
601getReductionInit(const Expr *ReductionOp) {
602 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
603 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
604 if (const auto *DRE =
605 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
606 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
607 return DRD;
608 return nullptr;
609}
610
611static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
612 const OMPDeclareReductionDecl *DRD,
613 const Expr *InitOp,
614 Address Private, Address Original,
615 QualType Ty) {
616 if (DRD->getInitializer()) {
617 std::pair<llvm::Function *, llvm::Function *> Reduction =
618 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
619 const auto *CE = cast<CallExpr>(InitOp);
620 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
621 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
622 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
623 const auto *LHSDRE =
624 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
625 const auto *RHSDRE =
626 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
627 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
628 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
629 [=]() { return Private; });
630 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
631 [=]() { return Original; });
632 (void)PrivateScope.Privatize();
633 RValue Func = RValue::get(Reduction.second);
634 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
635 CGF.EmitIgnoredExpr(InitOp);
636 } else {
637 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
638 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
639 auto *GV = new llvm::GlobalVariable(
640 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
641 llvm::GlobalValue::PrivateLinkage, Init, Name);
642 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
643 RValue InitRVal;
644 switch (CGF.getEvaluationKind(Ty)) {
645 case TEK_Scalar:
646 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
647 break;
648 case TEK_Complex:
649 InitRVal =
650 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
651 break;
652 case TEK_Aggregate:
653 InitRVal = RValue::getAggregate(LV.getAddress(CGF));
654 break;
655 }
656 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
657 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
658 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
659 /*IsInitializer=*/false);
660 }
661}
662
663/// Emit initialization of arrays of complex types.
664/// \param DestAddr Address of the array.
665/// \param Type Type of array.
666/// \param Init Initial expression of array.
667/// \param SrcAddr Address of the original array.
668static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
669 QualType Type, bool EmitDeclareReductionInit,
670 const Expr *Init,
671 const OMPDeclareReductionDecl *DRD,
672 Address SrcAddr = Address::invalid()) {
673 // Perform element-by-element initialization.
674 QualType ElementTy;
675
676 // Drill down to the base element type on both arrays.
677 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
678 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
679 DestAddr =
680 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
681 if (DRD)
682 SrcAddr =
683 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
684
685 llvm::Value *SrcBegin = nullptr;
686 if (DRD)
687 SrcBegin = SrcAddr.getPointer();
688 llvm::Value *DestBegin = DestAddr.getPointer();
689 // Cast from pointer to array type to pointer to single element.
690 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
691 // The basic structure here is a while-do loop.
692 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
693 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
694 llvm::Value *IsEmpty =
695 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
696 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
697
698 // Enter the loop body, making that address the current address.
699 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
700 CGF.EmitBlock(BodyBB);
701
702 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
703
704 llvm::PHINode *SrcElementPHI = nullptr;
705 Address SrcElementCurrent = Address::invalid();
706 if (DRD) {
707 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
708 "omp.arraycpy.srcElementPast");
709 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
710 SrcElementCurrent =
711 Address(SrcElementPHI,
712 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
713 }
714 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
715 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
716 DestElementPHI->addIncoming(DestBegin, EntryBB);
717 Address DestElementCurrent =
718 Address(DestElementPHI,
719 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
720
721 // Emit copy.
722 {
723 CodeGenFunction::RunCleanupsScope InitScope(CGF);
724 if (EmitDeclareReductionInit) {
725 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
726 SrcElementCurrent, ElementTy);
727 } else
728 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
729 /*IsInitializer=*/false);
730 }
731
732 if (DRD) {
733 // Shift the address forward by one element.
734 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
735 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
736 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
737 }
738
739 // Shift the address forward by one element.
740 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
741 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
742 // Check whether we've reached the end.
743 llvm::Value *Done =
744 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
745 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
746 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
747
748 // Done.
749 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
750}
751
752LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
753 return CGF.EmitOMPSharedLValue(E);
754}
755
756LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
757 const Expr *E) {
758 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
759 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
760 return LValue();
761}
762
763void ReductionCodeGen::emitAggregateInitialization(
764 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
765 const OMPDeclareReductionDecl *DRD) {
766 // Emit VarDecl with copy init for arrays.
767 // Get the address of the original variable captured in current
768 // captured region.
769 const auto *PrivateVD =
770 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
771 bool EmitDeclareReductionInit =
772 DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
773 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),
774 EmitDeclareReductionInit,
775 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
776 : PrivateVD->getInit(),
777 DRD, SharedLVal.getAddress(CGF));
778}
779
780ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
781 ArrayRef<const Expr *> Origs,
782 ArrayRef<const Expr *> Privates,
783 ArrayRef<const Expr *> ReductionOps) {
784 ClausesData.reserve(Shareds.size());
785 SharedAddresses.reserve(Shareds.size());
786 Sizes.reserve(Shareds.size());
787 BaseDecls.reserve(Shareds.size());
788 const auto *IOrig = Origs.begin();
789 const auto *IPriv = Privates.begin();
790 const auto *IRed = ReductionOps.begin();
791 for (const Expr *Ref : Shareds) {
792 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
793 std::advance(IOrig, 1);
794 std::advance(IPriv, 1);
795 std::advance(IRed, 1);
796 }
797}
798
799void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) {
800 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&((SharedAddresses.size() == N && OrigAddresses.size()
== N && "Number of generated lvalues must be exactly N."
) ? static_cast<void> (0) : __assert_fail ("SharedAddresses.size() == N && OrigAddresses.size() == N && \"Number of generated lvalues must be exactly N.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 801, __PRETTY_FUNCTION__))
801 "Number of generated lvalues must be exactly N.")((SharedAddresses.size() == N && OrigAddresses.size()
== N && "Number of generated lvalues must be exactly N."
) ? static_cast<void> (0) : __assert_fail ("SharedAddresses.size() == N && OrigAddresses.size() == N && \"Number of generated lvalues must be exactly N.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 801, __PRETTY_FUNCTION__))
;
802 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
803 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
804 SharedAddresses.emplace_back(First, Second);
805 if (ClausesData[N].Shared == ClausesData[N].Ref) {
806 OrigAddresses.emplace_back(First, Second);
807 } else {
808 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
809 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
810 OrigAddresses.emplace_back(First, Second);
811 }
812}
813
814void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
815 const auto *PrivateVD =
816 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
817 QualType PrivateType = PrivateVD->getType();
818 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
819 if (!PrivateType->isVariablyModifiedType()) {
820 Sizes.emplace_back(
821 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
822 nullptr);
823 return;
824 }
825 llvm::Value *Size;
826 llvm::Value *SizeInChars;
827 auto *ElemType =
828 cast<llvm::PointerType>(OrigAddresses[N].first.getPointer(CGF)->getType())
829 ->getElementType();
830 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
831 if (AsArraySection) {
832 Size = CGF.Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF),
833 OrigAddresses[N].first.getPointer(CGF));
834 Size = CGF.Builder.CreateNUWAdd(
835 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
836 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf);
837 } else {
838 SizeInChars =
839 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
840 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
841 }
842 Sizes.emplace_back(SizeInChars, Size);
843 CodeGenFunction::OpaqueValueMapping OpaqueMap(
844 CGF,
845 cast<OpaqueValueExpr>(
846 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
847 RValue::get(Size));
848 CGF.EmitVariablyModifiedType(PrivateType);
849}
850
851void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
852 llvm::Value *Size) {
853 const auto *PrivateVD =
854 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
855 QualType PrivateType = PrivateVD->getType();
856 if (!PrivateType->isVariablyModifiedType()) {
857 assert(!Size && !Sizes[N].second &&((!Size && !Sizes[N].second && "Size should be nullptr for non-variably modified reduction "
"items.") ? static_cast<void> (0) : __assert_fail ("!Size && !Sizes[N].second && \"Size should be nullptr for non-variably modified reduction \" \"items.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 859, __PRETTY_FUNCTION__))
858 "Size should be nullptr for non-variably modified reduction "((!Size && !Sizes[N].second && "Size should be nullptr for non-variably modified reduction "
"items.") ? static_cast<void> (0) : __assert_fail ("!Size && !Sizes[N].second && \"Size should be nullptr for non-variably modified reduction \" \"items.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 859, __PRETTY_FUNCTION__))
859 "items.")((!Size && !Sizes[N].second && "Size should be nullptr for non-variably modified reduction "
"items.") ? static_cast<void> (0) : __assert_fail ("!Size && !Sizes[N].second && \"Size should be nullptr for non-variably modified reduction \" \"items.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 859, __PRETTY_FUNCTION__))
;
860 return;
861 }
862 CodeGenFunction::OpaqueValueMapping OpaqueMap(
863 CGF,
864 cast<OpaqueValueExpr>(
865 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
866 RValue::get(Size));
867 CGF.EmitVariablyModifiedType(PrivateType);
868}
869
870void ReductionCodeGen::emitInitialization(
871 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
872 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
873 assert(SharedAddresses.size() > N && "No variable was generated")((SharedAddresses.size() > N && "No variable was generated"
) ? static_cast<void> (0) : __assert_fail ("SharedAddresses.size() > N && \"No variable was generated\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 873, __PRETTY_FUNCTION__))
;
874 const auto *PrivateVD =
875 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
876 const OMPDeclareReductionDecl *DRD =
877 getReductionInit(ClausesData[N].ReductionOp);
878 QualType PrivateType = PrivateVD->getType();
879 PrivateAddr = CGF.Builder.CreateElementBitCast(
880 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
881 QualType SharedType = SharedAddresses[N].first.getType();
882 SharedLVal = CGF.MakeAddrLValue(
883 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF),
884 CGF.ConvertTypeForMem(SharedType)),
885 SharedType, SharedAddresses[N].first.getBaseInfo(),
886 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType));
887 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
888 if (DRD && DRD->getInitializer())
889 (void)DefaultInit(CGF);
890 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD);
891 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
892 (void)DefaultInit(CGF);
893 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
894 PrivateAddr, SharedLVal.getAddress(CGF),
895 SharedLVal.getType());
896 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
897 !CGF.isTrivialInitializer(PrivateVD->getInit())) {
898 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,
899 PrivateVD->getType().getQualifiers(),
900 /*IsInitializer=*/false);
901 }
902}
903
904bool ReductionCodeGen::needCleanups(unsigned N) {
905 const auto *PrivateVD =
906 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
907 QualType PrivateType = PrivateVD->getType();
908 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
909 return DTorKind != QualType::DK_none;
910}
911
912void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
913 Address PrivateAddr) {
914 const auto *PrivateVD =
915 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
916 QualType PrivateType = PrivateVD->getType();
917 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
918 if (needCleanups(N)) {
919 PrivateAddr = CGF.Builder.CreateElementBitCast(
920 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
921 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);
922 }
923}
924
925static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
926 LValue BaseLV) {
927 BaseTy = BaseTy.getNonReferenceType();
928 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
929 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
930 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
931 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy);
932 } else {
933 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy);
934 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
935 }
936 BaseTy = BaseTy->getPointeeType();
937 }
938 return CGF.MakeAddrLValue(
939 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF),
940 CGF.ConvertTypeForMem(ElTy)),
941 BaseLV.getType(), BaseLV.getBaseInfo(),
942 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
943}
944
945static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
946 llvm::Type *BaseLVType, CharUnits BaseLVAlignment,
947 llvm::Value *Addr) {
948 Address Tmp = Address::invalid();
949 Address TopTmp = Address::invalid();
950 Address MostTopTmp = Address::invalid();
951 BaseTy = BaseTy.getNonReferenceType();
952 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
953 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
954 Tmp = CGF.CreateMemTemp(BaseTy);
955 if (TopTmp.isValid())
956 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
957 else
958 MostTopTmp = Tmp;
959 TopTmp = Tmp;
960 BaseTy = BaseTy->getPointeeType();
961 }
962 llvm::Type *Ty = BaseLVType;
963 if (Tmp.isValid())
964 Ty = Tmp.getElementType();
965 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);
966 if (Tmp.isValid()) {
967 CGF.Builder.CreateStore(Addr, Tmp);
968 return MostTopTmp;
969 }
970 return Address(Addr, BaseLVAlignment);
971}
972
973static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
974 const VarDecl *OrigVD = nullptr;
975 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
976 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
977 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
978 Base = TempOASE->getBase()->IgnoreParenImpCasts();
979 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
980 Base = TempASE->getBase()->IgnoreParenImpCasts();
981 DE = cast<DeclRefExpr>(Base);
982 OrigVD = cast<VarDecl>(DE->getDecl());
983 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
984 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
985 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
986 Base = TempASE->getBase()->IgnoreParenImpCasts();
987 DE = cast<DeclRefExpr>(Base);
988 OrigVD = cast<VarDecl>(DE->getDecl());
989 }
990 return OrigVD;
991}
992
993Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
994 Address PrivateAddr) {
995 const DeclRefExpr *DE;
996 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
997 BaseDecls.emplace_back(OrigVD);
998 LValue OriginalBaseLValue = CGF.EmitLValue(DE);
999 LValue BaseLValue =
1000 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
1001 OriginalBaseLValue);
1002 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
1003 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF));
1004 llvm::Value *PrivatePointer =
1005 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1006 PrivateAddr.getPointer(),
1007 SharedAddresses[N].first.getAddress(CGF).getType());
1008 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
1009 return castToBase(CGF, OrigVD->getType(),
1010 SharedAddresses[N].first.getType(),
1011 OriginalBaseLValue.getAddress(CGF).getType(),
1012 OriginalBaseLValue.getAlignment(), Ptr);
1013 }
1014 BaseDecls.emplace_back(
1015 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
1016 return PrivateAddr;
1017}
1018
1019bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
1020 const OMPDeclareReductionDecl *DRD =
1021 getReductionInit(ClausesData[N].ReductionOp);
1022 return DRD && DRD->getInitializer();
1023}
1024
1025LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
1026 return CGF.EmitLoadOfPointerLValue(
1027 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1028 getThreadIDVariable()->getType()->castAs<PointerType>());
1029}
1030
1031void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
1032 if (!CGF.HaveInsertPoint())
1033 return;
1034 // 1.2.2 OpenMP Language Terminology
1035 // Structured block - An executable statement with a single entry at the
1036 // top and a single exit at the bottom.
1037 // The point of exit cannot be a branch out of the structured block.
1038 // longjmp() and throw() must not violate the entry/exit criteria.
1039 CGF.EHStack.pushTerminate();
1040 CodeGen(CGF);
1041 CGF.EHStack.popTerminate();
1042}
1043
1044LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1045 CodeGenFunction &CGF) {
1046 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1047 getThreadIDVariable()->getType(),
1048 AlignmentSource::Decl);
1049}
1050
1051static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1052 QualType FieldTy) {
1053 auto *Field = FieldDecl::Create(
1054 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1055 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1056 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1057 Field->setAccess(AS_public);
1058 DC->addDecl(Field);
1059 return Field;
1060}
1061
1062CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
1063 StringRef Separator)
1064 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
1065 OMPBuilder(CGM.getModule()), OffloadEntriesInfoManager(CGM) {
1066 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
1067
1068 // Initialize Types used in OpenMPIRBuilder from OMPKinds.def
1069 OMPBuilder.initialize();
1070 loadOffloadInfoMetadata();
1071}
1072
1073void CGOpenMPRuntime::clear() {
1074 InternalVars.clear();
1075 // Clean non-target variable declarations possibly used only in debug info.
1076 for (const auto &Data : EmittedNonTargetVariables) {
1077 if (!Data.getValue().pointsToAliveValue())
1078 continue;
1079 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1080 if (!GV)
1081 continue;
1082 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1083 continue;
1084 GV->eraseFromParent();
1085 }
1086}
1087
1088std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1089 SmallString<128> Buffer;
1090 llvm::raw_svector_ostream OS(Buffer);
1091 StringRef Sep = FirstSeparator;
1092 for (StringRef Part : Parts) {
1093 OS << Sep << Part;
1094 Sep = Separator;
1095 }
1096 return std::string(OS.str());
1097}
1098
1099static llvm::Function *
1100emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1101 const Expr *CombinerInitializer, const VarDecl *In,
1102 const VarDecl *Out, bool IsCombiner) {
1103 // void .omp_combiner.(Ty *in, Ty *out);
1104 ASTContext &C = CGM.getContext();
1105 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1106 FunctionArgList Args;
1107 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
1108 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
1109 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
1110 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
1111 Args.push_back(&OmpOutParm);
1112 Args.push_back(&OmpInParm);
1113 const CGFunctionInfo &FnInfo =
1114 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
1115 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
1116 std::string Name = CGM.getOpenMPRuntime().getName(
1117 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1118 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1119 Name, &CGM.getModule());
1120 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
1121 if (CGM.getLangOpts().Optimize) {
1122 Fn->removeFnAttr(llvm::Attribute::NoInline);
1123 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1124 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1125 }
1126 CodeGenFunction CGF(CGM);
1127 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1128 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
1129 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1130 Out->getLocation());
1131 CodeGenFunction::OMPPrivateScope Scope(CGF);
1132 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
1133 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
1134 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
1135 .getAddress(CGF);
1136 });
1137 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
1138 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
1139 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
1140 .getAddress(CGF);
1141 });
1142 (void)Scope.Privatize();
1143 if (!IsCombiner && Out->hasInit() &&
1144 !CGF.isTrivialInitializer(Out->getInit())) {
1145 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1146 Out->getType().getQualifiers(),
1147 /*IsInitializer=*/true);
1148 }
1149 if (CombinerInitializer)
1150 CGF.EmitIgnoredExpr(CombinerInitializer);
1151 Scope.ForceCleanup();
1152 CGF.FinishFunction();
1153 return Fn;
1154}
1155
1156void CGOpenMPRuntime::emitUserDefinedReduction(
1157 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1158 if (UDRMap.count(D) > 0)
1159 return;
1160 llvm::Function *Combiner = emitCombinerOrInitializer(
1161 CGM, D->getType(), D->getCombiner(),
1162 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1163 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
1164 /*IsCombiner=*/true);
1165 llvm::Function *Initializer = nullptr;
1166 if (const Expr *Init = D->getInitializer()) {
1167 Initializer = emitCombinerOrInitializer(
1168 CGM, D->getType(),
1169 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1170 : nullptr,
1171 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1172 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
1173 /*IsCombiner=*/false);
1174 }
1175 UDRMap.try_emplace(D, Combiner, Initializer);
1176 if (CGF) {
1177 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1178 Decls.second.push_back(D);
1179 }
1180}
1181
1182std::pair<llvm::Function *, llvm::Function *>
1183CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1184 auto I = UDRMap.find(D);
1185 if (I != UDRMap.end())
1186 return I->second;
1187 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1188 return UDRMap.lookup(D);
1189}
1190
1191namespace {
1192// Temporary RAII solution to perform a push/pop stack event on the OpenMP IR
1193// Builder if one is present.
1194struct PushAndPopStackRAII {
1195 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF,
1196 bool HasCancel)
1197 : OMPBuilder(OMPBuilder) {
1198 if (!OMPBuilder)
1199 return;
1200
1201 // The following callback is the crucial part of clangs cleanup process.
1202 //
1203 // NOTE:
1204 // Once the OpenMPIRBuilder is used to create parallel regions (and
1205 // similar), the cancellation destination (Dest below) is determined via
1206 // IP. That means if we have variables to finalize we split the block at IP,
1207 // use the new block (=BB) as destination to build a JumpDest (via
1208 // getJumpDestInCurrentScope(BB)) which then is fed to
1209 // EmitBranchThroughCleanup. Furthermore, there will not be the need
1210 // to push & pop an FinalizationInfo object.
1211 // The FiniCB will still be needed but at the point where the
1212 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct.
1213 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1214 assert(IP.getBlock()->end() == IP.getPoint() &&((IP.getBlock()->end() == IP.getPoint() && "Clang CG should cause non-terminated block!"
) ? static_cast<void> (0) : __assert_fail ("IP.getBlock()->end() == IP.getPoint() && \"Clang CG should cause non-terminated block!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1215, __PRETTY_FUNCTION__))
1215 "Clang CG should cause non-terminated block!")((IP.getBlock()->end() == IP.getPoint() && "Clang CG should cause non-terminated block!"
) ? static_cast<void> (0) : __assert_fail ("IP.getBlock()->end() == IP.getPoint() && \"Clang CG should cause non-terminated block!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1215, __PRETTY_FUNCTION__))
;
1216 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1217 CGF.Builder.restoreIP(IP);
1218 CodeGenFunction::JumpDest Dest =
1219 CGF.getOMPCancelDestination(OMPD_parallel);
1220 CGF.EmitBranchThroughCleanup(Dest);
1221 };
1222
1223 // TODO: Remove this once we emit parallel regions through the
1224 // OpenMPIRBuilder as it can do this setup internally.
1225 llvm::OpenMPIRBuilder::FinalizationInfo FI(
1226 {FiniCB, OMPD_parallel, HasCancel});
1227 OMPBuilder->pushFinalizationCB(std::move(FI));
1228 }
1229 ~PushAndPopStackRAII() {
1230 if (OMPBuilder)
1231 OMPBuilder->popFinalizationCB();
1232 }
1233 llvm::OpenMPIRBuilder *OMPBuilder;
1234};
1235} // namespace
1236
1237static llvm::Function *emitParallelOrTeamsOutlinedFunction(
1238 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1239 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1240 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
1241 assert(ThreadIDVar->getType()->isPointerType() &&((ThreadIDVar->getType()->isPointerType() && "thread id variable must be of type kmp_int32 *"
) ? static_cast<void> (0) : __assert_fail ("ThreadIDVar->getType()->isPointerType() && \"thread id variable must be of type kmp_int32 *\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1242, __PRETTY_FUNCTION__))
1242 "thread id variable must be of type kmp_int32 *")((ThreadIDVar->getType()->isPointerType() && "thread id variable must be of type kmp_int32 *"
) ? static_cast<void> (0) : __assert_fail ("ThreadIDVar->getType()->isPointerType() && \"thread id variable must be of type kmp_int32 *\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1242, __PRETTY_FUNCTION__))
;
1243 CodeGenFunction CGF(CGM, true);
1244 bool HasCancel = false;
1245 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1246 HasCancel = OPD->hasCancel();
1247 else if (const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1248 HasCancel = OPD->hasCancel();
1249 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1250 HasCancel = OPSD->hasCancel();
1251 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1252 HasCancel = OPFD->hasCancel();
1253 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1254 HasCancel = OPFD->hasCancel();
1255 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1256 HasCancel = OPFD->hasCancel();
1257 else if (const auto *OPFD =
1258 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1259 HasCancel = OPFD->hasCancel();
1260 else if (const auto *OPFD =
1261 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1262 HasCancel = OPFD->hasCancel();
1263
1264 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new
1265 // parallel region to make cancellation barriers work properly.
1266 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
1267 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel);
1268 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
1269 HasCancel, OutlinedHelperName);
1270 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
1271 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc());
1272}
1273
1274llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
1275 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1276 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1277 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1278 return emitParallelOrTeamsOutlinedFunction(
1279 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1280}
1281
1282llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
1283 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1284 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1285 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1286 return emitParallelOrTeamsOutlinedFunction(
1287 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1288}
1289
1290llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
1291 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1292 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1293 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1294 bool Tied, unsigned &NumberOfParts) {
1295 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1296 PrePostActionTy &) {
1297 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1298 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
1299 llvm::Value *TaskArgs[] = {
1300 UpLoc, ThreadID,
1301 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1302 TaskTVar->getType()->castAs<PointerType>())
1303 .getPointer(CGF)};
1304 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
1305 CGM.getModule(), OMPRTL___kmpc_omp_task),
1306 TaskArgs);
1307 };
1308 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1309 UntiedCodeGen);
1310 CodeGen.setAction(Action);
1311 assert(!ThreadIDVar->getType()->isPointerType() &&((!ThreadIDVar->getType()->isPointerType() && "thread id variable must be of type kmp_int32 for tasks"
) ? static_cast<void> (0) : __assert_fail ("!ThreadIDVar->getType()->isPointerType() && \"thread id variable must be of type kmp_int32 for tasks\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1312, __PRETTY_FUNCTION__))
1312 "thread id variable must be of type kmp_int32 for tasks")((!ThreadIDVar->getType()->isPointerType() && "thread id variable must be of type kmp_int32 for tasks"
) ? static_cast<void> (0) : __assert_fail ("!ThreadIDVar->getType()->isPointerType() && \"thread id variable must be of type kmp_int32 for tasks\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1312, __PRETTY_FUNCTION__))
;
1313 const OpenMPDirectiveKind Region =
1314 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1315 : OMPD_task;
1316 const CapturedStmt *CS = D.getCapturedStmt(Region);
1317 bool HasCancel = false;
1318 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1319 HasCancel = TD->hasCancel();
1320 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1321 HasCancel = TD->hasCancel();
1322 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1323 HasCancel = TD->hasCancel();
1324 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1325 HasCancel = TD->hasCancel();
1326
1327 CodeGenFunction CGF(CGM, true);
1328 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1329 InnermostKind, HasCancel, Action);
1330 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
1331 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1332 if (!Tied)
1333 NumberOfParts = Action.getNumberOfParts();
1334 return Res;
1335}
1336
1337static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1338 const RecordDecl *RD, const CGRecordLayout &RL,
1339 ArrayRef<llvm::Constant *> Data) {
1340 llvm::StructType *StructTy = RL.getLLVMType();
1341 unsigned PrevIdx = 0;
1342 ConstantInitBuilder CIBuilder(CGM);
1343 auto DI = Data.begin();
1344 for (const FieldDecl *FD : RD->fields()) {
1345 unsigned Idx = RL.getLLVMFieldNo(FD);
1346 // Fill the alignment.
1347 for (unsigned I = PrevIdx; I < Idx; ++I)
1348 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1349 PrevIdx = Idx + 1;
1350 Fields.add(*DI);
1351 ++DI;
1352 }
1353}
1354
1355template <class... As>
1356static llvm::GlobalVariable *
1357createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1358 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1359 As &&... Args) {
1360 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1361 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1362 ConstantInitBuilder CIBuilder(CGM);
1363 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1364 buildStructValue(Fields, CGM, RD, RL, Data);
1365 return Fields.finishAndCreateGlobal(
1366 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1367 std::forward<As>(Args)...);
1368}
1369
1370template <typename T>
1371static void
1372createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1373 ArrayRef<llvm::Constant *> Data,
1374 T &Parent) {
1375 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1376 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1377 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1378 buildStructValue(Fields, CGM, RD, RL, Data);
1379 Fields.finishAndAddTo(Parent);
1380}
1381
1382void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1383 bool AtCurrentPoint) {
1384 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1385 assert(!Elem.second.ServiceInsertPt && "Insert point is set already.")((!Elem.second.ServiceInsertPt && "Insert point is set already."
) ? static_cast<void> (0) : __assert_fail ("!Elem.second.ServiceInsertPt && \"Insert point is set already.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1385, __PRETTY_FUNCTION__))
;
1386
1387 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1388 if (AtCurrentPoint) {
1389 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1390 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1391 } else {
1392 Elem.second.ServiceInsertPt =
1393 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1394 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1395 }
1396}
1397
1398void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1399 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1400 if (Elem.second.ServiceInsertPt) {
1401 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1402 Elem.second.ServiceInsertPt = nullptr;
1403 Ptr->eraseFromParent();
1404 }
1405}
1406
1407static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF,
1408 SourceLocation Loc,
1409 SmallString<128> &Buffer) {
1410 llvm::raw_svector_ostream OS(Buffer);
1411 // Build debug location
1412 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1413 OS << ";" << PLoc.getFilename() << ";";
1414 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
1415 OS << FD->getQualifiedNameAsString();
1416 OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1417 return OS.str();
1418}
1419
1420llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1421 SourceLocation Loc,
1422 unsigned Flags) {
1423 llvm::Constant *SrcLocStr;
1424 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
1425 Loc.isInvalid()) {
1426 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr();
1427 } else {
1428 std::string FunctionName = "";
1429 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
1430 FunctionName = FD->getQualifiedNameAsString();
1431 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1432 const char *FileName = PLoc.getFilename();
1433 unsigned Line = PLoc.getLine();
1434 unsigned Column = PLoc.getColumn();
1435 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FunctionName.c_str(), FileName,
1436 Line, Column);
1437 }
1438 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1439 return OMPBuilder.getOrCreateIdent(SrcLocStr, llvm::omp::IdentFlag(Flags),
1440 Reserved2Flags);
1441}
1442
1443llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1444 SourceLocation Loc) {
1445 assert(CGF.CurFn && "No function in current CodeGenFunction.")((CGF.CurFn && "No function in current CodeGenFunction."
) ? static_cast<void> (0) : __assert_fail ("CGF.CurFn && \"No function in current CodeGenFunction.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1445, __PRETTY_FUNCTION__))
;
1446 // If the OpenMPIRBuilder is used we need to use it for all thread id calls as
1447 // the clang invariants used below might be broken.
1448 if (CGM.getLangOpts().OpenMPIRBuilder) {
1449 SmallString<128> Buffer;
1450 OMPBuilder.updateToLocation(CGF.Builder.saveIP());
1451 auto *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(
1452 getIdentStringFromSourceLocation(CGF, Loc, Buffer));
1453 return OMPBuilder.getOrCreateThreadID(
1454 OMPBuilder.getOrCreateIdent(SrcLocStr));
1455 }
1456
1457 llvm::Value *ThreadID = nullptr;
1458 // Check whether we've already cached a load of the thread id in this
1459 // function.
1460 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1461 if (I != OpenMPLocThreadIDMap.end()) {
1462 ThreadID = I->second.ThreadID;
1463 if (ThreadID != nullptr)
1464 return ThreadID;
1465 }
1466 // If exceptions are enabled, do not use parameter to avoid possible crash.
1467 if (auto *OMPRegionInfo =
1468 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1469 if (OMPRegionInfo->getThreadIDVariable()) {
1470 // Check if this an outlined function with thread id passed as argument.
1471 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1472 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent();
1473 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1474 !CGF.getLangOpts().CXXExceptions ||
1475 CGF.Builder.GetInsertBlock() == TopBlock ||
1476 !isa<llvm::Instruction>(LVal.getPointer(CGF)) ||
1477 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1478 TopBlock ||
1479 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1480 CGF.Builder.GetInsertBlock()) {
1481 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
1482 // If value loaded in entry block, cache it and use it everywhere in
1483 // function.
1484 if (CGF.Builder.GetInsertBlock() == TopBlock) {
1485 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1486 Elem.second.ThreadID = ThreadID;
1487 }
1488 return ThreadID;
1489 }
1490 }
1491 }
1492
1493 // This is not an outlined function region - need to call __kmpc_int32
1494 // kmpc_global_thread_num(ident_t *loc).
1495 // Generate thread id value and cache this value for use across the
1496 // function.
1497 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1498 if (!Elem.second.ServiceInsertPt)
1499 setLocThreadIdInsertPt(CGF);
1500 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1501 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
1502 llvm::CallInst *Call = CGF.Builder.CreateCall(
1503 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
1504 OMPRTL___kmpc_global_thread_num),
1505 emitUpdateLocation(CGF, Loc));
1506 Call->setCallingConv(CGF.getRuntimeCC());
1507 Elem.second.ThreadID = Call;
1508 return Call;
1509}
1510
1511void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
1512 assert(CGF.CurFn && "No function in current CodeGenFunction.")((CGF.CurFn && "No function in current CodeGenFunction."
) ? static_cast<void> (0) : __assert_fail ("CGF.CurFn && \"No function in current CodeGenFunction.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1512, __PRETTY_FUNCTION__))
;
1513 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1514 clearLocThreadIdInsertPt(CGF);
1515 OpenMPLocThreadIDMap.erase(CGF.CurFn);
1516 }
1517 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
1518 for(const auto *D : FunctionUDRMap[CGF.CurFn])
1519 UDRMap.erase(D);
1520 FunctionUDRMap.erase(CGF.CurFn);
1521 }
1522 auto I = FunctionUDMMap.find(CGF.CurFn);
1523 if (I != FunctionUDMMap.end()) {
1524 for(const auto *D : I->second)
1525 UDMMap.erase(D);
1526 FunctionUDMMap.erase(I);
1527 }
1528 LastprivateConditionalToTypes.erase(CGF.CurFn);
1529 FunctionToUntiedTaskStackMap.erase(CGF.CurFn);
1530}
1531
1532llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
1533 return OMPBuilder.IdentPtr;
1534}
1535
1536llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
1537 if (!Kmpc_MicroTy) {
1538 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1539 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1540 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1541 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1542 }
1543 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1544}
1545
1546llvm::FunctionCallee
1547CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
1548 assert((IVSize == 32 || IVSize == 64) &&(((IVSize == 32 || IVSize == 64) && "IV size is not compatible with the omp runtime"
) ? static_cast<void> (0) : __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1549, __PRETTY_FUNCTION__))
1549 "IV size is not compatible with the omp runtime")(((IVSize == 32 || IVSize == 64) && "IV size is not compatible with the omp runtime"
) ? static_cast<void> (0) : __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1549, __PRETTY_FUNCTION__))
;
1550 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
1551 : "__kmpc_for_static_init_4u")
1552 : (IVSigned ? "__kmpc_for_static_init_8"
1553 : "__kmpc_for_static_init_8u");
1554 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1555 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
1556 llvm::Type *TypeParams[] = {
1557 getIdentTyPointerTy(), // loc
1558 CGM.Int32Ty, // tid
1559 CGM.Int32Ty, // schedtype
1560 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1561 PtrTy, // p_lower
1562 PtrTy, // p_upper
1563 PtrTy, // p_stride
1564 ITy, // incr
1565 ITy // chunk
1566 };
1567 auto *FnTy =
1568 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1569 return CGM.CreateRuntimeFunction(FnTy, Name);
1570}
1571
1572llvm::FunctionCallee
1573CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
1574 assert((IVSize == 32 || IVSize == 64) &&(((IVSize == 32 || IVSize == 64) && "IV size is not compatible with the omp runtime"
) ? static_cast<void> (0) : __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1575, __PRETTY_FUNCTION__))
1575 "IV size is not compatible with the omp runtime")(((IVSize == 32 || IVSize == 64) && "IV size is not compatible with the omp runtime"
) ? static_cast<void> (0) : __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1575, __PRETTY_FUNCTION__))
;
1576 StringRef Name =
1577 IVSize == 32
1578 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
1579 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
1580 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1581 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
1582 CGM.Int32Ty, // tid
1583 CGM.Int32Ty, // schedtype
1584 ITy, // lower
1585 ITy, // upper
1586 ITy, // stride
1587 ITy // chunk
1588 };
1589 auto *FnTy =
1590 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1591 return CGM.CreateRuntimeFunction(FnTy, Name);
1592}
1593
1594llvm::FunctionCallee
1595CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
1596 assert((IVSize == 32 || IVSize == 64) &&(((IVSize == 32 || IVSize == 64) && "IV size is not compatible with the omp runtime"
) ? static_cast<void> (0) : __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1597, __PRETTY_FUNCTION__))
1597 "IV size is not compatible with the omp runtime")(((IVSize == 32 || IVSize == 64) && "IV size is not compatible with the omp runtime"
) ? static_cast<void> (0) : __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1597, __PRETTY_FUNCTION__))
;
1598 StringRef Name =
1599 IVSize == 32
1600 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1601 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1602 llvm::Type *TypeParams[] = {
1603 getIdentTyPointerTy(), // loc
1604 CGM.Int32Ty, // tid
1605 };
1606 auto *FnTy =
1607 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1608 return CGM.CreateRuntimeFunction(FnTy, Name);
1609}
1610
1611llvm::FunctionCallee
1612CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
1613 assert((IVSize == 32 || IVSize == 64) &&(((IVSize == 32 || IVSize == 64) && "IV size is not compatible with the omp runtime"
) ? static_cast<void> (0) : __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1614, __PRETTY_FUNCTION__))
1614 "IV size is not compatible with the omp runtime")(((IVSize == 32 || IVSize == 64) && "IV size is not compatible with the omp runtime"
) ? static_cast<void> (0) : __assert_fail ("(IVSize == 32 || IVSize == 64) && \"IV size is not compatible with the omp runtime\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1614, __PRETTY_FUNCTION__))
;
1615 StringRef Name =
1616 IVSize == 32
1617 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1618 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1619 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1620 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
1621 llvm::Type *TypeParams[] = {
1622 getIdentTyPointerTy(), // loc
1623 CGM.Int32Ty, // tid
1624 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1625 PtrTy, // p_lower
1626 PtrTy, // p_upper
1627 PtrTy // p_stride
1628 };
1629 auto *FnTy =
1630 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1631 return CGM.CreateRuntimeFunction(FnTy, Name);
1632}
1633
1634/// Obtain information that uniquely identifies a target entry. This
1635/// consists of the file and device IDs as well as line number associated with
1636/// the relevant entry source location.
1637static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
1638 unsigned &DeviceID, unsigned &FileID,
1639 unsigned &LineNum) {
1640 SourceManager &SM = C.getSourceManager();
1641
1642 // The loc should be always valid and have a file ID (the user cannot use
1643 // #pragma directives in macros)
1644
1645 assert(Loc.isValid() && "Source location is expected to be always valid.")((Loc.isValid() && "Source location is expected to be always valid."
) ? static_cast<void> (0) : __assert_fail ("Loc.isValid() && \"Source location is expected to be always valid.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1645, __PRETTY_FUNCTION__))
;
1646
1647 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
1648 assert(PLoc.isValid() && "Source location is expected to be always valid.")((PLoc.isValid() && "Source location is expected to be always valid."
) ? static_cast<void> (0) : __assert_fail ("PLoc.isValid() && \"Source location is expected to be always valid.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1648, __PRETTY_FUNCTION__))
;
1649
1650 llvm::sys::fs::UniqueID ID;
1651 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
1652 SM.getDiagnostics().Report(diag::err_cannot_open_file)
1653 << PLoc.getFilename() << EC.message();
1654
1655 DeviceID = ID.getDevice();
1656 FileID = ID.getFile();
1657 LineNum = PLoc.getLine();
1658}
1659
1660Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
1661 if (CGM.getLangOpts().OpenMPSimd)
1662 return Address::invalid();
1663 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
1664 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1665 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
1666 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
1667 HasRequiresUnifiedSharedMemory))) {
1668 SmallString<64> PtrName;
1669 {
1670 llvm::raw_svector_ostream OS(PtrName);
1671 OS << CGM.getMangledName(GlobalDecl(VD));
1672 if (!VD->isExternallyVisible()) {
1673 unsigned DeviceID, FileID, Line;
1674 getTargetEntryUniqueInfo(CGM.getContext(),
1675 VD->getCanonicalDecl()->getBeginLoc(),
1676 DeviceID, FileID, Line);
1677 OS << llvm::format("_%x", FileID);
1678 }
1679 OS << "_decl_tgt_ref_ptr";
1680 }
1681 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
1682 if (!Ptr) {
1683 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
1684 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
1685 PtrName);
1686
1687 auto *GV = cast<llvm::GlobalVariable>(Ptr);
1688 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
1689
1690 if (!CGM.getLangOpts().OpenMPIsDevice)
1691 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
1692 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
1693 }
1694 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
1695 }
1696 return Address::invalid();
1697}
1698
1699llvm::Constant *
1700CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
1701 assert(!CGM.getLangOpts().OpenMPUseTLS ||((!CGM.getLangOpts().OpenMPUseTLS || !CGM.getContext().getTargetInfo
().isTLSSupported()) ? static_cast<void> (0) : __assert_fail
("!CGM.getLangOpts().OpenMPUseTLS || !CGM.getContext().getTargetInfo().isTLSSupported()"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1702, __PRETTY_FUNCTION__))
1702 !CGM.getContext().getTargetInfo().isTLSSupported())((!CGM.getLangOpts().OpenMPUseTLS || !CGM.getContext().getTargetInfo
().isTLSSupported()) ? static_cast<void> (0) : __assert_fail
("!CGM.getLangOpts().OpenMPUseTLS || !CGM.getContext().getTargetInfo().isTLSSupported()"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1702, __PRETTY_FUNCTION__))
;
1703 // Lookup the entry, lazily creating it if necessary.
1704 std::string Suffix = getName({"cache", ""});
1705 return getOrCreateInternalVariable(
1706 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
1707}
1708
1709Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1710 const VarDecl *VD,
1711 Address VDAddr,
1712 SourceLocation Loc) {
1713 if (CGM.getLangOpts().OpenMPUseTLS &&
1714 CGM.getContext().getTargetInfo().isTLSSupported())
1715 return VDAddr;
1716
1717 llvm::Type *VarTy = VDAddr.getElementType();
1718 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1719 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1720 CGM.Int8PtrTy),
1721 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1722 getOrCreateThreadPrivateCache(VD)};
1723 return Address(CGF.EmitRuntimeCall(
1724 OMPBuilder.getOrCreateRuntimeFunction(
1725 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1726 Args),
1727 VDAddr.getAlignment());
1728}
1729
1730void CGOpenMPRuntime::emitThreadPrivateVarInit(
1731 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
1732 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1733 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1734 // library.
1735 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
1736 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
1737 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1738 OMPLoc);
1739 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1740 // to register constructor/destructor for variable.
1741 llvm::Value *Args[] = {
1742 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
1743 Ctor, CopyCtor, Dtor};
1744 CGF.EmitRuntimeCall(
1745 OMPBuilder.getOrCreateRuntimeFunction(
1746 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1747 Args);
1748}
1749
1750llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
1751 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
1752 bool PerformInit, CodeGenFunction *CGF) {
1753 if (CGM.getLangOpts().OpenMPUseTLS &&
1754 CGM.getContext().getTargetInfo().isTLSSupported())
1755 return nullptr;
1756
1757 VD = VD->getDefinition(CGM.getContext());
1758 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
1759 QualType ASTTy = VD->getType();
1760
1761 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1762 const Expr *Init = VD->getAnyInitializer();
1763 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1764 // Generate function that re-emits the declaration's initializer into the
1765 // threadprivate copy of the variable VD
1766 CodeGenFunction CtorCGF(CGM);
1767 FunctionArgList Args;
1768 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
1769 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
1770 ImplicitParamDecl::Other);
1771 Args.push_back(&Dst);
1772
1773 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1774 CGM.getContext().VoidPtrTy, Args);
1775 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1776 std::string Name = getName({"__kmpc_global_ctor_", ""});
1777 llvm::Function *Fn =
1778 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1779 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1780 Args, Loc, Loc);
1781 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
1782 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
1783 CGM.getContext().VoidPtrTy, Dst.getLocation());
1784 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1785 Arg = CtorCGF.Builder.CreateElementBitCast(
1786 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
1787 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1788 /*IsInitializer=*/true);
1789 ArgVal = CtorCGF.EmitLoadOfScalar(
1790 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
1791 CGM.getContext().VoidPtrTy, Dst.getLocation());
1792 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1793 CtorCGF.FinishFunction();
1794 Ctor = Fn;
1795 }
1796 if (VD->getType().isDestructedType() != QualType::DK_none) {
1797 // Generate function that emits destructor call for the threadprivate copy
1798 // of the variable VD
1799 CodeGenFunction DtorCGF(CGM);
1800 FunctionArgList Args;
1801 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
1802 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
1803 ImplicitParamDecl::Other);
1804 Args.push_back(&Dst);
1805
1806 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1807 CGM.getContext().VoidTy, Args);
1808 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1809 std::string Name = getName({"__kmpc_global_dtor_", ""});
1810 llvm::Function *Fn =
1811 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1812 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
1813 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1814 Loc, Loc);
1815 // Create a scope with an artificial location for the body of this function.
1816 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
1817 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
1818 DtorCGF.GetAddrOfLocalVar(&Dst),
1819 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1820 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
1821 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1822 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1823 DtorCGF.FinishFunction();
1824 Dtor = Fn;
1825 }
1826 // Do not emit init function if it is not required.
1827 if (!Ctor && !Dtor)
1828 return nullptr;
1829
1830 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1831 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1832 /*isVarArg=*/false)
1833 ->getPointerTo();
1834 // Copying constructor for the threadprivate variable.
1835 // Must be NULL - reserved by runtime, but currently it requires that this
1836 // parameter is always NULL. Otherwise it fires assertion.
1837 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1838 if (Ctor == nullptr) {
1839 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1840 /*isVarArg=*/false)
1841 ->getPointerTo();
1842 Ctor = llvm::Constant::getNullValue(CtorTy);
1843 }
1844 if (Dtor == nullptr) {
1845 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1846 /*isVarArg=*/false)
1847 ->getPointerTo();
1848 Dtor = llvm::Constant::getNullValue(DtorTy);
1849 }
1850 if (!CGF) {
1851 auto *InitFunctionTy =
1852 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1853 std::string Name = getName({"__omp_threadprivate_init_", ""});
1854 llvm::Function *InitFunction = CGM.CreateGlobalInitOrCleanUpFunction(
1855 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
1856 CodeGenFunction InitCGF(CGM);
1857 FunctionArgList ArgList;
1858 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1859 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1860 Loc, Loc);
1861 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
1862 InitCGF.FinishFunction();
1863 return InitFunction;
1864 }
1865 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
1866 }
1867 return nullptr;
1868}
1869
1870bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
1871 llvm::GlobalVariable *Addr,
1872 bool PerformInit) {
1873 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
1874 !CGM.getLangOpts().OpenMPIsDevice)
1875 return false;
1876 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
1877 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1878 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
1879 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
1880 HasRequiresUnifiedSharedMemory))
1881 return CGM.getLangOpts().OpenMPIsDevice;
1882 VD = VD->getDefinition(CGM.getContext());
1883 assert(VD && "Unknown VarDecl")((VD && "Unknown VarDecl") ? static_cast<void> (
0) : __assert_fail ("VD && \"Unknown VarDecl\"", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1883, __PRETTY_FUNCTION__))
;
1884
1885 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
1886 return CGM.getLangOpts().OpenMPIsDevice;
1887
1888 QualType ASTTy = VD->getType();
1889 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
1890
1891 // Produce the unique prefix to identify the new target regions. We use
1892 // the source location of the variable declaration which we know to not
1893 // conflict with any target region.
1894 unsigned DeviceID;
1895 unsigned FileID;
1896 unsigned Line;
1897 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
1898 SmallString<128> Buffer, Out;
1899 {
1900 llvm::raw_svector_ostream OS(Buffer);
1901 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
1902 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
1903 }
1904
1905 const Expr *Init = VD->getAnyInitializer();
1906 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1907 llvm::Constant *Ctor;
1908 llvm::Constant *ID;
1909 if (CGM.getLangOpts().OpenMPIsDevice) {
1910 // Generate function that re-emits the declaration's initializer into
1911 // the threadprivate copy of the variable VD
1912 CodeGenFunction CtorCGF(CGM);
1913
1914 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
1915 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1916 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction(
1917 FTy, Twine(Buffer, "_ctor"), FI, Loc);
1918 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
1919 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
1920 FunctionArgList(), Loc, Loc);
1921 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
1922 CtorCGF.EmitAnyExprToMem(Init,
1923 Address(Addr, CGM.getContext().getDeclAlign(VD)),
1924 Init->getType().getQualifiers(),
1925 /*IsInitializer=*/true);
1926 CtorCGF.FinishFunction();
1927 Ctor = Fn;
1928 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
1929 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
1930 } else {
1931 Ctor = new llvm::GlobalVariable(
1932 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
1933 llvm::GlobalValue::PrivateLinkage,
1934 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
1935 ID = Ctor;
1936 }
1937
1938 // Register the information for the entry associated with the constructor.
1939 Out.clear();
1940 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
1941 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
1942 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
1943 }
1944 if (VD->getType().isDestructedType() != QualType::DK_none) {
1945 llvm::Constant *Dtor;
1946 llvm::Constant *ID;
1947 if (CGM.getLangOpts().OpenMPIsDevice) {
1948 // Generate function that emits destructor call for the threadprivate
1949 // copy of the variable VD
1950 CodeGenFunction DtorCGF(CGM);
1951
1952 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
1953 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1954 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction(
1955 FTy, Twine(Buffer, "_dtor"), FI, Loc);
1956 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
1957 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
1958 FunctionArgList(), Loc, Loc);
1959 // Create a scope with an artificial location for the body of this
1960 // function.
1961 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
1962 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
1963 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1964 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1965 DtorCGF.FinishFunction();
1966 Dtor = Fn;
1967 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
1968 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
1969 } else {
1970 Dtor = new llvm::GlobalVariable(
1971 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
1972 llvm::GlobalValue::PrivateLinkage,
1973 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
1974 ID = Dtor;
1975 }
1976 // Register the information for the entry associated with the destructor.
1977 Out.clear();
1978 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
1979 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
1980 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
1981 }
1982 return CGM.getLangOpts().OpenMPIsDevice;
1983}
1984
1985Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
1986 QualType VarType,
1987 StringRef Name) {
1988 std::string Suffix = getName({"artificial", ""});
1989 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
1990 llvm::Value *GAddr =
1991 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
1992 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS &&
1993 CGM.getTarget().isTLSSupported()) {
1994 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true);
1995 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType));
1996 }
1997 std::string CacheSuffix = getName({"cache", ""});
1998 llvm::Value *Args[] = {
1999 emitUpdateLocation(CGF, SourceLocation()),
2000 getThreadID(CGF, SourceLocation()),
2001 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
2002 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
2003 /*isSigned=*/false),
2004 getOrCreateInternalVariable(
2005 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
2006 return Address(
2007 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2008 CGF.EmitRuntimeCall(
2009 OMPBuilder.getOrCreateRuntimeFunction(
2010 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
2011 Args),
2012 VarLVType->getPointerTo(/*AddrSpace=*/0)),
2013 CGM.getContext().getTypeAlignInChars(VarType));
2014}
2015
2016void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond,
2017 const RegionCodeGenTy &ThenGen,
2018 const RegionCodeGenTy &ElseGen) {
2019 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
2020
2021 // If the condition constant folds and can be elided, try to avoid emitting
2022 // the condition and the dead arm of the if/else.
2023 bool CondConstant;
2024 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
10
Assuming the condition is true
11
Taking true branch
2025 if (CondConstant)
12
Assuming 'CondConstant' is true
13
Taking true branch
2026 ThenGen(CGF);
14
Calling 'RegionCodeGenTy::operator()'
2027 else
2028 ElseGen(CGF);
2029 return;
2030 }
2031
2032 // Otherwise, the condition did not fold, or we couldn't elide it. Just
2033 // emit the conditional branch.
2034 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
2035 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
2036 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
2037 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
2038
2039 // Emit the 'then' code.
2040 CGF.EmitBlock(ThenBlock);
2041 ThenGen(CGF);
2042 CGF.EmitBranch(ContBlock);
2043 // Emit the 'else' code if present.
2044 // There is no need to emit line number for unconditional branch.
2045 (void)ApplyDebugLocation::CreateEmpty(CGF);
2046 CGF.EmitBlock(ElseBlock);
2047 ElseGen(CGF);
2048 // There is no need to emit line number for unconditional branch.
2049 (void)ApplyDebugLocation::CreateEmpty(CGF);
2050 CGF.EmitBranch(ContBlock);
2051 // Emit the continuation block for code after the if.
2052 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
2053}
2054
2055void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
2056 llvm::Function *OutlinedFn,
2057 ArrayRef<llvm::Value *> CapturedVars,
2058 const Expr *IfCond) {
2059 if (!CGF.HaveInsertPoint())
2060 return;
2061 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
2062 auto &M = CGM.getModule();
2063 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
2064 this](CodeGenFunction &CGF, PrePostActionTy &) {
2065 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
2066 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
2067 llvm::Value *Args[] = {
2068 RTLoc,
2069 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
2070 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
2071 llvm::SmallVector<llvm::Value *, 16> RealArgs;
2072 RealArgs.append(std::begin(Args), std::end(Args));
2073 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2074
2075 llvm::FunctionCallee RTLFn =
2076 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
2077 CGF.EmitRuntimeCall(RTLFn, RealArgs);
2078 };
2079 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2080 this](CodeGenFunction &CGF, PrePostActionTy &) {
2081 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
2082 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
2083 // Build calls:
2084 // __kmpc_serialized_parallel(&Loc, GTid);
2085 llvm::Value *Args[] = {RTLoc, ThreadID};
2086 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2087 M, OMPRTL___kmpc_serialized_parallel),
2088 Args);
2089
2090 // OutlinedFn(&GTid, &zero_bound, CapturedStruct);
2091 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
2092 Address ZeroAddrBound =
2093 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
2094 /*Name=*/".bound.zero.addr");
2095 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0));
2096 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
2097 // ThreadId for serialized parallels is 0.
2098 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
2099 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer());
2100 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2101 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
2102
2103 // __kmpc_end_serialized_parallel(&Loc, GTid);
2104 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
2105 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2106 M, OMPRTL___kmpc_end_serialized_parallel),
2107 EndArgs);
2108 };
2109 if (IfCond) {
2110 emitIfClause(CGF, IfCond, ThenGen, ElseGen);
2111 } else {
2112 RegionCodeGenTy ThenRCG(ThenGen);
2113 ThenRCG(CGF);
2114 }
2115}
2116
2117// If we're inside an (outlined) parallel region, use the region info's
2118// thread-ID variable (it is passed in a first argument of the outlined function
2119// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
2120// regular serial code region, get thread ID by calling kmp_int32
2121// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
2122// return the address of that temp.
2123Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
2124 SourceLocation Loc) {
2125 if (auto *OMPRegionInfo =
2126 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
2127 if (OMPRegionInfo->getThreadIDVariable())
2128 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF);
2129
2130 llvm::Value *ThreadID = getThreadID(CGF, Loc);
2131 QualType Int32Ty =
2132 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
2133 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
2134 CGF.EmitStoreOfScalar(ThreadID,
2135 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
2136
2137 return ThreadIDTemp;
2138}
2139
2140llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
2141 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
2142 SmallString<256> Buffer;
2143 llvm::raw_svector_ostream Out(Buffer);
2144 Out << Name;
2145 StringRef RuntimeName = Out.str();
2146 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
2147 if (Elem.second) {
2148 assert(Elem.second->getType()->getPointerElementType() == Ty &&((Elem.second->getType()->getPointerElementType() == Ty
&& "OMP internal variable has different type than requested"
) ? static_cast<void> (0) : __assert_fail ("Elem.second->getType()->getPointerElementType() == Ty && \"OMP internal variable has different type than requested\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2149, __PRETTY_FUNCTION__))
2149 "OMP internal variable has different type than requested")((Elem.second->getType()->getPointerElementType() == Ty
&& "OMP internal variable has different type than requested"
) ? static_cast<void> (0) : __assert_fail ("Elem.second->getType()->getPointerElementType() == Ty && \"OMP internal variable has different type than requested\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2149, __PRETTY_FUNCTION__))
;
2150 return &*Elem.second;
2151 }
2152
2153 return Elem.second = new llvm::GlobalVariable(
2154 CGM.getModule(), Ty, /*IsConstant*/ false,
2155 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
2156 Elem.first(), /*InsertBefore=*/nullptr,
2157 llvm::GlobalValue::NotThreadLocal, AddressSpace);
2158}
2159
2160llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
2161 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
2162 std::string Name = getName({Prefix, "var"});
2163 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
2164}
2165
2166namespace {
2167/// Common pre(post)-action for different OpenMP constructs.
2168class CommonActionTy final : public PrePostActionTy {
2169 llvm::FunctionCallee EnterCallee;
2170 ArrayRef<llvm::Value *> EnterArgs;
2171 llvm::FunctionCallee ExitCallee;
2172 ArrayRef<llvm::Value *> ExitArgs;
2173 bool Conditional;
2174 llvm::BasicBlock *ContBlock = nullptr;
2175
2176public:
2177 CommonActionTy(llvm::FunctionCallee EnterCallee,
2178 ArrayRef<llvm::Value *> EnterArgs,
2179 llvm::FunctionCallee ExitCallee,
2180 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
2181 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2182 ExitArgs(ExitArgs), Conditional(Conditional) {}
2183 void Enter(CodeGenFunction &CGF) override {
2184 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
2185 if (Conditional) {
2186 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
2187 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
2188 ContBlock = CGF.createBasicBlock("omp_if.end");
2189 // Generate the branch (If-stmt)
2190 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2191 CGF.EmitBlock(ThenBlock);
2192 }
2193 }
2194 void Done(CodeGenFunction &CGF) {
2195 // Emit the rest of blocks/branches
2196 CGF.EmitBranch(ContBlock);
2197 CGF.EmitBlock(ContBlock, true);
2198 }
2199 void Exit(CodeGenFunction &CGF) override {
2200 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
2201 }
2202};
2203} // anonymous namespace
2204
2205void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
2206 StringRef CriticalName,
2207 const RegionCodeGenTy &CriticalOpGen,
2208 SourceLocation Loc, const Expr *Hint) {
2209 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
2210 // CriticalOpGen();
2211 // __kmpc_end_critical(ident_t *, gtid, Lock);
2212 // Prepare arguments and build a call to __kmpc_critical
2213 if (!CGF.HaveInsertPoint())
2214 return;
2215 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2216 getCriticalRegionLock(CriticalName)};
2217 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
2218 std::end(Args));
2219 if (Hint) {
2220 EnterArgs.push_back(CGF.Builder.CreateIntCast(
2221 CGF.EmitScalarExpr(Hint), CGM.Int32Ty, /*isSigned=*/false));
2222 }
2223 CommonActionTy Action(
2224 OMPBuilder.getOrCreateRuntimeFunction(
2225 CGM.getModule(),
2226 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical),
2227 EnterArgs,
2228 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
2229 OMPRTL___kmpc_end_critical),
2230 Args);
2231 CriticalOpGen.setAction(Action);
2232 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
2233}
2234
2235void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
2236 const RegionCodeGenTy &MasterOpGen,
2237 SourceLocation Loc) {
2238 if (!CGF.HaveInsertPoint())
2239 return;
2240 // if(__kmpc_master(ident_t *, gtid)) {
2241 // MasterOpGen();
2242 // __kmpc_end_master(ident_t *, gtid);
2243 // }
2244 // Prepare arguments and build a call to __kmpc_master
2245 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2246 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2247 CGM.getModule(), OMPRTL___kmpc_master),
2248 Args,
2249 OMPBuilder.getOrCreateRuntimeFunction(
2250 CGM.getModule(), OMPRTL___kmpc_end_master),
2251 Args,
2252 /*Conditional=*/true);
2253 MasterOpGen.setAction(Action);
2254 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
2255 Action.Done(CGF);
2256}
2257
2258void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
2259 SourceLocation Loc) {
2260 if (!CGF.HaveInsertPoint())
2261 return;
2262 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
2263 OMPBuilder.CreateTaskyield(CGF.Builder);
2264 } else {
2265 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
2266 llvm::Value *Args[] = {
2267 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2268 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
2269 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2270 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2271 Args);
2272 }
2273
2274 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
2275 Region->emitUntiedSwitch(CGF);
2276}
2277
2278void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
2279 const RegionCodeGenTy &TaskgroupOpGen,
2280 SourceLocation Loc) {
2281 if (!CGF.HaveInsertPoint())
2282 return;
2283 // __kmpc_taskgroup(ident_t *, gtid);
2284 // TaskgroupOpGen();
2285 // __kmpc_end_taskgroup(ident_t *, gtid);
2286 // Prepare arguments and build a call to __kmpc_taskgroup
2287 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2288 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2289 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2290 Args,
2291 OMPBuilder.getOrCreateRuntimeFunction(
2292 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2293 Args);
2294 TaskgroupOpGen.setAction(Action);
2295 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
2296}
2297
2298/// Given an array of pointers to variables, project the address of a
2299/// given variable.
2300static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
2301 unsigned Index, const VarDecl *Var) {
2302 // Pull out the pointer to the variable.
2303 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
2304 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
2305
2306 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
2307 Addr = CGF.Builder.CreateElementBitCast(
2308 Addr, CGF.ConvertTypeForMem(Var->getType()));
2309 return Addr;
2310}
2311
2312static llvm::Value *emitCopyprivateCopyFunction(
2313 CodeGenModule &CGM, llvm::Type *ArgsType,
2314 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
2315 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
2316 SourceLocation Loc) {
2317 ASTContext &C = CGM.getContext();
2318 // void copy_func(void *LHSArg, void *RHSArg);
2319 FunctionArgList Args;
2320 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
2321 ImplicitParamDecl::Other);
2322 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
2323 ImplicitParamDecl::Other);
2324 Args.push_back(&LHSArg);
2325 Args.push_back(&RHSArg);
2326 const auto &CGFI =
2327 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
2328 std::string Name =
2329 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
2330 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
2331 llvm::GlobalValue::InternalLinkage, Name,
2332 &CGM.getModule());
2333 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
2334 Fn->setDoesNotRecurse();
2335 CodeGenFunction CGF(CGM);
2336 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
2337 // Dest = (void*[n])(LHSArg);
2338 // Src = (void*[n])(RHSArg);
2339 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2340 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2341 ArgsType), CGF.getPointerAlign());
2342 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2343 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2344 ArgsType), CGF.getPointerAlign());
2345 // *(Type0*)Dst[0] = *(Type0*)Src[0];
2346 // *(Type1*)Dst[1] = *(Type1*)Src[1];
2347 // ...
2348 // *(Typen*)Dst[n] = *(Typen*)Src[n];
2349 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2350 const auto *DestVar =
2351 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2352 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
2353
2354 const auto *SrcVar =
2355 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2356 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
2357
2358 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2359 QualType Type = VD->getType();
2360 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2361 }
2362 CGF.FinishFunction();
2363 return Fn;
2364}
2365
2366void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
2367 const RegionCodeGenTy &SingleOpGen,
2368 SourceLocation Loc,
2369 ArrayRef<const Expr *> CopyprivateVars,
2370 ArrayRef<const Expr *> SrcExprs,
2371 ArrayRef<const Expr *> DstExprs,
2372 ArrayRef<const Expr *> AssignmentOps) {
2373 if (!CGF.HaveInsertPoint())
2374 return;
2375 assert(CopyprivateVars.size() == SrcExprs.size() &&((CopyprivateVars.size() == SrcExprs.size() && CopyprivateVars
.size() == DstExprs.size() && CopyprivateVars.size() ==
AssignmentOps.size()) ? static_cast<void> (0) : __assert_fail
("CopyprivateVars.size() == SrcExprs.size() && CopyprivateVars.size() == DstExprs.size() && CopyprivateVars.size() == AssignmentOps.size()"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2377, __PRETTY_FUNCTION__))
2376 CopyprivateVars.size() == DstExprs.size() &&((CopyprivateVars.size() == SrcExprs.size() && CopyprivateVars
.size() == DstExprs.size() && CopyprivateVars.size() ==
AssignmentOps.size()) ? static_cast<void> (0) : __assert_fail
("CopyprivateVars.size() == SrcExprs.size() && CopyprivateVars.size() == DstExprs.size() && CopyprivateVars.size() == AssignmentOps.size()"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2377, __PRETTY_FUNCTION__))
2377 CopyprivateVars.size() == AssignmentOps.size())((CopyprivateVars.size() == SrcExprs.size() && CopyprivateVars
.size() == DstExprs.size() && CopyprivateVars.size() ==
AssignmentOps.size()) ? static_cast<void> (0) : __assert_fail
("CopyprivateVars.size() == SrcExprs.size() && CopyprivateVars.size() == DstExprs.size() && CopyprivateVars.size() == AssignmentOps.size()"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2377, __PRETTY_FUNCTION__))
;
2378 ASTContext &C = CGM.getContext();
2379 // int32 did_it = 0;
2380 // if(__kmpc_single(ident_t *, gtid)) {
2381 // SingleOpGen();
2382 // __kmpc_end_single(ident_t *, gtid);
2383 // did_it = 1;
2384 // }
2385 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2386 // <copy_func>, did_it);
2387
2388 Address DidIt = Address::invalid();
2389 if (!CopyprivateVars.empty()) {
2390 // int32 did_it = 0;
2391 QualType KmpInt32Ty =
2392 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2393 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
2394 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
2395 }
2396 // Prepare arguments and build a call to __kmpc_single
2397 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2398 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2399 CGM.getModule(), OMPRTL___kmpc_single),
2400 Args,
2401 OMPBuilder.getOrCreateRuntimeFunction(
2402 CGM.getModule(), OMPRTL___kmpc_end_single),
2403 Args,
2404 /*Conditional=*/true);
2405 SingleOpGen.setAction(Action);
2406 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
2407 if (DidIt.isValid()) {
2408 // did_it = 1;
2409 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
2410 }
2411 Action.Done(CGF);
2412 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2413 // <copy_func>, did_it);
2414 if (DidIt.isValid()) {
2415 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
2416 QualType CopyprivateArrayTy = C.getConstantArrayType(
2417 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
2418 /*IndexTypeQuals=*/0);
2419 // Create a list of all private variables for copyprivate.
2420 Address CopyprivateList =
2421 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
2422 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2423 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
2424 CGF.Builder.CreateStore(
2425 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2426 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF),
2427 CGF.VoidPtrTy),
2428 Elem);
2429 }
2430 // Build function that copies private values from single region to all other
2431 // threads in the corresponding parallel region.
2432 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
2433 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
2434 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
2435 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
2436 Address CL =
2437 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
2438 CGF.VoidPtrTy);
2439 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
2440 llvm::Value *Args[] = {
2441 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
2442 getThreadID(CGF, Loc), // i32 <gtid>
2443 BufSize, // size_t <buf_size>
2444 CL.getPointer(), // void *<copyprivate list>
2445 CpyFn, // void (*) (void *, void *) <copy_func>
2446 DidItVal // i32 did_it
2447 };
2448 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2449 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2450 Args);
2451 }
2452}
2453
2454void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
2455 const RegionCodeGenTy &OrderedOpGen,
2456 SourceLocation Loc, bool IsThreads) {
2457 if (!CGF.HaveInsertPoint())
2458 return;
2459 // __kmpc_ordered(ident_t *, gtid);
2460 // OrderedOpGen();
2461 // __kmpc_end_ordered(ident_t *, gtid);
2462 // Prepare arguments and build a call to __kmpc_ordered
2463 if (IsThreads) {
2464 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2465 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2466 CGM.getModule(), OMPRTL___kmpc_ordered),
2467 Args,
2468 OMPBuilder.getOrCreateRuntimeFunction(
2469 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2470 Args);
2471 OrderedOpGen.setAction(Action);
2472 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2473 return;
2474 }
2475 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2476}
2477
2478unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
2479 unsigned Flags;
2480 if (Kind == OMPD_for)
2481 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2482 else if (Kind == OMPD_sections)
2483 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2484 else if (Kind == OMPD_single)
2485 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2486 else if (Kind == OMPD_barrier)
2487 Flags = OMP_IDENT_BARRIER_EXPL;
2488 else
2489 Flags = OMP_IDENT_BARRIER_IMPL;
2490 return Flags;
2491}
2492
2493void CGOpenMPRuntime::getDefaultScheduleAndChunk(
2494 CodeGenFunction &CGF, const OMPLoopDirective &S,
2495 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
2496 // Check if the loop directive is actually a doacross loop directive. In this
2497 // case choose static, 1 schedule.
2498 if (llvm::any_of(
2499 S.getClausesOfKind<OMPOrderedClause>(),
2500 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
2501 ScheduleKind = OMPC_SCHEDULE_static;
2502 // Chunk size is 1 in this case.
2503 llvm::APInt ChunkSize(32, 1);
2504 ChunkExpr = IntegerLiteral::Create(
2505 CGF.getContext(), ChunkSize,
2506 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
2507 SourceLocation());
2508 }
2509}
2510
2511void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
2512 OpenMPDirectiveKind Kind, bool EmitChecks,
2513 bool ForceSimpleCall) {
2514 // Check if we should use the OMPBuilder
2515 auto *OMPRegionInfo =
2516 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
2517 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
2518 CGF.Builder.restoreIP(OMPBuilder.CreateBarrier(
2519 CGF.Builder, Kind, ForceSimpleCall, EmitChecks));
2520 return;
2521 }
2522
2523 if (!CGF.HaveInsertPoint())
2524 return;
2525 // Build call __kmpc_cancel_barrier(loc, thread_id);
2526 // Build call __kmpc_barrier(loc, thread_id);
2527 unsigned Flags = getDefaultFlagsForBarriers(Kind);
2528 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
2529 // thread_id);
2530 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
2531 getThreadID(CGF, Loc)};
2532 if (OMPRegionInfo) {
2533 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2534 llvm::Value *Result = CGF.EmitRuntimeCall(
2535 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
2536 OMPRTL___kmpc_cancel_barrier),
2537 Args);
2538 if (EmitChecks) {
2539 // if (__kmpc_cancel_barrier()) {
2540 // exit from construct;
2541 // }
2542 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
2543 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
2544 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
2545 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2546 CGF.EmitBlock(ExitBB);
2547 // exit from construct;
2548 CodeGenFunction::JumpDest CancelDestination =
2549 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
2550 CGF.EmitBranchThroughCleanup(CancelDestination);
2551 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2552 }
2553 return;
2554 }
2555 }
2556 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2557 CGM.getModule(), OMPRTL___kmpc_barrier),
2558 Args);
2559}
2560
2561/// Map the OpenMP loop schedule to the runtime enumeration.
2562static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
2563 bool Chunked, bool Ordered) {
2564 switch (ScheduleKind) {
2565 case OMPC_SCHEDULE_static:
2566 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2567 : (Ordered ? OMP_ord_static : OMP_sch_static);
2568 case OMPC_SCHEDULE_dynamic:
2569 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2570 case OMPC_SCHEDULE_guided:
2571 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2572 case OMPC_SCHEDULE_runtime:
2573 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2574 case OMPC_SCHEDULE_auto:
2575 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2576 case OMPC_SCHEDULE_unknown:
2577 assert(!Chunked && "chunk was specified but schedule kind not known")((!Chunked && "chunk was specified but schedule kind not known"
) ? static_cast<void> (0) : __assert_fail ("!Chunked && \"chunk was specified but schedule kind not known\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2577, __PRETTY_FUNCTION__))
;
2578 return Ordered ? OMP_ord_static : OMP_sch_static;
2579 }
2580 llvm_unreachable("Unexpected runtime schedule")::llvm::llvm_unreachable_internal("Unexpected runtime schedule"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2580)
;
2581}
2582
2583/// Map the OpenMP distribute schedule to the runtime enumeration.
2584static OpenMPSchedType
2585getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
2586 // only static is allowed for dist_schedule
2587 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2588}
2589
2590bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
2591 bool Chunked) const {
2592 OpenMPSchedType Schedule =
2593 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
2594 return Schedule == OMP_sch_static;
2595}
2596
2597bool CGOpenMPRuntime::isStaticNonchunked(
2598 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2599 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2600 return Schedule == OMP_dist_sch_static;
2601}
2602
2603bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
2604 bool Chunked) const {
2605 OpenMPSchedType Schedule =
2606 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
2607 return Schedule == OMP_sch_static_chunked;
2608}
2609
2610bool CGOpenMPRuntime::isStaticChunked(
2611 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2612 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2613 return Schedule == OMP_dist_sch_static_chunked;
2614}
2615
2616bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
2617 OpenMPSchedType Schedule =
2618 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
2619 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here")((Schedule != OMP_sch_static_chunked && "cannot be chunked here"
) ? static_cast<void> (0) : __assert_fail ("Schedule != OMP_sch_static_chunked && \"cannot be chunked here\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2619, __PRETTY_FUNCTION__))
;
2620 return Schedule != OMP_sch_static;
2621}
2622
2623static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
2624 OpenMPScheduleClauseModifier M1,
2625 OpenMPScheduleClauseModifier M2) {
2626 int Modifier = 0;
2627 switch (M1) {
2628 case OMPC_SCHEDULE_MODIFIER_monotonic:
2629 Modifier = OMP_sch_modifier_monotonic;
2630 break;
2631 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2632 Modifier = OMP_sch_modifier_nonmonotonic;
2633 break;
2634 case OMPC_SCHEDULE_MODIFIER_simd:
2635 if (Schedule == OMP_sch_static_chunked)
2636 Schedule = OMP_sch_static_balanced_chunked;
2637 break;
2638 case OMPC_SCHEDULE_MODIFIER_last:
2639 case OMPC_SCHEDULE_MODIFIER_unknown:
2640 break;
2641 }
2642 switch (M2) {
2643 case OMPC_SCHEDULE_MODIFIER_monotonic:
2644 Modifier = OMP_sch_modifier_monotonic;
2645 break;
2646 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2647 Modifier = OMP_sch_modifier_nonmonotonic;
2648 break;
2649 case OMPC_SCHEDULE_MODIFIER_simd:
2650 if (Schedule == OMP_sch_static_chunked)
2651 Schedule = OMP_sch_static_balanced_chunked;
2652 break;
2653 case OMPC_SCHEDULE_MODIFIER_last:
2654 case OMPC_SCHEDULE_MODIFIER_unknown:
2655 break;
2656 }
2657 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
2658 // If the static schedule kind is specified or if the ordered clause is
2659 // specified, and if the nonmonotonic modifier is not specified, the effect is
2660 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
2661 // modifier is specified, the effect is as if the nonmonotonic modifier is
2662 // specified.
2663 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
2664 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2665 Schedule == OMP_sch_static_balanced_chunked ||
2666 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2667 Schedule == OMP_dist_sch_static_chunked ||
2668 Schedule == OMP_dist_sch_static))
2669 Modifier = OMP_sch_modifier_nonmonotonic;
2670 }
2671 return Schedule | Modifier;
2672}
2673
2674void CGOpenMPRuntime::emitForDispatchInit(
2675 CodeGenFunction &CGF, SourceLocation Loc,
2676 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
2677 bool Ordered, const DispatchRTInput &DispatchValues) {
2678 if (!CGF.HaveInsertPoint())
2679 return;
2680 OpenMPSchedType Schedule = getRuntimeSchedule(
2681 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
2682 assert(Ordered ||((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)) ? static_cast<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)"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2685, __PRETTY_FUNCTION__))
2683 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&((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)) ? static_cast<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)"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2685, __PRETTY_FUNCTION__))
2684 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&((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)) ? static_cast<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)"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2685, __PRETTY_FUNCTION__))
2685 Schedule != OMP_sch_static_balanced_chunked))((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)) ? static_cast<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)"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2685, __PRETTY_FUNCTION__))
;
2686 // Call __kmpc_dispatch_init(
2687 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
2688 // kmp_int[32|64] lower, kmp_int[32|64] upper,
2689 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
2690
2691 // If the Chunk was not specified in the clause - use default value 1.
2692 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
2693 : CGF.Builder.getIntN(IVSize, 1);
2694 llvm::Value *Args[] = {
2695 emitUpdateLocation(CGF, Loc),
2696 getThreadID(CGF, Loc),
2697 CGF.Builder.getInt32(addMonoNonMonoModifier(
2698 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
2699 DispatchValues.LB, // Lower
2700 DispatchValues.UB, // Upper
2701 CGF.Builder.getIntN(IVSize, 1), // Stride
2702 Chunk // Chunk
2703 };
2704 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
2705}
2706
2707static void emitForStaticInitCall(
2708 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2709 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2710 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
2711 const CGOpenMPRuntime::StaticRTInput &Values) {
2712 if (!CGF.HaveInsertPoint())
2713 return;
2714
2715 assert(!Values.Ordered)((!Values.Ordered) ? static_cast<void> (0) : __assert_fail
("!Values.Ordered", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2715, __PRETTY_FUNCTION__))
;
2716 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||((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
) ? static_cast<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"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2720, __PRETTY_FUNCTION__))
2717 Schedule == OMP_sch_static_balanced_chunked ||((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
) ? static_cast<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"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2720, __PRETTY_FUNCTION__))
2718 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||((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
) ? static_cast<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"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2720, __PRETTY_FUNCTION__))
2719 Schedule == OMP_dist_sch_static ||((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
) ? static_cast<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"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2720, __PRETTY_FUNCTION__))
2720 Schedule == OMP_dist_sch_static_chunked)((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
) ? static_cast<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"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2720, __PRETTY_FUNCTION__))
;
2721
2722 // Call __kmpc_for_static_init(
2723 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
2724 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
2725 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
2726 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
2727 llvm::Value *Chunk = Values.Chunk;
2728 if (Chunk == nullptr) {
2729 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||(((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
Schedule == OMP_dist_sch_static) && "expected static non-chunked schedule"
) ? static_cast<void> (0) : __assert_fail ("(Schedule == OMP_sch_static || Schedule == OMP_ord_static || Schedule == OMP_dist_sch_static) && \"expected static non-chunked schedule\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2731, __PRETTY_FUNCTION__))
2730 Schedule == OMP_dist_sch_static) &&(((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
Schedule == OMP_dist_sch_static) && "expected static non-chunked schedule"
) ? static_cast<void> (0) : __assert_fail ("(Schedule == OMP_sch_static || Schedule == OMP_ord_static || Schedule == OMP_dist_sch_static) && \"expected static non-chunked schedule\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2731, __PRETTY_FUNCTION__))
2731 "expected static non-chunked schedule")(((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
Schedule == OMP_dist_sch_static) && "expected static non-chunked schedule"
) ? static_cast<void> (0) : __assert_fail ("(Schedule == OMP_sch_static || Schedule == OMP_ord_static || Schedule == OMP_dist_sch_static) && \"expected static non-chunked schedule\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2731, __PRETTY_FUNCTION__))
;
2732 // If the Chunk was not specified in the clause - use default value 1.
2733 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
2734 } else {
2735 assert((Schedule == OMP_sch_static_chunked ||(((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") ? static_cast
<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2739, __PRETTY_FUNCTION__))
2736 Schedule == OMP_sch_static_balanced_chunked ||(((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") ? static_cast
<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2739, __PRETTY_FUNCTION__))
2737 Schedule == OMP_ord_static_chunked ||(((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") ? static_cast
<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2739, __PRETTY_FUNCTION__))
2738 Schedule == OMP_dist_sch_static_chunked) &&(((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") ? static_cast
<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2739, __PRETTY_FUNCTION__))
2739 "expected static chunked schedule")(((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") ? static_cast
<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2739, __PRETTY_FUNCTION__))
;
2740 }
2741 llvm::Value *Args[] = {
2742 UpdateLocation,
2743 ThreadId,
2744 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
2745 M2)), // Schedule type
2746 Values.IL.getPointer(), // &isLastIter
2747 Values.LB.getPointer(), // &LB
2748 Values.UB.getPointer(), // &UB
2749 Values.ST.getPointer(), // &Stride
2750 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
2751 Chunk // Chunk
2752 };
2753 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
2754}
2755
2756void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
2757 SourceLocation Loc,
2758 OpenMPDirectiveKind DKind,
2759 const OpenMPScheduleTy &ScheduleKind,
2760 const StaticRTInput &Values) {
2761 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
2762 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
2763 assert(isOpenMPWorksharingDirective(DKind) &&((isOpenMPWorksharingDirective(DKind) && "Expected loop-based or sections-based directive."
) ? static_cast<void> (0) : __assert_fail ("isOpenMPWorksharingDirective(DKind) && \"Expected loop-based or sections-based directive.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2764, __PRETTY_FUNCTION__))
2764 "Expected loop-based or sections-based directive.")((isOpenMPWorksharingDirective(DKind) && "Expected loop-based or sections-based directive."
) ? static_cast<void> (0) : __assert_fail ("isOpenMPWorksharingDirective(DKind) && \"Expected loop-based or sections-based directive.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2764, __PRETTY_FUNCTION__))
;
2765 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
2766 isOpenMPLoopDirective(DKind)
2767 ? OMP_IDENT_WORK_LOOP
2768 : OMP_IDENT_WORK_SECTIONS);
2769 llvm::Value *ThreadId = getThreadID(CGF, Loc);
2770 llvm::FunctionCallee StaticInitFunction =
2771 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
2772 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
2773 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
2774 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
2775}
2776
2777void CGOpenMPRuntime::emitDistributeStaticInit(
2778 CodeGenFunction &CGF, SourceLocation Loc,
2779 OpenMPDistScheduleClauseKind SchedKind,
2780 const CGOpenMPRuntime::StaticRTInput &Values) {
2781 OpenMPSchedType ScheduleNum =
2782 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
2783 llvm::Value *UpdatedLocation =
2784 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
2785 llvm::Value *ThreadId = getThreadID(CGF, Loc);
2786 llvm::FunctionCallee StaticInitFunction =
2787 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
2788 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
2789 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
2790 OMPC_SCHEDULE_MODIFIER_unknown, Values);
2791}
2792
2793void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
2794 SourceLocation Loc,
2795 OpenMPDirectiveKind DKind) {
2796 if (!CGF.HaveInsertPoint())
2797 return;
2798 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
2799 llvm::Value *Args[] = {
2800 emitUpdateLocation(CGF, Loc,
2801 isOpenMPDistributeDirective(DKind)
2802 ? OMP_IDENT_WORK_DISTRIBUTE
2803 : isOpenMPLoopDirective(DKind)
2804 ? OMP_IDENT_WORK_LOOP
2805 : OMP_IDENT_WORK_SECTIONS),
2806 getThreadID(CGF, Loc)};
2807 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
2808 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2809 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2810 Args);
2811}
2812
2813void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
2814 SourceLocation Loc,
2815 unsigned IVSize,
2816 bool IVSigned) {
2817 if (!CGF.HaveInsertPoint())
2818 return;
2819 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
2820 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2821 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
2822}
2823
2824llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
2825 SourceLocation Loc, unsigned IVSize,
2826 bool IVSigned, Address IL,
2827 Address LB, Address UB,
2828 Address ST) {
2829 // Call __kmpc_dispatch_next(
2830 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2831 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2832 // kmp_int[32|64] *p_stride);
2833 llvm::Value *Args[] = {
2834 emitUpdateLocation(CGF, Loc),
2835 getThreadID(CGF, Loc),
2836 IL.getPointer(), // &isLastIter
2837 LB.getPointer(), // &Lower
2838 UB.getPointer(), // &Upper
2839 ST.getPointer() // &Stride
2840 };
2841 llvm::Value *Call =
2842 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
2843 return CGF.EmitScalarConversion(
2844 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
2845 CGF.getContext().BoolTy, Loc);
2846}
2847
2848void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
2849 llvm::Value *NumThreads,
2850 SourceLocation Loc) {
2851 if (!CGF.HaveInsertPoint())
2852 return;
2853 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
2854 llvm::Value *Args[] = {
2855 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2856 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
2857 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2858 CGM.getModule(), OMPRTL___kmpc_push_num_threads),
2859 Args);
2860}
2861
2862void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
2863 ProcBindKind ProcBind,
2864 SourceLocation Loc) {
2865 if (!CGF.HaveInsertPoint())
2866 return;
2867 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value.")((ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."
) ? static_cast<void> (0) : __assert_fail ("ProcBind != OMP_PROC_BIND_unknown && \"Unsupported proc_bind value.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2867, __PRETTY_FUNCTION__))
;
2868 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
2869 llvm::Value *Args[] = {
2870 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2871 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)};
2872 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2873 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2874 Args);
2875}
2876
2877void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
2878 SourceLocation Loc, llvm::AtomicOrdering AO) {
2879 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
2880 OMPBuilder.CreateFlush(CGF.Builder);
2881 } else {
2882 if (!CGF.HaveInsertPoint())
2883 return;
2884 // Build call void __kmpc_flush(ident_t *loc)
2885 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2886 CGM.getModule(), OMPRTL___kmpc_flush),
2887 emitUpdateLocation(CGF, Loc));
2888 }
2889}
2890
2891namespace {
2892/// Indexes of fields for type kmp_task_t.
2893enum KmpTaskTFields {
2894 /// List of shared variables.
2895 KmpTaskTShareds,
2896 /// Task routine.
2897 KmpTaskTRoutine,
2898 /// Partition id for the untied tasks.
2899 KmpTaskTPartId,
2900 /// Function with call of destructors for private variables.
2901 Data1,
2902 /// Task priority.
2903 Data2,
2904 /// (Taskloops only) Lower bound.
2905 KmpTaskTLowerBound,
2906 /// (Taskloops only) Upper bound.
2907 KmpTaskTUpperBound,
2908 /// (Taskloops only) Stride.
2909 KmpTaskTStride,
2910 /// (Taskloops only) Is last iteration flag.
2911 KmpTaskTLastIter,
2912 /// (Taskloops only) Reduction data.
2913 KmpTaskTReductions,
2914};
2915} // anonymous namespace
2916
2917bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
2918 return OffloadEntriesTargetRegion.empty() &&
2919 OffloadEntriesDeviceGlobalVar.empty();
2920}
2921
2922/// Initialize target region entry.
2923void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2924 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2925 StringRef ParentName, unsigned LineNum,
2926 unsigned Order) {
2927 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "((CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
"only required for the device " "code generation.") ? static_cast
<void> (0) : __assert_fail ("CGM.getLangOpts().OpenMPIsDevice && \"Initialization of entries is \" \"only required for the device \" \"code generation.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2929, __PRETTY_FUNCTION__))
2928 "only required for the device "((CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
"only required for the device " "code generation.") ? static_cast
<void> (0) : __assert_fail ("CGM.getLangOpts().OpenMPIsDevice && \"Initialization of entries is \" \"only required for the device \" \"code generation.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2929, __PRETTY_FUNCTION__))
2929 "code generation.")((CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
"only required for the device " "code generation.") ? static_cast
<void> (0) : __assert_fail ("CGM.getLangOpts().OpenMPIsDevice && \"Initialization of entries is \" \"only required for the device \" \"code generation.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2929, __PRETTY_FUNCTION__))
;
2930 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
2931 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
2932 OMPTargetRegionEntryTargetRegion);
2933 ++OffloadingEntriesNum;
2934}
2935
2936void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2937 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2938 StringRef ParentName, unsigned LineNum,
2939 llvm::Constant *Addr, llvm::Constant *ID,
2940 OMPTargetRegionEntryKind Flags) {
2941 // If we are emitting code for a target, the entry is already initialized,
2942 // only has to be registered.
2943 if (CGM.getLangOpts().OpenMPIsDevice) {
2944 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
2945 unsigned DiagID = CGM.getDiags().getCustomDiagID(
2946 DiagnosticsEngine::Error,
2947 "Unable to find target region on line '%0' in the device code.");
2948 CGM.getDiags().Report(DiagID) << LineNum;
2949 return;
2950 }
2951 auto &Entry =
2952 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
2953 assert(Entry.isValid() && "Entry not initialized!")((Entry.isValid() && "Entry not initialized!") ? static_cast
<void> (0) : __assert_fail ("Entry.isValid() && \"Entry not initialized!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2953, __PRETTY_FUNCTION__))
;
2954 Entry.setAddress(Addr);
2955 Entry.setID(ID);
2956 Entry.setFlags(Flags);
2957 } else {
2958 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
2959 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
2960 ++OffloadingEntriesNum;
2961 }
2962}
2963
2964bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
2965 unsigned DeviceID, unsigned FileID, StringRef ParentName,
2966 unsigned LineNum) const {
2967 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
2968 if (PerDevice == OffloadEntriesTargetRegion.end())
2969 return false;
2970 auto PerFile = PerDevice->second.find(FileID);
2971 if (PerFile == PerDevice->second.end())
2972 return false;
2973 auto PerParentName = PerFile->second.find(ParentName);
2974 if (PerParentName == PerFile->second.end())
2975 return false;
2976 auto PerLine = PerParentName->second.find(LineNum);
2977 if (PerLine == PerParentName->second.end())
2978 return false;
2979 // Fail if this entry is already registered.
2980 if (PerLine->second.getAddress() || PerLine->second.getID())
2981 return false;
2982 return true;
2983}
2984
2985void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
2986 const OffloadTargetRegionEntryInfoActTy &Action) {
2987 // Scan all target region entries and perform the provided action.
2988 for (const auto &D : OffloadEntriesTargetRegion)
2989 for (const auto &F : D.second)
2990 for (const auto &P : F.second)
2991 for (const auto &L : P.second)
2992 Action(D.first, F.first, P.first(), L.first, L.second);
2993}
2994
2995void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2996 initializeDeviceGlobalVarEntryInfo(StringRef Name,
2997 OMPTargetGlobalVarEntryKind Flags,
2998 unsigned Order) {
2999 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "((CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
"only required for the device " "code generation.") ? static_cast
<void> (0) : __assert_fail ("CGM.getLangOpts().OpenMPIsDevice && \"Initialization of entries is \" \"only required for the device \" \"code generation.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3001, __PRETTY_FUNCTION__))
3000 "only required for the device "((CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
"only required for the device " "code generation.") ? static_cast
<void> (0) : __assert_fail ("CGM.getLangOpts().OpenMPIsDevice && \"Initialization of entries is \" \"only required for the device \" \"code generation.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3001, __PRETTY_FUNCTION__))
3001 "code generation.")((CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
"only required for the device " "code generation.") ? static_cast
<void> (0) : __assert_fail ("CGM.getLangOpts().OpenMPIsDevice && \"Initialization of entries is \" \"only required for the device \" \"code generation.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3001, __PRETTY_FUNCTION__))
;
3002 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3003 ++OffloadingEntriesNum;
3004}
3005
3006void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3007 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3008 CharUnits VarSize,
3009 OMPTargetGlobalVarEntryKind Flags,
3010 llvm::GlobalValue::LinkageTypes Linkage) {
3011 if (CGM.getLangOpts().OpenMPIsDevice) {
3012 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3013 assert(Entry.isValid() && Entry.getFlags() == Flags &&((Entry.isValid() && Entry.getFlags() == Flags &&
"Entry not initialized!") ? static_cast<void> (0) : __assert_fail
("Entry.isValid() && Entry.getFlags() == Flags && \"Entry not initialized!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3014, __PRETTY_FUNCTION__))
3014 "Entry not initialized!")((Entry.isValid() && Entry.getFlags() == Flags &&
"Entry not initialized!") ? static_cast<void> (0) : __assert_fail
("Entry.isValid() && Entry.getFlags() == Flags && \"Entry not initialized!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3014, __PRETTY_FUNCTION__))
;
3015 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&(((!Entry.getAddress() || Entry.getAddress() == Addr) &&
"Resetting with the new address.") ? static_cast<void>
(0) : __assert_fail ("(!Entry.getAddress() || Entry.getAddress() == Addr) && \"Resetting with the new address.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3016, __PRETTY_FUNCTION__))
3016 "Resetting with the new address.")(((!Entry.getAddress() || Entry.getAddress() == Addr) &&
"Resetting with the new address.") ? static_cast<void>
(0) : __assert_fail ("(!Entry.getAddress() || Entry.getAddress() == Addr) && \"Resetting with the new address.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3016, __PRETTY_FUNCTION__))
;
3017 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3018 if (Entry.getVarSize().isZero()) {
3019 Entry.setVarSize(VarSize);
3020 Entry.setLinkage(Linkage);
3021 }
3022 return;
3023 }
3024 Entry.setVarSize(VarSize);
3025 Entry.setLinkage(Linkage);
3026 Entry.setAddress(Addr);
3027 } else {
3028 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3029 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3030 assert(Entry.isValid() && Entry.getFlags() == Flags &&((Entry.isValid() && Entry.getFlags() == Flags &&
"Entry not initialized!") ? static_cast<void> (0) : __assert_fail
("Entry.isValid() && Entry.getFlags() == Flags && \"Entry not initialized!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3031, __PRETTY_FUNCTION__))
3031 "Entry not initialized!")((Entry.isValid() && Entry.getFlags() == Flags &&
"Entry not initialized!") ? static_cast<void> (0) : __assert_fail
("Entry.isValid() && Entry.getFlags() == Flags && \"Entry not initialized!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3031, __PRETTY_FUNCTION__))
;
3032 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&(((!Entry.getAddress() || Entry.getAddress() == Addr) &&
"Resetting with the new address.") ? static_cast<void>
(0) : __assert_fail ("(!Entry.getAddress() || Entry.getAddress() == Addr) && \"Resetting with the new address.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3033, __PRETTY_FUNCTION__))
3033 "Resetting with the new address.")(((!Entry.getAddress() || Entry.getAddress() == Addr) &&
"Resetting with the new address.") ? static_cast<void>
(0) : __assert_fail ("(!Entry.getAddress() || Entry.getAddress() == Addr) && \"Resetting with the new address.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3033, __PRETTY_FUNCTION__))
;
3034 if (Entry.getVarSize().isZero()) {
3035 Entry.setVarSize(VarSize);
3036 Entry.setLinkage(Linkage);
3037 }
3038 return;
3039 }
3040 OffloadEntriesDeviceGlobalVar.try_emplace(
3041 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
3042 ++OffloadingEntriesNum;
3043 }
3044}
3045
3046void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3047 actOnDeviceGlobalVarEntriesInfo(
3048 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
3049 // Scan all target region entries and perform the provided action.
3050 for (const auto &E : OffloadEntriesDeviceGlobalVar)
3051 Action(E.getKey(), E.getValue());
3052}
3053
3054void CGOpenMPRuntime::createOffloadEntry(
3055 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
3056 llvm::GlobalValue::LinkageTypes Linkage) {
3057 StringRef Name = Addr->getName();
3058 llvm::Module &M = CGM.getModule();
3059 llvm::LLVMContext &C = M.getContext();
3060
3061 // Create constant string with the name.
3062 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
3063
3064 std::string StringName = getName({"omp_offloading", "entry_name"});
3065 auto *Str = new llvm::GlobalVariable(
3066 M, StrPtrInit->getType(), /*isConstant=*/true,
3067 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
3068 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
3069
3070 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
3071 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
3072 llvm::ConstantInt::get(CGM.SizeTy, Size),
3073 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
3074 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
3075 std::string EntryName = getName({"omp_offloading", "entry", ""});
3076 llvm::GlobalVariable *Entry = createGlobalStruct(
3077 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
3078 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
3079
3080 // The entry has to be created in the section the linker expects it to be.
3081 Entry->setSection("omp_offloading_entries");
3082}
3083
3084void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
3085 // Emit the offloading entries and metadata so that the device codegen side
3086 // can easily figure out what to emit. The produced metadata looks like
3087 // this:
3088 //
3089 // !omp_offload.info = !{!1, ...}
3090 //
3091 // Right now we only generate metadata for function that contain target
3092 // regions.
3093
3094 // If we are in simd mode or there are no entries, we don't need to do
3095 // anything.
3096 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty())
3097 return;
3098
3099 llvm::Module &M = CGM.getModule();
3100 llvm::LLVMContext &C = M.getContext();
3101 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *,
3102 SourceLocation, StringRef>,
3103 16>
3104 OrderedEntries(OffloadEntriesInfoManager.size());
3105 llvm::SmallVector<StringRef, 16> ParentFunctions(
3106 OffloadEntriesInfoManager.size());
3107
3108 // Auxiliary methods to create metadata values and strings.
3109 auto &&GetMDInt = [this](unsigned V) {
3110 return llvm::ConstantAsMetadata::get(
3111 llvm::ConstantInt::get(CGM.Int32Ty, V));
3112 };
3113
3114 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
3115
3116 // Create the offloading info metadata node.
3117 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
3118
3119 // Create function that emits metadata for each target region entry;
3120 auto &&TargetRegionMetadataEmitter =
3121 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt,
3122 &GetMDString](
3123 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3124 unsigned Line,
3125 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
3126 // Generate metadata for target regions. Each entry of this metadata
3127 // contains:
3128 // - Entry 0 -> Kind of this type of metadata (0).
3129 // - Entry 1 -> Device ID of the file where the entry was identified.
3130 // - Entry 2 -> File ID of the file where the entry was identified.
3131 // - Entry 3 -> Mangled name of the function where the entry was
3132 // identified.
3133 // - Entry 4 -> Line in the file where the entry was identified.
3134 // - Entry 5 -> Order the entry was created.
3135 // The first element of the metadata node is the kind.
3136 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
3137 GetMDInt(FileID), GetMDString(ParentName),
3138 GetMDInt(Line), GetMDInt(E.getOrder())};
3139
3140 SourceLocation Loc;
3141 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
3142 E = CGM.getContext().getSourceManager().fileinfo_end();
3143 I != E; ++I) {
3144 if (I->getFirst()->getUniqueID().getDevice() == DeviceID &&
3145 I->getFirst()->getUniqueID().getFile() == FileID) {
3146 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
3147 I->getFirst(), Line, 1);
3148 break;
3149 }
3150 }
3151 // Save this entry in the right position of the ordered entries array.
3152 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName);
3153 ParentFunctions[E.getOrder()] = ParentName;
3154
3155 // Add metadata to the named metadata node.
3156 MD->addOperand(llvm::MDNode::get(C, Ops));
3157 };
3158
3159 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
3160 TargetRegionMetadataEmitter);
3161
3162 // Create function that emits metadata for each device global variable entry;
3163 auto &&DeviceGlobalVarMetadataEmitter =
3164 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
3165 MD](StringRef MangledName,
3166 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
3167 &E) {
3168 // Generate metadata for global variables. Each entry of this metadata
3169 // contains:
3170 // - Entry 0 -> Kind of this type of metadata (1).
3171 // - Entry 1 -> Mangled name of the variable.
3172 // - Entry 2 -> Declare target kind.
3173 // - Entry 3 -> Order the entry was created.
3174 // The first element of the metadata node is the kind.
3175 llvm::Metadata *Ops[] = {
3176 GetMDInt(E.getKind()), GetMDString(MangledName),
3177 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
3178
3179 // Save this entry in the right position of the ordered entries array.
3180 OrderedEntries[E.getOrder()] =
3181 std::make_tuple(&E, SourceLocation(), MangledName);
3182
3183 // Add metadata to the named metadata node.
3184 MD->addOperand(llvm::MDNode::get(C, Ops));
3185 };
3186
3187 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
3188 DeviceGlobalVarMetadataEmitter);
3189
3190 for (const auto &E : OrderedEntries) {
3191 assert(std::get<0>(E) && "All ordered entries must exist!")((std::get<0>(E) && "All ordered entries must exist!"
) ? static_cast<void> (0) : __assert_fail ("std::get<0>(E) && \"All ordered entries must exist!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3191, __PRETTY_FUNCTION__))
;
3192 if (const auto *CE =
3193 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
3194 std::get<0>(E))) {
3195 if (!CE->getID() || !CE->getAddress()) {
3196 // Do not blame the entry if the parent funtion is not emitted.
3197 StringRef FnName = ParentFunctions[CE->getOrder()];
3198 if (!CGM.GetGlobalValue(FnName))
3199 continue;
3200 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3201 DiagnosticsEngine::Error,
3202 "Offloading entry for target region in %0 is incorrect: either the "
3203 "address or the ID is invalid.");
3204 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName;
3205 continue;
3206 }
3207 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
3208 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
3209 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy::
3210 OffloadEntryInfoDeviceGlobalVar>(
3211 std::get<0>(E))) {
3212 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
3213 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
3214 CE->getFlags());
3215 switch (Flags) {
3216 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
3217 if (CGM.getLangOpts().OpenMPIsDevice &&
3218 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
3219 continue;
3220 if (!CE->getAddress()) {
3221 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3222 DiagnosticsEngine::Error, "Offloading entry for declare target "
3223 "variable %0 is incorrect: the "
3224 "address is invalid.");
3225 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E);
3226 continue;
3227 }
3228 // The vaiable has no definition - no need to add the entry.
3229 if (CE->getVarSize().isZero())
3230 continue;
3231 break;
3232 }
3233 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
3234 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||((((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress
()) || (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress
())) && "Declaret target link address is set.") ? static_cast
<void> (0) : __assert_fail ("((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && \"Declaret target link address is set.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3236, __PRETTY_FUNCTION__))
3235 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&((((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress
()) || (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress
())) && "Declaret target link address is set.") ? static_cast
<void> (0) : __assert_fail ("((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && \"Declaret target link address is set.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3236, __PRETTY_FUNCTION__))
3236 "Declaret target link address is set.")((((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress
()) || (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress
())) && "Declaret target link address is set.") ? static_cast
<void> (0) : __assert_fail ("((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && \"Declaret target link address is set.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3236, __PRETTY_FUNCTION__))
;
3237 if (CGM.getLangOpts().OpenMPIsDevice)
3238 continue;
3239 if (!CE->getAddress()) {
3240 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3241 DiagnosticsEngine::Error,
3242 "Offloading entry for declare target variable is incorrect: the "
3243 "address is invalid.");
3244 CGM.getDiags().Report(DiagID);
3245 continue;
3246 }
3247 break;
3248 }
3249 createOffloadEntry(CE->getAddress(), CE->getAddress(),
3250 CE->getVarSize().getQuantity(), Flags,
3251 CE->getLinkage());
3252 } else {
3253 llvm_unreachable("Unsupported entry kind.")::llvm::llvm_unreachable_internal("Unsupported entry kind.", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3253)
;
3254 }
3255 }
3256}
3257
3258/// Loads all the offload entries information from the host IR
3259/// metadata.
3260void CGOpenMPRuntime::loadOffloadInfoMetadata() {
3261 // If we are in target mode, load the metadata from the host IR. This code has
3262 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
3263
3264 if (!CGM.getLangOpts().OpenMPIsDevice)
3265 return;
3266
3267 if (CGM.getLangOpts().OMPHostIRFile.empty())
3268 return;
3269
3270 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
3271 if (auto EC = Buf.getError()) {
3272 CGM.getDiags().Report(diag::err_cannot_open_file)
3273 << CGM.getLangOpts().OMPHostIRFile << EC.message();
3274 return;
3275 }
3276
3277 llvm::LLVMContext C;
3278 auto ME = expectedToErrorOrAndEmitErrors(
3279 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
3280
3281 if (auto EC = ME.getError()) {
3282 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3283 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
3284 CGM.getDiags().Report(DiagID)
3285 << CGM.getLangOpts().OMPHostIRFile << EC.message();
3286 return;
3287 }
3288
3289 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
3290 if (!MD)
3291 return;
3292
3293 for (llvm::MDNode *MN : MD->operands()) {
3294 auto &&GetMDInt = [MN](unsigned Idx) {
3295 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
3296 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
3297 };
3298
3299 auto &&GetMDString = [MN](unsigned Idx) {
3300 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
3301 return V->getString();
3302 };
3303
3304 switch (GetMDInt(0)) {
3305 default:
3306 llvm_unreachable("Unexpected metadata!")::llvm::llvm_unreachable_internal("Unexpected metadata!", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3306)
;
3307 break;
3308 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
3309 OffloadingEntryInfoTargetRegion:
3310 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
3311 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
3312 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
3313 /*Order=*/GetMDInt(5));
3314 break;
3315 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
3316 OffloadingEntryInfoDeviceGlobalVar:
3317 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
3318 /*MangledName=*/GetMDString(1),
3319 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
3320 /*Flags=*/GetMDInt(2)),
3321 /*Order=*/GetMDInt(3));
3322 break;
3323 }
3324 }
3325}
3326
3327void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
3328 if (!KmpRoutineEntryPtrTy) {
3329 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
3330 ASTContext &C = CGM.getContext();
3331 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
3332 FunctionProtoType::ExtProtoInfo EPI;
3333 KmpRoutineEntryPtrQTy = C.getPointerType(
3334 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3335 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
3336 }
3337}
3338
3339QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
3340 // Make sure the type of the entry is already created. This is the type we
3341 // have to create:
3342 // struct __tgt_offload_entry{
3343 // void *addr; // Pointer to the offload entry info.
3344 // // (function or global)
3345 // char *name; // Name of the function or global.
3346 // size_t size; // Size of the entry info (0 if it a function).
3347 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
3348 // int32_t reserved; // Reserved, to use by the runtime library.
3349 // };
3350 if (TgtOffloadEntryQTy.isNull()) {
3351 ASTContext &C = CGM.getContext();
3352 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
3353 RD->startDefinition();
3354 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3355 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
3356 addFieldToRecordDecl(C, RD, C.getSizeType());
3357 addFieldToRecordDecl(
3358 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
3359 addFieldToRecordDecl(
3360 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
3361 RD->completeDefinition();
3362 RD->addAttr(PackedAttr::CreateImplicit(C));
3363 TgtOffloadEntryQTy = C.getRecordType(RD);
3364 }
3365 return TgtOffloadEntryQTy;
3366}
3367
3368namespace {
3369struct PrivateHelpersTy {
3370 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original,
3371 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit)
3372 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3373 PrivateElemInit(PrivateElemInit) {}
3374 PrivateHelpersTy(const VarDecl *Original) : Original(Original) {}
3375 const Expr *OriginalRef = nullptr;
3376 const VarDecl *Original = nullptr;
3377 const VarDecl *PrivateCopy = nullptr;
3378 const VarDecl *PrivateElemInit = nullptr;
3379 bool isLocalPrivate() const {
3380 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3381 }
3382};
3383typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
3384} // anonymous namespace
3385
3386static bool isAllocatableDecl(const VarDecl *VD) {
3387 const VarDecl *CVD = VD->getCanonicalDecl();
3388 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
3389 return false;
3390 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
3391 // Use the default allocation.
3392 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
3393 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
3394 !AA->getAllocator());
3395}
3396
3397static RecordDecl *
3398createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
3399 if (!Privates.empty()) {
3400 ASTContext &C = CGM.getContext();
3401 // Build struct .kmp_privates_t. {
3402 // /* private vars */
3403 // };
3404 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
3405 RD->startDefinition();
3406 for (const auto &Pair : Privates) {
3407 const VarDecl *VD = Pair.second.Original;
3408 QualType Type = VD->getType().getNonReferenceType();
3409 // If the private variable is a local variable with lvalue ref type,
3410 // allocate the pointer instead of the pointee type.
3411 if (Pair.second.isLocalPrivate()) {
3412 if (VD->getType()->isLValueReferenceType())
3413 Type = C.getPointerType(Type);
3414 if (isAllocatableDecl(VD))
3415 Type = C.getPointerType(Type);
3416 }
3417 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
3418 if (VD->hasAttrs()) {
3419 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
3420 E(VD->getAttrs().end());
3421 I != E; ++I)
3422 FD->addAttr(*I);
3423 }
3424 }
3425 RD->completeDefinition();
3426 return RD;
3427 }
3428 return nullptr;
3429}
3430
3431static RecordDecl *
3432createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
3433 QualType KmpInt32Ty,
3434 QualType KmpRoutineEntryPointerQTy) {
3435 ASTContext &C = CGM.getContext();
3436 // Build struct kmp_task_t {
3437 // void * shareds;
3438 // kmp_routine_entry_t routine;
3439 // kmp_int32 part_id;
3440 // kmp_cmplrdata_t data1;
3441 // kmp_cmplrdata_t data2;
3442 // For taskloops additional fields:
3443 // kmp_uint64 lb;
3444 // kmp_uint64 ub;
3445 // kmp_int64 st;
3446 // kmp_int32 liter;
3447 // void * reductions;
3448 // };
3449 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
3450 UD->startDefinition();
3451 addFieldToRecordDecl(C, UD, KmpInt32Ty);
3452 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
3453 UD->completeDefinition();
3454 QualType KmpCmplrdataTy = C.getRecordType(UD);
3455 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
3456 RD->startDefinition();
3457 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3458 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
3459 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3460 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
3461 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
3462 if (isOpenMPTaskLoopDirective(Kind)) {
3463 QualType KmpUInt64Ty =
3464 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
3465 QualType KmpInt64Ty =
3466 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
3467 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
3468 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
3469 addFieldToRecordDecl(C, RD, KmpInt64Ty);
3470 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3471 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3472 }
3473 RD->completeDefinition();
3474 return RD;
3475}
3476
3477static RecordDecl *
3478createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
3479 ArrayRef<PrivateDataTy> Privates) {
3480 ASTContext &C = CGM.getContext();
3481 // Build struct kmp_task_t_with_privates {
3482 // kmp_task_t task_data;
3483 // .kmp_privates_t. privates;
3484 // };
3485 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
3486 RD->startDefinition();
3487 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
3488 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
3489 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
3490 RD->completeDefinition();
3491 return RD;
3492}
3493
3494/// Emit a proxy function which accepts kmp_task_t as the second
3495/// argument.
3496/// \code
3497/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
3498/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
3499/// For taskloops:
3500/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
3501/// tt->reductions, tt->shareds);
3502/// return 0;
3503/// }
3504/// \endcode
3505static llvm::Function *
3506emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
3507 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
3508 QualType KmpTaskTWithPrivatesPtrQTy,
3509 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
3510 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3511 llvm::Value *TaskPrivatesMap) {
3512 ASTContext &C = CGM.getContext();
3513 FunctionArgList Args;
3514 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
3515 ImplicitParamDecl::Other);
3516 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3517 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
3518 ImplicitParamDecl::Other);
3519 Args.push_back(&GtidArg);
3520 Args.push_back(&TaskTypeArg);
3521 const auto &TaskEntryFnInfo =
3522 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
3523 llvm::FunctionType *TaskEntryTy =
3524 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
3525 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
3526 auto *TaskEntry = llvm::Function::Create(
3527 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
3528 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
3529 TaskEntry->setDoesNotRecurse();
3530 CodeGenFunction CGF(CGM);
3531 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
3532 Loc, Loc);
3533
3534 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
3535 // tt,
3536 // For taskloops:
3537 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
3538 // tt->task_data.shareds);
3539 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
3540 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
3541 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3542 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3543 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3544 const auto *KmpTaskTWithPrivatesQTyRD =
3545 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3546 LValue Base =
3547 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
3548 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
3549 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3550 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
3551 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3552
3553 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3554 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
3555 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3556 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
3557 CGF.ConvertTypeForMem(SharedsPtrTy));
3558
3559 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3560 llvm::Value *PrivatesParam;
3561 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3562 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
3563 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3564 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy);
3565 } else {
3566 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3567 }
3568
3569 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
3570 TaskPrivatesMap,
3571 CGF.Builder
3572 .CreatePointerBitCastOrAddrSpaceCast(
3573 TDBase.getAddress(CGF), CGF.VoidPtrTy)
3574 .getPointer()};
3575 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
3576 std::end(CommonArgs));
3577 if (isOpenMPTaskLoopDirective(Kind)) {
3578 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3579 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
3580 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
3581 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3582 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
3583 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
3584 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3585 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
3586 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
3587 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3588 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
3589 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
3590 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3591 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
3592 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
3593 CallArgs.push_back(LBParam);
3594 CallArgs.push_back(UBParam);
3595 CallArgs.push_back(StParam);
3596 CallArgs.push_back(LIParam);
3597 CallArgs.push_back(RParam);
3598 }
3599 CallArgs.push_back(SharedsParam);
3600
3601 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
3602 CallArgs);
3603 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
3604 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
3605 CGF.FinishFunction();
3606 return TaskEntry;
3607}
3608
3609static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
3610 SourceLocation Loc,
3611 QualType KmpInt32Ty,
3612 QualType KmpTaskTWithPrivatesPtrQTy,
3613 QualType KmpTaskTWithPrivatesQTy) {
3614 ASTContext &C = CGM.getContext();
3615 FunctionArgList Args;
3616 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
3617 ImplicitParamDecl::Other);
3618 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3619 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
3620 ImplicitParamDecl::Other);
3621 Args.push_back(&GtidArg);
3622 Args.push_back(&TaskTypeArg);
3623 const auto &DestructorFnInfo =
3624 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
3625 llvm::FunctionType *DestructorFnTy =
3626 CGM.getTypes().GetFunctionType(DestructorFnInfo);
3627 std::string Name =
3628 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
3629 auto *DestructorFn =
3630 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3631 Name, &CGM.getModule());
3632 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
3633 DestructorFnInfo);
3634 DestructorFn->setDoesNotRecurse();
3635 CodeGenFunction CGF(CGM);
3636 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
3637 Args, Loc, Loc);
3638
3639 LValue Base = CGF.EmitLoadOfPointerLValue(
3640 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3641 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3642 const auto *KmpTaskTWithPrivatesQTyRD =
3643 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3644 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3645 Base = CGF.EmitLValueForField(Base, *FI);
3646 for (const auto *Field :
3647 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3648 if (QualType::DestructionKind DtorKind =
3649 Field->getType().isDestructedType()) {
3650 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
3651 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType());
3652 }
3653 }
3654 CGF.FinishFunction();
3655 return DestructorFn;
3656}
3657
3658/// Emit a privates mapping function for correct handling of private and
3659/// firstprivate variables.
3660/// \code
3661/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
3662/// **noalias priv1,..., <tyn> **noalias privn) {
3663/// *priv1 = &.privates.priv1;
3664/// ...;
3665/// *privn = &.privates.privn;
3666/// }
3667/// \endcode
3668static llvm::Value *
3669emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
3670 const OMPTaskDataTy &Data, QualType PrivatesQTy,
3671 ArrayRef<PrivateDataTy> Privates) {
3672 ASTContext &C = CGM.getContext();
3673 FunctionArgList Args;
3674 ImplicitParamDecl TaskPrivatesArg(
3675 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3676 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3677 ImplicitParamDecl::Other);
3678 Args.push_back(&TaskPrivatesArg);
3679 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, unsigned> PrivateVarsPos;
3680 unsigned Counter = 1;
3681 for (const Expr *E : Data.PrivateVars) {
3682 Args.push_back(ImplicitParamDecl::Create(
3683 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3684 C.getPointerType(C.getPointerType(E->getType()))
3685 .withConst()
3686 .withRestrict(),
3687 ImplicitParamDecl::Other));
3688 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3689 PrivateVarsPos[VD] = Counter;
3690 ++Counter;
3691 }
3692 for (const Expr *E : Data.FirstprivateVars) {
3693 Args.push_back(ImplicitParamDecl::Create(
3694 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3695 C.getPointerType(C.getPointerType(E->getType()))
3696 .withConst()
3697 .withRestrict(),
3698 ImplicitParamDecl::Other));
3699 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3700 PrivateVarsPos[VD] = Counter;
3701 ++Counter;
3702 }
3703 for (const Expr *E : Data.LastprivateVars) {
3704 Args.push_back(ImplicitParamDecl::Create(
3705 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3706 C.getPointerType(C.getPointerType(E->getType()))
3707 .withConst()
3708 .withRestrict(),
3709 ImplicitParamDecl::Other));
3710 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3711 PrivateVarsPos[VD] = Counter;
3712 ++Counter;
3713 }
3714 for (const VarDecl *VD : Data.PrivateLocals) {
3715 QualType Ty = VD->getType().getNonReferenceType();
3716 if (VD->getType()->isLValueReferenceType())
3717 Ty = C.getPointerType(Ty);
3718 if (isAllocatableDecl(VD))
3719 Ty = C.getPointerType(Ty);
3720 Args.push_back(ImplicitParamDecl::Create(
3721 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3722 C.getPointerType(C.getPointerType(Ty)).withConst().withRestrict(),
3723 ImplicitParamDecl::Other));
3724 PrivateVarsPos[VD] = Counter;
3725 ++Counter;
3726 }
3727 const auto &TaskPrivatesMapFnInfo =
3728 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
3729 llvm::FunctionType *TaskPrivatesMapTy =
3730 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
3731 std::string Name =
3732 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
3733 auto *TaskPrivatesMap = llvm::Function::Create(
3734 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3735 &CGM.getModule());
3736 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
3737 TaskPrivatesMapFnInfo);
3738 if (CGM.getLangOpts().Optimize) {
3739 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3740 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3741 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3742 }
3743 CodeGenFunction CGF(CGM);
3744 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
3745 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3746
3747 // *privi = &.privates.privi;
3748 LValue Base = CGF.EmitLoadOfPointerLValue(
3749 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
3750 TaskPrivatesArg.getType()->castAs<PointerType>());
3751 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
3752 Counter = 0;
3753 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
3754 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
3755 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
3756 LValue RefLVal =
3757 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
3758 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
3759 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>());
3760 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal);
3761 ++Counter;
3762 }
3763 CGF.FinishFunction();
3764 return TaskPrivatesMap;
3765}
3766
3767/// Emit initialization for private variables in task-based directives.
3768static void emitPrivatesInit(CodeGenFunction &CGF,
3769 const OMPExecutableDirective &D,
3770 Address KmpTaskSharedsPtr, LValue TDBase,
3771 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
3772 QualType SharedsTy, QualType SharedsPtrTy,
3773 const OMPTaskDataTy &Data,
3774 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
3775 ASTContext &C = CGF.getContext();
3776 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3777 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
3778 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
3779 ? OMPD_taskloop
3780 : OMPD_task;
3781 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
3782 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
3783 LValue SrcBase;
3784 bool IsTargetTask =
3785 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
3786 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
3787 // For target-based directives skip 4 firstprivate arrays BasePointersArray,
3788 // PointersArray, SizesArray, and MappersArray. The original variables for
3789 // these arrays are not captured and we get their addresses explicitly.
3790 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) ||
3791 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
3792 SrcBase = CGF.MakeAddrLValue(
3793 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3794 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
3795 SharedsTy);
3796 }
3797 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
3798 for (const PrivateDataTy &Pair : Privates) {
3799 // Do not initialize private locals.
3800 if (Pair.second.isLocalPrivate()) {
3801 ++FI;
3802 continue;
3803 }
3804 const VarDecl *VD = Pair.second.PrivateCopy;
3805 const Expr *Init = VD->getAnyInitializer();
3806 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
3807 !CGF.isTrivialInitializer(Init)))) {
3808 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
3809 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
3810 const VarDecl *OriginalVD = Pair.second.Original;
3811 // Check if the variable is the target-based BasePointersArray,
3812 // PointersArray, SizesArray, or MappersArray.
3813 LValue SharedRefLValue;
3814 QualType Type = PrivateLValue.getType();
3815 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
3816 if (IsTargetTask && !SharedField) {
3817 assert(isa<ImplicitParamDecl>(OriginalVD) &&((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.") ? static_cast<
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.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3824, __PRETTY_FUNCTION__))
3818 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&((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.") ? static_cast<
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.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3824, __PRETTY_FUNCTION__))
3819 cast<CapturedDecl>(OriginalVD->getDeclContext())((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.") ? static_cast<
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.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3824, __PRETTY_FUNCTION__))
3820 ->getNumParams() == 0 &&((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.") ? static_cast<
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.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3824, __PRETTY_FUNCTION__))
3821 isa<TranslationUnitDecl>(((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.") ? static_cast<
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.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3824, __PRETTY_FUNCTION__))
3822 cast<CapturedDecl>(OriginalVD->getDeclContext())((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.") ? static_cast<
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.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3824, __PRETTY_FUNCTION__))
3823 ->getDeclContext()) &&((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.") ? static_cast<
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.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3824, __PRETTY_FUNCTION__))
3824 "Expected artificial target data variable.")((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.") ? static_cast<
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.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3824, __PRETTY_FUNCTION__))
;
3825 SharedRefLValue =
3826 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
3827 } else if (ForDup) {
3828 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
3829 SharedRefLValue = CGF.MakeAddrLValue(
3830 Address(SharedRefLValue.getPointer(CGF),
3831 C.getDeclAlign(OriginalVD)),
3832 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
3833 SharedRefLValue.getTBAAInfo());
3834 } else if (CGF.LambdaCaptureFields.count(
3835 Pair.second.Original->getCanonicalDecl()) > 0 ||
3836 dyn_cast_or_null<BlockDecl>(CGF.CurCodeDecl)) {
3837 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef);
3838 } else {
3839 // Processing for implicitly captured variables.
3840 InlinedOpenMPRegionRAII Region(
3841 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown,
3842 /*HasCancel=*/false);
3843 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef);
3844 }
3845 if (Type->isArrayType()) {
3846 // Initialize firstprivate array.
3847 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
3848 // Perform simple memcpy.
3849 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
3850 } else {
3851 // Initialize firstprivate array using element-by-element
3852 // initialization.
3853 CGF.EmitOMPAggregateAssign(
3854 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF),
3855 Type,
3856 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
3857 Address SrcElement) {
3858 // Clean up any temporaries needed by the initialization.
3859 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3860 InitScope.addPrivate(
3861 Elem, [SrcElement]() -> Address { return SrcElement; });
3862 (void)InitScope.Privatize();
3863 // Emit initialization for single element.
3864 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3865 CGF, &CapturesInfo);
3866 CGF.EmitAnyExprToMem(Init, DestElement,
3867 Init->getType().getQualifiers(),
3868 /*IsInitializer=*/false);
3869 });
3870 }
3871 } else {
3872 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3873 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address {
3874 return SharedRefLValue.getAddress(CGF);
3875 });
3876 (void)InitScope.Privatize();
3877 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
3878 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
3879 /*capturedByInit=*/false);
3880 }
3881 } else {
3882 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
3883 }
3884 }
3885 ++FI;
3886 }
3887}
3888
3889/// Check if duplication function is required for taskloops.
3890static bool checkInitIsRequired(CodeGenFunction &CGF,
3891 ArrayRef<PrivateDataTy> Privates) {
3892 bool InitRequired = false;
3893 for (const PrivateDataTy &Pair : Privates) {
3894 if (Pair.second.isLocalPrivate())
3895 continue;
3896 const VarDecl *VD = Pair.second.PrivateCopy;
3897 const Expr *Init = VD->getAnyInitializer();
3898 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
3899 !CGF.isTrivialInitializer(Init));
3900 if (InitRequired)
3901 break;
3902 }
3903 return InitRequired;
3904}
3905
3906
3907/// Emit task_dup function (for initialization of
3908/// private/firstprivate/lastprivate vars and last_iter flag)
3909/// \code
3910/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
3911/// lastpriv) {
3912/// // setup lastprivate flag
3913/// task_dst->last = lastpriv;
3914/// // could be constructor calls here...
3915/// }
3916/// \endcode
3917static llvm::Value *
3918emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
3919 const OMPExecutableDirective &D,
3920 QualType KmpTaskTWithPrivatesPtrQTy,
3921 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
3922 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
3923 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
3924 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
3925 ASTContext &C = CGM.getContext();
3926 FunctionArgList Args;
3927 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3928 KmpTaskTWithPrivatesPtrQTy,
3929 ImplicitParamDecl::Other);
3930 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3931 KmpTaskTWithPrivatesPtrQTy,
3932 ImplicitParamDecl::Other);
3933 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
3934 ImplicitParamDecl::Other);
3935 Args.push_back(&DstArg);
3936 Args.push_back(&SrcArg);
3937 Args.push_back(&LastprivArg);
3938 const auto &TaskDupFnInfo =
3939 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
3940 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
3941 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
3942 auto *TaskDup = llvm::Function::Create(
3943 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
3944 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
3945 TaskDup->setDoesNotRecurse();
3946 CodeGenFunction CGF(CGM);
3947 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
3948 Loc);
3949
3950 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3951 CGF.GetAddrOfLocalVar(&DstArg),
3952 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3953 // task_dst->liter = lastpriv;
3954 if (WithLastIter) {
3955 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3956 LValue Base = CGF.EmitLValueForField(
3957 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
3958 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
3959 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
3960 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
3961 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
3962 }
3963
3964 // Emit initial values for private copies (if any).
3965 assert(!Privates.empty())((!Privates.empty()) ? static_cast<void> (0) : __assert_fail
("!Privates.empty()", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3965, __PRETTY_FUNCTION__))
;
3966 Address KmpTaskSharedsPtr = Address::invalid();
3967 if (!Data.FirstprivateVars.empty()) {
3968 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3969 CGF.GetAddrOfLocalVar(&SrcArg),
3970 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3971 LValue Base = CGF.EmitLValueForField(
3972 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
3973 KmpTaskSharedsPtr = Address(
3974 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
3975 Base, *std::next(KmpTaskTQTyRD->field_begin(),
3976 KmpTaskTShareds)),
3977 Loc),
3978 CGM.getNaturalTypeAlignment(SharedsTy));
3979 }
3980 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3981 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
3982 CGF.FinishFunction();
3983 return TaskDup;
3984}
3985
3986/// Checks if destructor function is required to be generated.
3987/// \return true if cleanups are required, false otherwise.
3988static bool
3989checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD,
3990 ArrayRef<PrivateDataTy> Privates) {
3991 for (const PrivateDataTy &P : Privates) {
3992 if (P.second.isLocalPrivate())
3993 continue;
3994 QualType Ty = P.second.Original->getType().getNonReferenceType();
3995 if (Ty.isDestructedType())
3996 return true;
3997 }
3998 return false;
3999}
4000
4001namespace {
4002/// Loop generator for OpenMP iterator expression.
4003class OMPIteratorGeneratorScope final
4004 : public CodeGenFunction::OMPPrivateScope {
4005 CodeGenFunction &CGF;
4006 const OMPIteratorExpr *E = nullptr;
4007 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
4008 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
4009 OMPIteratorGeneratorScope() = delete;
4010 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete;
4011
4012public:
4013 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E)
4014 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
4015 if (!E)
4016 return;
4017 SmallVector<llvm::Value *, 4> Uppers;
4018 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
4019 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
4020 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
4021 addPrivate(VD, [&CGF, VD]() {
4022 return CGF.CreateMemTemp(VD->getType(), VD->getName());
4023 });
4024 const OMPIteratorHelperData &HelperData = E->getHelper(I);
4025 addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() {
4026 return CGF.CreateMemTemp(HelperData.CounterVD->getType(),
4027 "counter.addr");
4028 });
4029 }
4030 Privatize();
4031
4032 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
4033 const OMPIteratorHelperData &HelperData = E->getHelper(I);
4034 LValue CLVal =
4035 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
4036 HelperData.CounterVD->getType());
4037 // Counter = 0;
4038 CGF.EmitStoreOfScalar(
4039 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0),
4040 CLVal);
4041 CodeGenFunction::JumpDest &ContDest =
4042 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont"));
4043 CodeGenFunction::JumpDest &ExitDest =
4044 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit"));
4045 // N = <number-of_iterations>;
4046 llvm::Value *N = Uppers[I];
4047 // cont:
4048 // if (Counter < N) goto body; else goto exit;
4049 CGF.EmitBlock(ContDest.getBlock());
4050 auto *CVal =
4051 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
4052 llvm::Value *Cmp =
4053 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
4054 ? CGF.Builder.CreateICmpSLT(CVal, N)
4055 : CGF.Builder.CreateICmpULT(CVal, N);
4056 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body");
4057 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
4058 // body:
4059 CGF.EmitBlock(BodyBB);
4060 // Iteri = Begini + Counter * Stepi;
4061 CGF.EmitIgnoredExpr(HelperData.Update);
4062 }
4063 }
4064 ~OMPIteratorGeneratorScope() {
4065 if (!E)
4066 return;
4067 for (unsigned I = E->numOfIterators(); I > 0; --I) {
4068 // Counter = Counter + 1;
4069 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1);
4070 CGF.EmitIgnoredExpr(HelperData.CounterUpdate);
4071 // goto cont;
4072 CGF.EmitBranchThroughCleanup(ContDests[I - 1]);
4073 // exit:
4074 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1);
4075 }
4076 }
4077};
4078} // namespace
4079
4080static std::pair<llvm::Value *, llvm::Value *>
4081getPointerAndSize(CodeGenFunction &CGF, const Expr *E) {
4082 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
4083 llvm::Value *Addr;
4084 if (OASE) {
4085 const Expr *Base = OASE->getBase();
4086 Addr = CGF.EmitScalarExpr(Base);
4087 } else {
4088 Addr = CGF.EmitLValue(E).getPointer(CGF);
4089 }
4090 llvm::Value *SizeVal;
4091 QualType Ty = E->getType();
4092 if (OASE) {
4093 SizeVal = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType());
4094 for (const Expr *SE : OASE->getDimensions()) {
4095 llvm::Value *Sz = CGF.EmitScalarExpr(SE);
4096 Sz = CGF.EmitScalarConversion(
4097 Sz, SE->getType(), CGF.getContext().getSizeType(), SE->getExprLoc());
4098 SizeVal = CGF.Builder.CreateNUWMul(SizeVal, Sz);
4099 }
4100 } else if (const auto *ASE =
4101 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
4102 LValue UpAddrLVal =
4103 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
4104 llvm::Value *UpAddr =
4105 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(CGF), /*Idx0=*/1);
4106 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy);
4107 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy);
4108 SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
4109 } else {
4110 SizeVal = CGF.getTypeSize(Ty);
4111 }
4112 return std::make_pair(Addr, SizeVal);
4113}
4114
4115/// Builds kmp_depend_info, if it is not built yet, and builds flags type.
4116static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) {
4117 QualType FlagsTy = C.getIntTypeForBitwidth(32, /*Signed=*/false);
4118 if (KmpTaskAffinityInfoTy.isNull()) {
4119 RecordDecl *KmpAffinityInfoRD =
4120 C.buildImplicitRecord("kmp_task_affinity_info_t");
4121 KmpAffinityInfoRD->startDefinition();
4122 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getIntPtrType());
4123 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType());
4124 addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy);
4125 KmpAffinityInfoRD->completeDefinition();
4126 KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD);
4127 }
4128}
4129
4130CGOpenMPRuntime::TaskResultTy
4131CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4132 const OMPExecutableDirective &D,
4133 llvm::Function *TaskFunction, QualType SharedsTy,
4134 Address Shareds, const OMPTaskDataTy &Data) {
4135 ASTContext &C = CGM.getContext();
4136 llvm::SmallVector<PrivateDataTy, 4> Privates;
4137 // Aggregate privates and sort them by the alignment.
4138 const auto *I = Data.PrivateCopies.begin();
4139 for (const Expr *E : Data.PrivateVars) {
4140 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4141 Privates.emplace_back(
4142 C.getDeclAlign(VD),
4143 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
4144 /*PrivateElemInit=*/nullptr));
4145 ++I;
4146 }
4147 I = Data.FirstprivateCopies.begin();
4148 const auto *IElemInitRef = Data.FirstprivateInits.begin();
4149 for (const Expr *E : Data.FirstprivateVars) {
4150 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4151 Privates.emplace_back(
4152 C.getDeclAlign(VD),
4153 PrivateHelpersTy(
4154 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
4155 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
4156 ++I;
4157 ++IElemInitRef;
4158 }
4159 I = Data.LastprivateCopies.begin();
4160 for (const Expr *E : Data.LastprivateVars) {
4161 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4162 Privates.emplace_back(
4163 C.getDeclAlign(VD),
4164 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
4165 /*PrivateElemInit=*/nullptr));
4166 ++I;
4167 }
4168 for (const VarDecl *VD : Data.PrivateLocals) {
4169 if (isAllocatableDecl(VD))
4170 Privates.emplace_back(CGM.getPointerAlign(), PrivateHelpersTy(VD));
4171 else
4172 Privates.emplace_back(C.getDeclAlign(VD), PrivateHelpersTy(VD));
4173 }
4174 llvm::stable_sort(Privates,
4175 [](const PrivateDataTy &L, const PrivateDataTy &R) {
4176 return L.first > R.first;
4177 });
4178 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
4179 // Build type kmp_routine_entry_t (if not built yet).
4180 emitKmpRoutineEntryT(KmpInt32Ty);
4181 // Build type kmp_task_t (if not built yet).
4182 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
4183 if (SavedKmpTaskloopTQTy.isNull()) {
4184 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
4185 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
4186 }
4187 KmpTaskTQTy = SavedKmpTaskloopTQTy;
4188 } else {
4189 assert((D.getDirectiveKind() == OMPD_task ||(((D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective
(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective
(D.getDirectiveKind())) && "Expected taskloop, task or target directive"
) ? static_cast<void> (0) : __assert_fail ("(D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && \"Expected taskloop, task or target directive\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4192, __PRETTY_FUNCTION__))
4190 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||(((D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective
(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective
(D.getDirectiveKind())) && "Expected taskloop, task or target directive"
) ? static_cast<void> (0) : __assert_fail ("(D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && \"Expected taskloop, task or target directive\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4192, __PRETTY_FUNCTION__))
4191 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&(((D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective
(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective
(D.getDirectiveKind())) && "Expected taskloop, task or target directive"
) ? static_cast<void> (0) : __assert_fail ("(D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && \"Expected taskloop, task or target directive\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4192, __PRETTY_FUNCTION__))
4192 "Expected taskloop, task or target directive")(((D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective
(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective
(D.getDirectiveKind())) && "Expected taskloop, task or target directive"
) ? static_cast<void> (0) : __assert_fail ("(D.getDirectiveKind() == OMPD_task || isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && \"Expected taskloop, task or target directive\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4192, __PRETTY_FUNCTION__))
;
4193 if (SavedKmpTaskTQTy.isNull()) {
4194 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
4195 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
4196 }
4197 KmpTaskTQTy = SavedKmpTaskTQTy;
4198 }
4199 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
4200 // Build particular struct kmp_task_t for the given task.
4201 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
4202 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
4203 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
4204 QualType KmpTaskTWithPrivatesPtrQTy =
4205 C.getPointerType(KmpTaskTWithPrivatesQTy);
4206 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
4207 llvm::Type *KmpTaskTWithPrivatesPtrTy =
4208 KmpTaskTWithPrivatesTy->getPointerTo();
4209 llvm::Value *KmpTaskTWithPrivatesTySize =
4210 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
4211 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
4212
4213 // Emit initial values for private copies (if any).
4214 llvm::Value *TaskPrivatesMap = nullptr;
4215 llvm::Type *TaskPrivatesMapTy =
4216 std::next(TaskFunction->arg_begin(), 3)->getType();
4217 if (!Privates.empty()) {
4218 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4219 TaskPrivatesMap =
4220 emitTaskPrivateMappingFunction(CGM, Loc, Data, FI->getType(), Privates);
4221 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4222 TaskPrivatesMap, TaskPrivatesMapTy);
4223 } else {
4224 TaskPrivatesMap = llvm::ConstantPointerNull::get(
4225 cast<llvm::PointerType>(TaskPrivatesMapTy));
4226 }
4227 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
4228 // kmp_task_t *tt);
4229 llvm::Function *TaskEntry = emitProxyTaskFunction(
4230 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4231 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
4232 TaskPrivatesMap);
4233
4234 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
4235 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
4236 // kmp_routine_entry_t *task_entry);
4237 // Task flags. Format is taken from
4238 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
4239 // description of kmp_tasking_flags struct.
4240 enum {
4241 TiedFlag = 0x1,
4242 FinalFlag = 0x2,
4243 DestructorsFlag = 0x8,
4244 PriorityFlag = 0x20,
4245 DetachableFlag = 0x40,
4246 };
4247 unsigned Flags = Data.Tied ? TiedFlag : 0;
4248 bool NeedsCleanup = false;
4249 if (!Privates.empty()) {
4250 NeedsCleanup =
4251 checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD, Privates);
4252 if (NeedsCleanup)
4253 Flags = Flags | DestructorsFlag;
4254 }
4255 if (Data.Priority.getInt())
4256 Flags = Flags | PriorityFlag;
4257 if (D.hasClausesOfKind<OMPDetachClause>())
4258 Flags = Flags | DetachableFlag;
4259 llvm::Value *TaskFlags =
4260 Data.Final.getPointer()
4261 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
4262 CGF.Builder.getInt32(FinalFlag),
4263 CGF.Builder.getInt32(/*C=*/0))
4264 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
4265 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
4266 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
4267 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
4268 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
4269 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4270 TaskEntry, KmpRoutineEntryPtrTy)};
4271 llvm::Value *NewTask;
4272 if (D.hasClausesOfKind<OMPNowaitClause>()) {
4273 // Check if we have any device clause associated with the directive.
4274 const Expr *Device = nullptr;
4275 if (auto *C = D.getSingleClause<OMPDeviceClause>())
4276 Device = C->getDevice();
4277 // Emit device ID if any otherwise use default value.
4278 llvm::Value *DeviceID;
4279 if (Device)
4280 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
4281 CGF.Int64Ty, /*isSigned=*/true);
4282 else
4283 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
4284 AllocArgs.push_back(DeviceID);
4285 NewTask = CGF.EmitRuntimeCall(
4286 OMPBuilder.getOrCreateRuntimeFunction(
4287 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
4288 AllocArgs);
4289 } else {
4290 NewTask =
4291 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
4292 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
4293 AllocArgs);
4294 }
4295 // Emit detach clause initialization.
4296 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid,
4297 // task_descriptor);
4298 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) {
4299 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts();
4300 LValue EvtLVal = CGF.EmitLValue(Evt);
4301
4302 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref,
4303 // int gtid, kmp_task_t *task);
4304 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc());
4305 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc());
4306 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false);
4307 llvm::Value *EvtVal = CGF.EmitRuntimeCall(
4308 OMPBuilder.getOrCreateRuntimeFunction(
4309 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
4310 {Loc, Tid, NewTask});
4311 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(),
4312 Evt->getExprLoc());
4313 CGF.EmitStoreOfScalar(EvtVal, EvtLVal);
4314 }
4315 // Process affinity clauses.
4316 if (D.hasClausesOfKind<OMPAffinityClause>()) {
4317 // Process list of affinity data.
4318 ASTContext &C = CGM.getContext();
4319 Address AffinitiesArray = Address::invalid();
4320 // Calculate number of elements to form the array of affinity data.
4321 llvm::Value *NumOfElements = nullptr;
4322 unsigned NumAffinities = 0;
4323 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
4324 if (const Expr *Modifier = C->getModifier()) {
4325 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts());
4326 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4327 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper);
4328 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false);
4329 NumOfElements =
4330 NumOfElements ? CGF.Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
4331 }
4332 } else {
4333 NumAffinities += C->varlist_size();
4334 }
4335 }
4336 getKmpAffinityType(CGM.getContext(), KmpTaskAffinityInfoTy);
4337 // Fields ids in kmp_task_affinity_info record.
4338 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
4339
4340 QualType KmpTaskAffinityInfoArrayTy;
4341 if (NumOfElements) {
4342 NumOfElements = CGF.Builder.CreateNUWAdd(
4343 llvm::ConstantInt::get(CGF.SizeTy, NumAffinities), NumOfElements);
4344 OpaqueValueExpr OVE(
4345 Loc,
4346 C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0),
4347 VK_RValue);
4348 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE,
4349 RValue::get(NumOfElements));
4350 KmpTaskAffinityInfoArrayTy =
4351 C.getVariableArrayType(KmpTaskAffinityInfoTy, &OVE, ArrayType::Normal,
4352 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc));
4353 // Properly emit variable-sized array.
4354 auto *PD = ImplicitParamDecl::Create(C, KmpTaskAffinityInfoArrayTy,
4355 ImplicitParamDecl::Other);
4356 CGF.EmitVarDecl(*PD);
4357 AffinitiesArray = CGF.GetAddrOfLocalVar(PD);
4358 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty,
4359 /*isSigned=*/false);
4360 } else {
4361 KmpTaskAffinityInfoArrayTy = C.getConstantArrayType(
4362 KmpTaskAffinityInfoTy,
4363 llvm::APInt(C.getTypeSize(C.getSizeType()), NumAffinities), nullptr,
4364 ArrayType::Normal, /*IndexTypeQuals=*/0);
4365 AffinitiesArray =
4366 CGF.CreateMemTemp(KmpTaskAffinityInfoArrayTy, ".affs.arr.addr");
4367 AffinitiesArray = CGF.Builder.CreateConstArrayGEP(AffinitiesArray, 0);
4368 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumAffinities,
4369 /*isSigned=*/false);
4370 }
4371
4372 const auto *KmpAffinityInfoRD = KmpTaskAffinityInfoTy->getAsRecordDecl();
4373 // Fill array by elements without iterators.
4374 unsigned Pos = 0;
4375 bool HasIterator = false;
4376 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
4377 if (C->getModifier()) {
4378 HasIterator = true;
4379 continue;
4380 }
4381 for (const Expr *E : C->varlists()) {
4382 llvm::Value *Addr;
4383 llvm::Value *Size;
4384 std::tie(Addr, Size) = getPointerAndSize(CGF, E);
4385 LValue Base =
4386 CGF.MakeAddrLValue(CGF.Builder.CreateConstGEP(AffinitiesArray, Pos),
4387 KmpTaskAffinityInfoTy);
4388 // affs[i].base_addr = &<Affinities[i].second>;
4389 LValue BaseAddrLVal = CGF.EmitLValueForField(
4390 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4391 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy),
4392 BaseAddrLVal);
4393 // affs[i].len = sizeof(<Affinities[i].second>);
4394 LValue LenLVal = CGF.EmitLValueForField(
4395 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4396 CGF.EmitStoreOfScalar(Size, LenLVal);
4397 ++Pos;
4398 }
4399 }
4400 LValue PosLVal;
4401 if (HasIterator) {
4402 PosLVal = CGF.MakeAddrLValue(
4403 CGF.CreateMemTemp(C.getSizeType(), "affs.counter.addr"),
4404 C.getSizeType());
4405 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal);
4406 }
4407 // Process elements with iterators.
4408 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
4409 const Expr *Modifier = C->getModifier();
4410 if (!Modifier)
4411 continue;
4412 OMPIteratorGeneratorScope IteratorScope(
4413 CGF, cast_or_null<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts()));
4414 for (const Expr *E : C->varlists()) {
4415 llvm::Value *Addr;
4416 llvm::Value *Size;
4417 std::tie(Addr, Size) = getPointerAndSize(CGF, E);
4418 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4419 LValue Base = CGF.MakeAddrLValue(
4420 Address(CGF.Builder.CreateGEP(AffinitiesArray.getPointer(), Idx),
4421 AffinitiesArray.getAlignment()),
4422 KmpTaskAffinityInfoTy);
4423 // affs[i].base_addr = &<Affinities[i].second>;
4424 LValue BaseAddrLVal = CGF.EmitLValueForField(
4425 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4426 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy),
4427 BaseAddrLVal);
4428 // affs[i].len = sizeof(<Affinities[i].second>);
4429 LValue LenLVal = CGF.EmitLValueForField(
4430 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4431 CGF.EmitStoreOfScalar(Size, LenLVal);
4432 Idx = CGF.Builder.CreateNUWAdd(
4433 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4434 CGF.EmitStoreOfScalar(Idx, PosLVal);
4435 }
4436 }
4437 // Call to kmp_int32 __kmpc_omp_reg_task_with_affinity(ident_t *loc_ref,
4438 // kmp_int32 gtid, kmp_task_t *new_task, kmp_int32
4439 // naffins, kmp_task_affinity_info_t *affin_list);
4440 llvm::Value *LocRef = emitUpdateLocation(CGF, Loc);
4441 llvm::Value *GTid = getThreadID(CGF, Loc);
4442 llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4443 AffinitiesArray.getPointer(), CGM.VoidPtrTy);
4444 // FIXME: Emit the function and ignore its result for now unless the
4445 // runtime function is properly implemented.
4446 (void)CGF.EmitRuntimeCall(
4447 OMPBuilder.getOrCreateRuntimeFunction(
4448 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4449 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4450 }
4451 llvm::Value *NewTaskNewTaskTTy =
4452 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4453 NewTask, KmpTaskTWithPrivatesPtrTy);
4454 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
4455 KmpTaskTWithPrivatesQTy);
4456 LValue TDBase =
4457 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
4458 // Fill the data in the resulting kmp_task_t record.
4459 // Copy shareds if there are any.
4460 Address KmpTaskSharedsPtr = Address::invalid();
4461 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
4462 KmpTaskSharedsPtr =
4463 Address(CGF.EmitLoadOfScalar(
4464 CGF.EmitLValueForField(
4465 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
4466 KmpTaskTShareds)),
4467 Loc),
4468 CGM.getNaturalTypeAlignment(SharedsTy));
4469 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
4470 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
4471 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
4472 }
4473 // Emit initial values for private copies (if any).
4474 TaskResultTy Result;
4475 if (!Privates.empty()) {
4476 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
4477 SharedsTy, SharedsPtrTy, Data, Privates,
4478 /*ForDup=*/false);
4479 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
4480 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
4481 Result.TaskDupFn = emitTaskDupFunction(
4482 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4483 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
4484 /*WithLastIter=*/!Data.LastprivateVars.empty());
4485 }
4486 }
4487 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
4488 enum { Priority = 0, Destructors = 1 };
4489 // Provide pointer to function with destructors for privates.
4490 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4491 const RecordDecl *KmpCmplrdataUD =
4492 (*FI)->getType()->getAsUnionType()->getDecl();
4493 if (NeedsCleanup) {
4494 llvm::Value *DestructorFn = emitDestructorsFunction(
4495 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4496 KmpTaskTWithPrivatesQTy);
4497 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
4498 LValue DestructorsLV = CGF.EmitLValueForField(
4499 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4500 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4501 DestructorFn, KmpRoutineEntryPtrTy),
4502 DestructorsLV);
4503 }
4504 // Set priority.
4505 if (Data.Priority.getInt()) {
4506 LValue Data2LV = CGF.EmitLValueForField(
4507 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4508 LValue PriorityLV = CGF.EmitLValueForField(
4509 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4510 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
4511 }
4512 Result.NewTask = NewTask;
4513 Result.TaskEntry = TaskEntry;
4514 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4515 Result.TDBase = TDBase;
4516 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4517 return Result;
4518}
4519
4520namespace {
4521/// Dependence kind for RTL.
4522enum RTLDependenceKindTy {
4523 DepIn = 0x01,
4524 DepInOut = 0x3,
4525 DepMutexInOutSet = 0x4
4526};
4527/// Fields ids in kmp_depend_info record.
4528enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
4529} // namespace
4530
4531/// Translates internal dependency kind into the runtime kind.
4532static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) {
4533 RTLDependenceKindTy DepKind;
4534 switch (K) {
4535 case OMPC_DEPEND_in:
4536 DepKind = DepIn;
4537 break;
4538 // Out and InOut dependencies must use the same code.
4539 case OMPC_DEPEND_out:
4540 case OMPC_DEPEND_inout:
4541 DepKind = DepInOut;
4542 break;
4543 case OMPC_DEPEND_mutexinoutset:
4544 DepKind = DepMutexInOutSet;
4545 break;
4546 case OMPC_DEPEND_source:
4547 case OMPC_DEPEND_sink:
4548 case OMPC_DEPEND_depobj:
4549 case OMPC_DEPEND_unknown:
4550 llvm_unreachable("Unknown task dependence type")::llvm::llvm_unreachable_internal("Unknown task dependence type"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4550)
;
4551 }
4552 return DepKind;
4553}
4554
4555/// Builds kmp_depend_info, if it is not built yet, and builds flags type.
4556static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy,
4557 QualType &FlagsTy) {
4558 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
4559 if (KmpDependInfoTy.isNull()) {
4560 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
4561 KmpDependInfoRD->startDefinition();
4562 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
4563 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
4564 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
4565 KmpDependInfoRD->completeDefinition();
4566 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
4567 }
4568}
4569
4570std::pair<llvm::Value *, LValue>
4571CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal,
4572 SourceLocation Loc) {
4573 ASTContext &C = CGM.getContext();
4574 QualType FlagsTy;
4575 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4576 RecordDecl *KmpDependInfoRD =
4577 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4578 LValue Base = CGF.EmitLoadOfPointerLValue(
4579 DepobjLVal.getAddress(CGF),
4580 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
4581 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
4582 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4583 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy));
4584 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
4585 Base.getTBAAInfo());
4586 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
4587 Addr.getPointer(),
4588 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
4589 LValue NumDepsBase = CGF.MakeAddrLValue(
4590 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
4591 Base.getBaseInfo(), Base.getTBAAInfo());
4592 // NumDeps = deps[i].base_addr;
4593 LValue BaseAddrLVal = CGF.EmitLValueForField(
4594 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
4595 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc);
4596 return std::make_pair(NumDeps, Base);
4597}
4598
4599static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy,
4600 llvm::PointerUnion<unsigned *, LValue *> Pos,
4601 const OMPTaskDataTy::DependData &Data,
4602 Address DependenciesArray) {
4603 CodeGenModule &CGM = CGF.CGM;
4604 ASTContext &C = CGM.getContext();
4605 QualType FlagsTy;
4606 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4607 RecordDecl *KmpDependInfoRD =
4608 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4609 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
4610
4611 OMPIteratorGeneratorScope IteratorScope(
4612 CGF, cast_or_null<OMPIteratorExpr>(
4613 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts()
4614 : nullptr));
4615 for (const Expr *E : Data.DepExprs) {
4616 llvm::Value *Addr;
4617 llvm::Value *Size;
4618 std::tie(Addr, Size) = getPointerAndSize(CGF, E);
4619 LValue Base;
4620 if (unsigned *P = Pos.dyn_cast<unsigned *>()) {
4621 Base = CGF.MakeAddrLValue(
4622 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy);
4623 } else {
4624 LValue &PosLVal = *Pos.get<LValue *>();
4625 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4626 Base = CGF.MakeAddrLValue(
4627 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Idx),
4628 DependenciesArray.getAlignment()),
4629 KmpDependInfoTy);
4630 }
4631 // deps[i].base_addr = &<Dependencies[i].second>;
4632 LValue BaseAddrLVal = CGF.EmitLValueForField(
4633 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
4634 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy),
4635 BaseAddrLVal);
4636 // deps[i].len = sizeof(<Dependencies[i].second>);
4637 LValue LenLVal = CGF.EmitLValueForField(
4638 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
4639 CGF.EmitStoreOfScalar(Size, LenLVal);
4640 // deps[i].flags = <Dependencies[i].first>;
4641 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind);
4642 LValue FlagsLVal = CGF.EmitLValueForField(
4643 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
4644 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
4645 FlagsLVal);
4646 if (unsigned *P = Pos.dyn_cast<unsigned *>()) {
4647 ++(*P);
4648 } else {
4649 LValue &PosLVal = *Pos.get<LValue *>();
4650 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4651 Idx = CGF.Builder.CreateNUWAdd(Idx,
4652 llvm::ConstantInt::get(Idx->getType(), 1));
4653 CGF.EmitStoreOfScalar(Idx, PosLVal);
4654 }
4655 }
4656}
4657
4658static SmallVector<llvm::Value *, 4>
4659emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy,
4660 const OMPTaskDataTy::DependData &Data) {
4661 assert(Data.DepKind == OMPC_DEPEND_depobj &&((Data.DepKind == OMPC_DEPEND_depobj && "Expected depobj dependecy kind."
) ? static_cast<void> (0) : __assert_fail ("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependecy kind.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4662, __PRETTY_FUNCTION__))
4662 "Expected depobj dependecy kind.")((Data.DepKind == OMPC_DEPEND_depobj && "Expected depobj dependecy kind."
) ? static_cast<void> (0) : __assert_fail ("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependecy kind.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4662, __PRETTY_FUNCTION__))
;
4663 SmallVector<llvm::Value *, 4> Sizes;
4664 SmallVector<LValue, 4> SizeLVals;
4665 ASTContext &C = CGF.getContext();
4666 QualType FlagsTy;
4667 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4668 RecordDecl *KmpDependInfoRD =
4669 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4670 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
4671 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy);
4672 {
4673 OMPIteratorGeneratorScope IteratorScope(
4674 CGF, cast_or_null<OMPIteratorExpr>(
4675 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts()
4676 : nullptr));
4677 for (const Expr *E : Data.DepExprs) {
4678 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts());
4679 LValue Base = CGF.EmitLoadOfPointerLValue(
4680 DepobjLVal.getAddress(CGF),
4681 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
4682 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4683 Base.getAddress(CGF), KmpDependInfoPtrT);
4684 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
4685 Base.getTBAAInfo());
4686 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
4687 Addr.getPointer(),
4688 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
4689 LValue NumDepsBase = CGF.MakeAddrLValue(
4690 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
4691 Base.getBaseInfo(), Base.getTBAAInfo());
4692 // NumDeps = deps[i].base_addr;
4693 LValue BaseAddrLVal = CGF.EmitLValueForField(
4694 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
4695 llvm::Value *NumDeps =
4696 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc());
4697 LValue NumLVal = CGF.MakeAddrLValue(
4698 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"),
4699 C.getUIntPtrType());
4700 CGF.InitTempAlloca(NumLVal.getAddress(CGF),
4701 llvm::ConstantInt::get(CGF.IntPtrTy, 0));
4702 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc());
4703 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps);
4704 CGF.EmitStoreOfScalar(Add, NumLVal);
4705 SizeLVals.push_back(NumLVal);
4706 }
4707 }
4708 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4709 llvm::Value *Size =
4710 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc());
4711 Sizes.push_back(Size);
4712 }
4713 return Sizes;
4714}
4715
4716static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy,
4717 LValue PosLVal,
4718 const OMPTaskDataTy::DependData &Data,
4719 Address DependenciesArray) {
4720 assert(Data.DepKind == OMPC_DEPEND_depobj &&((Data.DepKind == OMPC_DEPEND_depobj && "Expected depobj dependecy kind."
) ? static_cast<void> (0) : __assert_fail ("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependecy kind.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4721, __PRETTY_FUNCTION__))
4721 "Expected depobj dependecy kind.")((Data.DepKind == OMPC_DEPEND_depobj && "Expected depobj dependecy kind."
) ? static_cast<void> (0) : __assert_fail ("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependecy kind.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4721, __PRETTY_FUNCTION__))
;
4722 ASTContext &C = CGF.getContext();
4723 QualType FlagsTy;
4724 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4725 RecordDecl *KmpDependInfoRD =
4726 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4727 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
4728 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy);
4729 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy);
4730 {
4731 OMPIteratorGeneratorScope IteratorScope(
4732 CGF, cast_or_null<OMPIteratorExpr>(
4733 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts()
4734 : nullptr));
4735 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) {
4736 const Expr *E = Data.DepExprs[I];
4737 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts());
4738 LValue Base = CGF.EmitLoadOfPointerLValue(
4739 DepobjLVal.getAddress(CGF),
4740 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
4741 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4742 Base.getAddress(CGF), KmpDependInfoPtrT);
4743 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
4744 Base.getTBAAInfo());
4745
4746 // Get number of elements in a single depobj.
4747 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
4748 Addr.getPointer(),
4749 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
4750 LValue NumDepsBase = CGF.MakeAddrLValue(
4751 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
4752 Base.getBaseInfo(), Base.getTBAAInfo());
4753 // NumDeps = deps[i].base_addr;
4754 LValue BaseAddrLVal = CGF.EmitLValueForField(
4755 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
4756 llvm::Value *NumDeps =
4757 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc());
4758
4759 // memcopy dependency data.
4760 llvm::Value *Size = CGF.Builder.CreateNUWMul(
4761 ElSize,
4762 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false));
4763 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4764 Address DepAddr =
4765 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Pos),
4766 DependenciesArray.getAlignment());
4767 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size);
4768
4769 // Increase pos.
4770 // pos += size;
4771 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps);
4772 CGF.EmitStoreOfScalar(Add, PosLVal);
4773 }
4774 }
4775}
4776
4777std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause(
4778 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies,
4779 SourceLocation Loc) {
4780 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) {
4781 return D.DepExprs.empty();
4782 }))
4783 return std::make_pair(nullptr, Address::invalid());
4784 // Process list of dependencies.
4785 ASTContext &C = CGM.getContext();
4786 Address DependenciesArray = Address::invalid();
4787 llvm::Value *NumOfElements = nullptr;
4788 unsigned NumDependencies = std::accumulate(
4789 Dependencies.begin(), Dependencies.end(), 0,
4790 [](unsigned V, const OMPTaskDataTy::DependData &D) {
4791 return D.DepKind == OMPC_DEPEND_depobj
4792 ? V
4793 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4794 });
4795 QualType FlagsTy;
4796 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4797 bool HasDepobjDeps = false;
4798 bool HasRegularWithIterators = false;
4799 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0);
4800 llvm::Value *NumOfRegularWithIterators =
4801 llvm::ConstantInt::get(CGF.IntPtrTy, 1);
4802 // Calculate number of depobj dependecies and regular deps with the iterators.
4803 for (const OMPTaskDataTy::DependData &D : Dependencies) {
4804 if (D.DepKind == OMPC_DEPEND_depobj) {
4805 SmallVector<llvm::Value *, 4> Sizes =
4806 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D);
4807 for (llvm::Value *Size : Sizes) {
4808 NumOfDepobjElements =
4809 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4810 }
4811 HasDepobjDeps = true;
4812 continue;
4813 }
4814 // Include number of iterations, if any.
4815 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) {
4816 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4817 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper);
4818 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false);
4819 NumOfRegularWithIterators =
4820 CGF.Builder.CreateNUWMul(NumOfRegularWithIterators, Sz);
4821 }
4822 HasRegularWithIterators = true;
4823 continue;
4824 }
4825 }
4826
4827 QualType KmpDependInfoArrayTy;
4828 if (HasDepobjDeps || HasRegularWithIterators) {
4829 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies,
4830 /*isSigned=*/false);
4831 if (HasDepobjDeps) {
4832 NumOfElements =
4833 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4834 }
4835 if (HasRegularWithIterators) {
4836 NumOfElements =
4837 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4838 }
4839 OpaqueValueExpr OVE(Loc,
4840 C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0),
4841 VK_RValue);
4842 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE,
4843 RValue::get(NumOfElements));
4844 KmpDependInfoArrayTy =
4845 C.getVariableArrayType(KmpDependInfoTy, &OVE, ArrayType::Normal,
4846 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc));
4847 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy);
4848 // Properly emit variable-sized array.
4849 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy,
4850 ImplicitParamDecl::Other);
4851 CGF.EmitVarDecl(*PD);
4852 DependenciesArray = CGF.GetAddrOfLocalVar(PD);
4853 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty,
4854 /*isSigned=*/false);
4855 } else {
4856 KmpDependInfoArrayTy = C.getConstantArrayType(
4857 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr,
4858 ArrayType::Normal, /*IndexTypeQuals=*/0);
4859 DependenciesArray =
4860 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
4861 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0);
4862 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies,
4863 /*isSigned=*/false);
4864 }
4865 unsigned Pos = 0;
4866 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4867 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj ||
4868 Dependencies[I].IteratorExpr)
4869 continue;
4870 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I],
4871 DependenciesArray);
4872 }
4873 // Copy regular dependecies with iterators.
4874 LValue PosLVal = CGF.MakeAddrLValue(
4875 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType());
4876 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal);
4877 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4878 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj ||
4879 !Dependencies[I].IteratorExpr)
4880 continue;
4881 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I],
4882 DependenciesArray);
4883 }
4884 // Copy final depobj arrays without iterators.
4885 if (HasDepobjDeps) {
4886 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4887 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj)
4888 continue;
4889 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I],
4890 DependenciesArray);
4891 }
4892 }
4893 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4894 DependenciesArray, CGF.VoidPtrTy);
4895 return std::make_pair(NumOfElements, DependenciesArray);
4896}
4897
4898Address CGOpenMPRuntime::emitDepobjDependClause(
4899 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies,
4900 SourceLocation Loc) {
4901 if (Dependencies.DepExprs.empty())
4902 return Address::invalid();
4903 // Process list of dependencies.
4904 ASTContext &C = CGM.getContext();
4905 Address DependenciesArray = Address::invalid();
4906 unsigned NumDependencies = Dependencies.DepExprs.size();
4907 QualType FlagsTy;
4908 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4909 RecordDecl *KmpDependInfoRD =
4910 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4911
4912 llvm::Value *Size;
4913 // Define type kmp_depend_info[<Dependencies.size()>];
4914 // For depobj reserve one extra element to store the number of elements.
4915 // It is required to handle depobj(x) update(in) construct.
4916 // kmp_depend_info[<Dependencies.size()>] deps;
4917 llvm::Value *NumDepsVal;
4918 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy);
4919 if (const auto *IE =
4920 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) {
4921 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1);
4922 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4923 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper);
4924 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false);
4925 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz);
4926 }
4927 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1),
4928 NumDepsVal);
4929 CharUnits SizeInBytes =
4930 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align);
4931 llvm::Value *RecSize = CGM.getSize(SizeInBytes);
4932 Size = CGF.Builder.CreateNUWMul(Size, RecSize);
4933 NumDepsVal =
4934 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false);
4935 } else {
4936 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
4937 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1),
4938 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
4939 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy);
4940 Size = CGM.getSize(Sz.alignTo(Align));
4941 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies);
4942 }
4943 // Need to allocate on the dynamic memory.
4944 llvm::Value *ThreadID = getThreadID(CGF, Loc);
4945 // Use default allocator.
4946 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
4947 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4948
4949 llvm::Value *Addr =
4950 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
4951 CGM.getModule(), OMPRTL___kmpc_alloc),
4952 Args, ".dep.arr.addr");
4953 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4954 Addr, CGF.ConvertTypeForMem(KmpDependInfoTy)->getPointerTo());
4955 DependenciesArray = Address(Addr, Align);
4956 // Write number of elements in the first element of array for depobj.
4957 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy);
4958 // deps[i].base_addr = NumDependencies;
4959 LValue BaseAddrLVal = CGF.EmitLValueForField(
4960 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
4961 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal);
4962 llvm::PointerUnion<unsigned *, LValue *> Pos;
4963 unsigned Idx = 1;
4964 LValue PosLVal;
4965 if (Dependencies.IteratorExpr) {
4966 PosLVal = CGF.MakeAddrLValue(
4967 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"),
4968 C.getSizeType());
4969 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal,
4970 /*IsInit=*/true);
4971 Pos = &PosLVal;
4972 } else {
4973 Pos = &Idx;
4974 }
4975 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray);
4976 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4977 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy);
4978 return DependenciesArray;
4979}
4980
4981void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal,
4982 SourceLocation Loc) {
4983 ASTContext &C = CGM.getContext();
4984 QualType FlagsTy;
4985 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4986 LValue Base = CGF.EmitLoadOfPointerLValue(
4987 DepobjLVal.getAddress(CGF),
4988 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
4989 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
4990 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4991 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy));
4992 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
4993 Addr.getPointer(),
4994 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
4995 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr,
4996 CGF.VoidPtrTy);
4997 llvm::Value *ThreadID = getThreadID(CGF, Loc);
4998 // Use default allocator.
4999 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5000 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
5001
5002 // _kmpc_free(gtid, addr, nullptr);
5003 (void)CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
5004 CGM.getModule(), OMPRTL___kmpc_free),
5005 Args);
5006}
5007
5008void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal,
5009 OpenMPDependClauseKind NewDepKind,
5010 SourceLocation Loc) {
5011 ASTContext &C = CGM.getContext();
5012 QualType FlagsTy;
5013 getDependTypes(C, KmpDependInfoTy, FlagsTy);
5014 RecordDecl *KmpDependInfoRD =
5015 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
5016 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5017 llvm::Value *NumDeps;
5018 LValue Base;
5019 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc);
5020
5021 Address Begin = Base.getAddress(CGF);
5022 // Cast from pointer to array type to pointer to single element.
5023 llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps);
5024 // The basic structure here is a while-do loop.
5025 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body");
5026 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done");
5027 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
5028 CGF.EmitBlock(BodyBB);
5029 llvm::PHINode *ElementPHI =
5030 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast");
5031 ElementPHI->addIncoming(Begin.getPointer(), EntryBB);
5032 Begin = Address(ElementPHI, Begin.getAlignment());
5033 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(),
5034 Base.getTBAAInfo());
5035 // deps[i].flags = NewDepKind;
5036 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind);
5037 LValue FlagsLVal = CGF.EmitLValueForField(
5038 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5039 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5040 FlagsLVal);
5041
5042 // Shift the address forward by one element.
5043 Address ElementNext =
5044 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext");
5045 ElementPHI->addIncoming(ElementNext.getPointer(),
5046 CGF.Builder.GetInsertBlock());
5047 llvm::Value *IsEmpty =
5048 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty");
5049 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5050 // Done.
5051 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5052}
5053
5054void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5055 const OMPExecutableDirective &D,
5056 llvm::Function *TaskFunction,
5057 QualType SharedsTy, Address Shareds,
5058 const Expr *IfCond,
5059 const OMPTaskDataTy &Data) {
5060 if (!CGF.HaveInsertPoint())
5061 return;
5062
5063 TaskResultTy Result =
5064 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5065 llvm::Value *NewTask = Result.NewTask;
5066 llvm::Function *TaskEntry = Result.TaskEntry;
5067 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5068 LValue TDBase = Result.TDBase;
5069 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5070 // Process list of dependences.
5071 Address DependenciesArray = Address::invalid();
5072 llvm::Value *NumOfElements;
5073 std::tie(NumOfElements, DependenciesArray) =
5074 emitDependClause(CGF, Data.Dependences, Loc);
5075
5076 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
5077 // libcall.
5078 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5079 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5080 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5081 // list is not empty
5082 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5083 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5084 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5085 llvm::Value *DepTaskArgs[7];
5086 if (!Data.Dependences.empty()) {
5087 DepTaskArgs[0] = UpLoc;
5088 DepTaskArgs[1] = ThreadID;
5089 DepTaskArgs[2] = NewTask;
5090 DepTaskArgs[3] = NumOfElements;
5091 DepTaskArgs[4] = DependenciesArray.getPointer();
5092 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5093 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5094 }
5095 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
5096 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
5097 if (!Data.Tied) {
5098 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
5099 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
5100 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5101 }
5102 if (!Data.Dependences.empty()) {
5103 CGF.EmitRuntimeCall(
5104 OMPBuilder.getOrCreateRuntimeFunction(
5105 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
5106 DepTaskArgs);
5107 } else {
5108 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
5109 CGM.getModule(), OMPRTL___kmpc_omp_task),
5110 TaskArgs);
5111 }
5112 // Check if parent region is untied and build return for untied task;
5113 if (auto *Region =
5114 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5115 Region->emitUntiedSwitch(CGF);
5116 };
5117
5118 llvm::Value *DepWaitTaskArgs[6];
5119 if (!Data.Dependences.empty()) {
5120 DepWaitTaskArgs[0] = UpLoc;
5121 DepWaitTaskArgs[1] = ThreadID;
5122 DepWaitTaskArgs[2] = NumOfElements;
5123 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5124 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5125 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5126 }
5127 auto &M = CGM.getModule();
5128 auto &&ElseCodeGen = [this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
5129 TaskEntry, &Data, &DepWaitTaskArgs,
5130 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
5131 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5132 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5133 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5134 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5135 // is specified.
5136 if (!Data.Dependences.empty())
5137 CGF.EmitRuntimeCall(
5138 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps),
5139 DepWaitTaskArgs);
5140 // Call proxy_task_entry(gtid, new_task);
5141 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5142 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
5143 Action.Enter(CGF);
5144 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
5145 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
5146 OutlinedFnArgs);
5147 };
5148
5149 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5150 // kmp_task_t *new_task);
5151 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5152 // kmp_task_t *new_task);
5153 RegionCodeGenTy RCG(CodeGen);
5154 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
5155 M, OMPRTL___kmpc_omp_task_begin_if0),
5156 TaskArgs,
5157 OMPBuilder.getOrCreateRuntimeFunction(
5158 M, OMPRTL___kmpc_omp_task_complete_if0),
5159 TaskArgs);
5160 RCG.setAction(Action);
5161 RCG(CGF);
5162 };
5163
5164 if (IfCond) {
5165 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
5166 } else {
5167 RegionCodeGenTy ThenRCG(ThenCodeGen);
5168 ThenRCG(CGF);
5169 }
5170}
5171
5172void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5173 const OMPLoopDirective &D,
5174 llvm::Function *TaskFunction,
5175 QualType SharedsTy, Address Shareds,
5176 const Expr *IfCond,
5177 const OMPTaskDataTy &Data) {
5178 if (!CGF.HaveInsertPoint())
5179 return;
5180 TaskResultTy Result =
5181 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5182 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
5183 // libcall.
5184 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5185 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5186 // sched, kmp_uint64 grainsize, void *task_dup);
5187 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5188 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5189 llvm::Value *IfVal;
5190 if (IfCond) {
5191 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5192 /*isSigned=*/true);
5193 } else {
5194 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
5195 }
5196
5197 LValue LBLVal = CGF.EmitLValueForField(
5198 Result.TDBase,
5199 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
5200 const auto *LBVar =
5201 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5202 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF),
5203 LBLVal.getQuals(),
5204 /*IsInitializer=*/true);
5205 LValue UBLVal = CGF.EmitLValueForField(
5206 Result.TDBase,
5207 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
5208 const auto *UBVar =
5209 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5210 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF),
5211 UBLVal.getQuals(),
5212 /*IsInitializer=*/true);
5213 LValue StLVal = CGF.EmitLValueForField(
5214 Result.TDBase,
5215 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
5216 const auto *StVar =
5217 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5218 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF),
5219 StLVal.getQuals(),
5220 /*IsInitializer=*/true);
5221 // Store reductions address.
5222 LValue RedLVal = CGF.EmitLValueForField(
5223 Result.TDBase,
5224 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
5225 if (Data.Reductions) {
5226 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
5227 } else {
5228 CGF.EmitNullInitialization(RedLVal.getAddress(CGF),
5229 CGF.getContext().VoidPtrTy);
5230 }
5231 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
5232 llvm::Value *TaskArgs[] = {
5233 UpLoc,
5234 ThreadID,
5235 Result.NewTask,
5236 IfVal,
5237 LBLVal.getPointer(CGF),
5238 UBLVal.getPointer(CGF),
5239 CGF.EmitLoadOfScalar(StLVal, Loc),
5240 llvm::ConstantInt::getSigned(
5241 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
5242 llvm::ConstantInt::getSigned(
5243 CGF.IntTy, Data.Schedule.getPointer()
5244 ? Data.Schedule.getInt() ? NumTasks : Grainsize
5245 : NoSchedule),
5246 Data.Schedule.getPointer()
5247 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
5248 /*isSigned=*/false)
5249 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
5250 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5251 Result.TaskDupFn, CGF.VoidPtrTy)
5252 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
5253 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
5254 CGM.getModule(), OMPRTL___kmpc_taskloop),
5255 TaskArgs);
5256}
5257
5258/// Emit reduction operation for each element of array (required for
5259/// array sections) LHS op = RHS.
5260/// \param Type Type of array.
5261/// \param LHSVar Variable on the left side of the reduction operation
5262/// (references element of array in original variable).
5263/// \param RHSVar Variable on the right side of the reduction operation
5264/// (references element of array in original variable).
5265/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5266/// RHSVar.
5267static void EmitOMPAggregateReduction(
5268 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5269 const VarDecl *RHSVar,
5270 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5271 const Expr *, const Expr *)> &RedOpGen,
5272 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5273 const Expr *UpExpr = nullptr) {
5274 // Perform element-by-element initialization.
5275 QualType ElementTy;
5276 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5277 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5278
5279 // Drill down to the base element type on both arrays.
5280 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5281 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
5282
5283 llvm::Value *RHSBegin = RHSAddr.getPointer();
5284 llvm::Value *LHSBegin = LHSAddr.getPointer();
5285 // Cast from pointer to array type to pointer to single element.
5286 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
5287 // The basic structure here is a while-do loop.
5288 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5289 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5290 llvm::Value *IsEmpty =
5291 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5292 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5293
5294 // Enter the loop body, making that address the current address.
5295 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
5296 CGF.EmitBlock(BodyBB);
5297
5298 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5299
5300 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5301 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5302 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5303 Address RHSElementCurrent =
5304 Address(RHSElementPHI,
5305 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5306
5307 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5308 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5309 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5310 Address LHSElementCurrent =
5311 Address(LHSElementPHI,
5312 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5313
5314 // Emit copy.
5315 CodeGenFunction::OMPPrivateScope Scope(CGF);
5316 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5317 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
5318 Scope.Privatize();
5319 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5320 Scope.ForceCleanup();
5321
5322 // Shift the address forward by one element.
5323 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
5324 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
5325 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
5326 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5327 // Check whether we've reached the end.
5328 llvm::Value *Done =
5329 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5330 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5331 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5332 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5333
5334 // Done.
5335 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5336}
5337
5338/// Emit reduction combiner. If the combiner is a simple expression emit it as
5339/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5340/// UDR combiner function.
5341static void emitReductionCombiner(CodeGenFunction &CGF,
5342 const Expr *ReductionOp) {
5343 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5344 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5345 if (const auto *DRE =
5346 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
5347 if (const auto *DRD =
5348 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
5349 std::pair<llvm::Function *, llvm::Function *> Reduction =
5350 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5351 RValue Func = RValue::get(Reduction.first);
5352 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5353 CGF.EmitIgnoredExpr(ReductionOp);
5354 return;
5355 }
5356 CGF.EmitIgnoredExpr(ReductionOp);
5357}
5358
5359llvm::Function *CGOpenMPRuntime::emitReductionFunction(
5360 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5361 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5362 ArrayRef<const Expr *> ReductionOps) {
5363 ASTContext &C = CGM.getContext();
5364
5365 // void reduction_func(void *LHSArg, void *RHSArg);
5366 FunctionArgList Args;
5367 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5368 ImplicitParamDecl::Other);
5369 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5370 ImplicitParamDecl::Other);
5371 Args.push_back(&LHSArg);
5372 Args.push_back(&RHSArg);
5373 const auto &CGFI =
5374 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5375 std::string Name = getName({"omp", "reduction", "reduction_func"});
5376 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5377 llvm::GlobalValue::InternalLinkage, Name,
5378 &CGM.getModule());
5379 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
5380 Fn->setDoesNotRecurse();
5381 CodeGenFunction CGF(CGM);
5382 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
5383
5384 // Dst = (void*[n])(LHSArg);
5385 // Src = (void*[n])(RHSArg);
5386 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5387 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5388 ArgsType), CGF.getPointerAlign());
5389 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5390 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5391 ArgsType), CGF.getPointerAlign());
5392
5393 // ...
5394 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5395 // ...
5396 CodeGenFunction::OMPPrivateScope Scope(CGF);
5397 auto IPriv = Privates.begin();
5398 unsigned Idx = 0;
5399 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5400 const auto *RHSVar =
5401 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5402 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
5403 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
5404 });
5405 const auto *LHSVar =
5406 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5407 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
5408 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
5409 });
5410 QualType PrivTy = (*IPriv)->getType();
5411 if (PrivTy->isVariablyModifiedType()) {
5412 // Get array size and emit VLA type.
5413 ++Idx;
5414 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
5415 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
5416 const VariableArrayType *VLA =
5417 CGF.getContext().getAsVariableArrayType(PrivTy);
5418 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
5419 CodeGenFunction::OpaqueValueMapping OpaqueMap(
5420 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
5421 CGF.EmitVariablyModifiedType(PrivTy);
5422 }
5423 }
5424 Scope.Privatize();
5425 IPriv = Privates.begin();
5426 auto ILHS = LHSExprs.begin();
5427 auto IRHS = RHSExprs.begin();
5428 for (const Expr *E : ReductionOps) {
5429 if ((*IPriv)->getType()->isArrayType()) {
5430 // Emit reduction for array section.
5431 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5432 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5433 EmitOMPAggregateReduction(
5434 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5435 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5436 emitReductionCombiner(CGF, E);
5437 });
5438 } else {
5439 // Emit reduction for array subscript or single variable.
5440 emitReductionCombiner(CGF, E);
5441 }
5442 ++IPriv;
5443 ++ILHS;
5444 ++IRHS;
5445 }
5446 Scope.ForceCleanup();
5447 CGF.FinishFunction();
5448 return Fn;
5449}
5450
5451void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5452 const Expr *ReductionOp,
5453 const Expr *PrivateRef,
5454 const DeclRefExpr *LHS,
5455 const DeclRefExpr *RHS) {
5456 if (PrivateRef->getType()->isArrayType()) {
5457 // Emit reduction for array section.
5458 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5459 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
5460 EmitOMPAggregateReduction(
5461 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5462 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5463 emitReductionCombiner(CGF, ReductionOp);
5464 });
5465 } else {
5466 // Emit reduction for array subscript or single variable.
5467 emitReductionCombiner(CGF, ReductionOp);
5468 }
5469}
5470
5471void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
5472 ArrayRef<const Expr *> Privates,
5473 ArrayRef<const Expr *> LHSExprs,
5474 ArrayRef<const Expr *> RHSExprs,
5475 ArrayRef<const Expr *> ReductionOps,
5476 ReductionOptionsTy Options) {
5477 if (!CGF.HaveInsertPoint())
5478 return;
5479
5480 bool WithNowait = Options.WithNowait;
5481 bool SimpleReduction = Options.SimpleReduction;
5482
5483 // Next code should be emitted for reduction:
5484 //
5485 // static kmp_critical_name lock = { 0 };
5486 //
5487 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5488 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5489 // ...
5490 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5491 // *(Type<n>-1*)rhs[<n>-1]);
5492 // }
5493 //
5494 // ...
5495 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5496 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5497 // RedList, reduce_func, &<lock>)) {
5498 // case 1:
5499 // ...
5500 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5501 // ...
5502 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5503 // break;
5504 // case 2:
5505 // ...
5506 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5507 // ...
5508 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
5509 // break;
5510 // default:;
5511 // }
5512 //
5513 // if SimpleReduction is true, only the next code is generated:
5514 // ...
5515 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5516 // ...
5517
5518 ASTContext &C = CGM.getContext();
5519
5520 if (SimpleReduction) {
5521 CodeGenFunction::RunCleanupsScope Scope(CGF);
5522 auto IPriv = Privates.begin();
5523 auto ILHS = LHSExprs.begin();
5524 auto IRHS = RHSExprs.begin();
5525 for (const Expr *E : ReductionOps) {
5526 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5527 cast<DeclRefExpr>(*IRHS));
5528 ++IPriv;
5529 ++ILHS;
5530 ++IRHS;
5531 }
5532 return;
5533 }
5534
5535 // 1. Build a list of reduction variables.
5536 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
5537 auto Size = RHSExprs.size();
5538 for (const Expr *E : Privates) {
5539 if (E->getType()->isVariablyModifiedType())
5540 // Reserve place for array size.
5541 ++Size;
5542 }
5543 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
5544 QualType ReductionArrayTy =
5545 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
5546 /*IndexTypeQuals=*/0);
5547 Address ReductionList =
5548 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
5549 auto IPriv = Privates.begin();
5550 unsigned Idx = 0;
5551 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5552 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
5553 CGF.Builder.CreateStore(
5554 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5555 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy),
5556 Elem);
5557 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5558 // Store array size.
5559 ++Idx;
5560 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
5561 llvm::Value *Size = CGF.Builder.CreateIntCast(
5562 CGF.getVLASize(
5563 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
5564 .NumElts,
5565 CGF.SizeTy, /*isSigned=*/false);
5566 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5567 Elem);
5568 }
5569 }
5570
5571 // 2. Emit reduce_func().
5572 llvm::Function *ReductionFn = emitReductionFunction(
5573 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5574 LHSExprs, RHSExprs, ReductionOps);
5575
5576 // 3. Create static kmp_critical_name lock = { 0 };
5577 std::string Name = getName({"reduction"});
5578 llvm::Value *Lock = getCriticalRegionLock(Name);
5579
5580 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5581 // RedList, reduce_func, &<lock>);
5582 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5583 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5584 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5585 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5586 ReductionList.getPointer(), CGF.VoidPtrTy);
5587 llvm::Value *Args[] = {
5588 IdentTLoc, // ident_t *<loc>
5589 ThreadId, // i32 <gtid>
5590 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5591 ReductionArrayTySize, // size_type sizeof(RedList)
5592 RL, // void *RedList
5593 ReductionFn, // void (*) (void *, void *) <reduce_func>
5594 Lock // kmp_critical_name *&<lock>
5595 };
5596 llvm::Value *Res = CGF.EmitRuntimeCall(
5597 OMPBuilder.getOrCreateRuntimeFunction(
5598 CGM.getModule(),
5599 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5600 Args);
5601
5602 // 5. Build switch(res)
5603 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5604 llvm::SwitchInst *SwInst =
5605 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
5606
5607 // 6. Build case 1:
5608 // ...
5609 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5610 // ...
5611 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5612 // break;
5613 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
5614 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5615 CGF.EmitBlock(Case1BB);
5616
5617 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5618 llvm::Value *EndArgs[] = {
5619 IdentTLoc, // ident_t *<loc>
5620 ThreadId, // i32 <gtid>
5621 Lock // kmp_critical_name *&<lock>
5622 };
5623 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5624 CodeGenFunction &CGF, PrePostActionTy &Action) {
5625 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
5626 auto IPriv = Privates.begin();
5627 auto ILHS = LHSExprs.begin();
5628 auto IRHS = RHSExprs.begin();
5629 for (const Expr *E : ReductionOps) {
5630 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5631 cast<DeclRefExpr>(*IRHS));
5632 ++IPriv;
5633 ++ILHS;
5634 ++IRHS;
5635 }
5636 };
5637 RegionCodeGenTy RCG(CodeGen);
5638 CommonActionTy Action(
5639 nullptr, llvm::None,
5640 OMPBuilder.getOrCreateRuntimeFunction(
5641 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5642 : OMPRTL___kmpc_end_reduce),
5643 EndArgs);
5644 RCG.setAction(Action);
5645 RCG(CGF);
5646
5647 CGF.EmitBranch(DefaultBB);
5648
5649 // 7. Build case 2:
5650 // ...
5651 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5652 // ...
5653 // break;
5654 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
5655 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5656 CGF.EmitBlock(Case2BB);
5657
5658 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5659 CodeGenFunction &CGF, PrePostActionTy &Action) {
5660 auto ILHS = LHSExprs.begin();
5661 auto IRHS = RHSExprs.begin();
5662 auto IPriv = Privates.begin();
5663 for (const Expr *E : ReductionOps) {
5664 const Expr *XExpr = nullptr;
5665 const Expr *EExpr = nullptr;
5666 const Expr *UpExpr = nullptr;
5667 BinaryOperatorKind BO = BO_Comma;
5668 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
5669 if (BO->getOpcode() == BO_Assign) {
5670 XExpr = BO->getLHS();
5671 UpExpr = BO->getRHS();
5672 }
5673 }
5674 // Try to emit update expression as a simple atomic.
5675 const Expr *RHSExpr = UpExpr;
5676 if (RHSExpr) {
5677 // Analyze RHS part of the whole expression.
5678 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5679 RHSExpr->IgnoreParenImpCasts())) {
5680 // If this is a conditional operator, analyze its condition for
5681 // min/max reduction operator.
5682 RHSExpr = ACO->getCond();
5683 }
5684 if (const auto *BORHS =
5685 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5686 EExpr = BORHS->getRHS();
5687 BO = BORHS->getOpcode();
5688 }
5689 }
5690 if (XExpr) {
5691 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5692 auto &&AtomicRedGen = [BO, VD,
5693 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5694 const Expr *EExpr, const Expr *UpExpr) {
5695 LValue X = CGF.EmitLValue(XExpr);
5696 RValue E;
5697 if (EExpr)
5698 E = CGF.EmitAnyExpr(EExpr);
5699 CGF.EmitOMPAtomicSimpleUpdateExpr(
5700 X, E, BO, /*IsXLHSInRHSPart=*/true,
5701 llvm::AtomicOrdering::Monotonic, Loc,
5702 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
5703 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5704 PrivateScope.addPrivate(
5705 VD, [&CGF, VD, XRValue, Loc]() {
5706 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5707 CGF.emitOMPSimpleStore(
5708 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5709 VD->getType().getNonReferenceType(), Loc);
5710 return LHSTemp;
5711 });
5712 (void)PrivateScope.Privatize();
5713 return CGF.EmitAnyExpr(UpExpr);
5714 });
5715 };
5716 if ((*IPriv)->getType()->isArrayType()) {
5717 // Emit atomic reduction for array section.
5718 const auto *RHSVar =
5719 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5720 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5721 AtomicRedGen, XExpr, EExpr, UpExpr);
5722 } else {
5723 // Emit atomic reduction for array subscript or single variable.
5724 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5725 }
5726 } else {
5727 // Emit as a critical region.
5728 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
5729 const Expr *, const Expr *) {
5730 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
5731 std::string Name = RT.getName({"atomic_reduction"});
5732 RT.emitCriticalRegion(
5733 CGF, Name,
5734 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5735 Action.Enter(CGF);
5736 emitReductionCombiner(CGF, E);
5737 },
5738 Loc);
5739 };
5740 if ((*IPriv)->getType()->isArrayType()) {
5741 const auto *LHSVar =
5742 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5743 const auto *RHSVar =
5744 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5745 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5746 CritRedGen);
5747 } else {
5748 CritRedGen(CGF, nullptr, nullptr, nullptr);
5749 }
5750 }
5751 ++ILHS;
5752 ++IRHS;
5753 ++IPriv;
5754 }
5755 };
5756 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5757 if (!WithNowait) {
5758 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5759 llvm::Value *EndArgs[] = {
5760 IdentTLoc, // ident_t *<loc>
5761 ThreadId, // i32 <gtid>
5762 Lock // kmp_critical_name *&<lock>
5763 };
5764 CommonActionTy Action(nullptr, llvm::None,
5765 OMPBuilder.getOrCreateRuntimeFunction(
5766 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5767 EndArgs);
5768 AtomicRCG.setAction(Action);
5769 AtomicRCG(CGF);
5770 } else {
5771 AtomicRCG(CGF);
5772 }
5773
5774 CGF.EmitBranch(DefaultBB);
5775 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5776}
5777
5778/// Generates unique name for artificial threadprivate variables.
5779/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5780static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5781 const Expr *Ref) {
5782 SmallString<256> Buffer;
5783 llvm::raw_svector_ostream Out(Buffer);
5784 const clang::DeclRefExpr *DE;
5785 const VarDecl *D = ::getBaseDecl(Ref, DE);
5786 if (!D)
5787 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5788 D = D->getCanonicalDecl();
5789 std::string Name = CGM.getOpenMPRuntime().getName(
5790 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
5791 Out << Prefix << Name << "_"
5792 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
5793 return std::string(Out.str());
5794}
5795
5796/// Emits reduction initializer function:
5797/// \code
5798/// void @.red_init(void* %arg, void* %orig) {
5799/// %0 = bitcast void* %arg to <type>*
5800/// store <type> <init>, <type>* %0
5801/// ret void
5802/// }
5803/// \endcode
5804static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
5805 SourceLocation Loc,
5806 ReductionCodeGen &RCG, unsigned N) {
5807 ASTContext &C = CGM.getContext();
5808 QualType VoidPtrTy = C.VoidPtrTy;
5809 VoidPtrTy.addRestrict();
5810 FunctionArgList Args;
5811 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy,
5812 ImplicitParamDecl::Other);
5813 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy,
5814 ImplicitParamDecl::Other);
5815 Args.emplace_back(&Param);
5816 Args.emplace_back(&ParamOrig);
5817 const auto &FnInfo =
5818 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5819 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
5820 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
5821 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5822 Name, &CGM.getModule());
5823 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
5824 Fn->setDoesNotRecurse();
5825 CodeGenFunction CGF(CGM);
5826 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
5827 Address PrivateAddr = CGF.EmitLoadOfPointer(
5828 CGF.GetAddrOfLocalVar(&Param),
5829 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5830 llvm::Value *Size = nullptr;
5831 // If the size of the reduction item is non-constant, load it from global
5832 // threadprivate variable.
5833 if (RCG.getSizes(N).second) {
5834 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5835 CGF, CGM.getContext().getSizeType(),
5836 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
5837 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
5838 CGM.getContext().getSizeType(), Loc);
5839 }
5840 RCG.emitAggregateType(CGF, N, Size);
5841 LValue OrigLVal;
5842 // If initializer uses initializer from declare reduction construct, emit a
5843 // pointer to the address of the original reduction item (reuired by reduction
5844 // initializer)
5845 if (RCG.usesReductionInitializer(N)) {
5846 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig);
5847 SharedAddr = CGF.EmitLoadOfPointer(
5848 SharedAddr,
5849 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
5850 OrigLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
5851 } else {
5852 OrigLVal = CGF.MakeNaturalAlignAddrLValue(
5853 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
5854 CGM.getContext().VoidPtrTy);
5855 }
5856 // Emit the initializer:
5857 // %0 = bitcast void* %arg to <type>*
5858 // store <type> <init>, <type>* %0
5859 RCG.emitInitialization(CGF, N, PrivateAddr, OrigLVal,
5860 [](CodeGenFunction &) { return false; });
5861 CGF.FinishFunction();
5862 return Fn;
5863}
5864
5865/// Emits reduction combiner function:
5866/// \code
5867/// void @.red_comb(void* %arg0, void* %arg1) {
5868/// %lhs = bitcast void* %arg0 to <type>*
5869/// %rhs = bitcast void* %arg1 to <type>*
5870/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
5871/// store <type> %2, <type>* %lhs
5872/// ret void
5873/// }
5874/// \endcode
5875static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
5876 SourceLocation Loc,
5877 ReductionCodeGen &RCG, unsigned N,
5878 const Expr *ReductionOp,
5879 const Expr *LHS, const Expr *RHS,
5880 const Expr *PrivateRef) {
5881 ASTContext &C = CGM.getContext();
5882 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
5883 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
5884 FunctionArgList Args;
5885 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
5886 C.VoidPtrTy, ImplicitParamDecl::Other);
5887 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5888 ImplicitParamDecl::Other);
5889 Args.emplace_back(&ParamInOut);
5890 Args.emplace_back(&ParamIn);
5891 const auto &FnInfo =
5892 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5893 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
5894 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
5895 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5896 Name, &CGM.getModule());
5897 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
5898 Fn->setDoesNotRecurse();
5899 CodeGenFunction CGF(CGM);
5900 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
5901 llvm::Value *Size = nullptr;
5902 // If the size of the reduction item is non-constant, load it from global
5903 // threadprivate variable.
5904 if (RCG.getSizes(N).second) {
5905 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5906 CGF, CGM.getContext().getSizeType(),
5907 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
5908 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
5909 CGM.getContext().getSizeType(), Loc);
5910 }
5911 RCG.emitAggregateType(CGF, N, Size);
5912 // Remap lhs and rhs variables to the addresses of the function arguments.
5913 // %lhs = bitcast void* %arg0 to <type>*
5914 // %rhs = bitcast void* %arg1 to <type>*
5915 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5916 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
5917 // Pull out the pointer to the variable.
5918 Address PtrAddr = CGF.EmitLoadOfPointer(
5919 CGF.GetAddrOfLocalVar(&ParamInOut),
5920 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5921 return CGF.Builder.CreateElementBitCast(
5922 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
5923 });
5924 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
5925 // Pull out the pointer to the variable.
5926 Address PtrAddr = CGF.EmitLoadOfPointer(
5927 CGF.GetAddrOfLocalVar(&ParamIn),
5928 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5929 return CGF.Builder.CreateElementBitCast(
5930 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
5931 });
5932 PrivateScope.Privatize();
5933 // Emit the combiner body:
5934 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
5935 // store <type> %2, <type>* %lhs
5936 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
5937 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
5938 cast<DeclRefExpr>(RHS));
5939 CGF.FinishFunction();
5940 return Fn;
5941}
5942
5943/// Emits reduction finalizer function:
5944/// \code
5945/// void @.red_fini(void* %arg) {
5946/// %0 = bitcast void* %arg to <type>*
5947/// <destroy>(<type>* %0)
5948/// ret void
5949/// }
5950/// \endcode
5951static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
5952 SourceLocation Loc,
5953 ReductionCodeGen &RCG, unsigned N) {
5954 if (!RCG.needCleanups(N))
5955 return nullptr;
5956 ASTContext &C = CGM.getContext();
5957 FunctionArgList Args;
5958 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5959 ImplicitParamDecl::Other);
5960 Args.emplace_back(&Param);
5961 const auto &FnInfo =
5962 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5963 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
5964 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
5965 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5966 Name, &CGM.getModule());
5967 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
5968 Fn->setDoesNotRecurse();
5969 CodeGenFunction CGF(CGM);
5970 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
5971 Address PrivateAddr = CGF.EmitLoadOfPointer(
5972 CGF.GetAddrOfLocalVar(&Param),
5973 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5974 llvm::Value *Size = nullptr;
5975 // If the size of the reduction item is non-constant, load it from global
5976 // threadprivate variable.
5977 if (RCG.getSizes(N).second) {
5978 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5979 CGF, CGM.getContext().getSizeType(),
5980 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
5981 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
5982 CGM.getContext().getSizeType(), Loc);
5983 }
5984 RCG.emitAggregateType(CGF, N, Size);
5985 // Emit the finalizer body:
5986 // <destroy>(<type>* %0)
5987 RCG.emitCleanups(CGF, N, PrivateAddr);
5988 CGF.FinishFunction(Loc);
5989 return Fn;
5990}
5991
5992llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
5993 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
5994 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
5995 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
5996 return nullptr;
5997
5998 // Build typedef struct:
5999 // kmp_taskred_input {
6000 // void *reduce_shar; // shared reduction item
6001 // void *reduce_orig; // original reduction item used for initialization
6002 // size_t reduce_size; // size of data item
6003 // void *reduce_init; // data initialization routine
6004 // void *reduce_fini; // data finalization routine
6005 // void *reduce_comb; // data combiner routine
6006 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6007 // } kmp_taskred_input_t;
6008 ASTContext &C = CGM.getContext();
6009 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t");
6010 RD->startDefinition();
6011 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6012 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6013 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6014 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6015 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6016 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6017 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6018 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6019 RD->completeDefinition();
6020 QualType RDType = C.getRecordType(RD);
6021 unsigned Size = Data.ReductionVars.size();
6022 llvm::APInt ArraySize(/*numBits=*/64, Size);
6023 QualType ArrayRDType = C.getConstantArrayType(
6024 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
6025 // kmp_task_red_input_t .rd_input.[Size];
6026 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6027 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs,
6028 Data.ReductionCopies, Data.ReductionOps);
6029 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6030 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6031 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6032 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6033 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6034 TaskRedInput.getPointer(), Idxs,
6035 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6036 ".rd_input.gep.");
6037 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6038 // ElemLVal.reduce_shar = &Shareds[Cnt];
6039 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6040 RCG.emitSharedOrigLValue(CGF, Cnt);
6041 llvm::Value *CastedShared =
6042 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF));
6043 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6044 // ElemLVal.reduce_orig = &Origs[Cnt];
6045 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD);
6046 llvm::Value *CastedOrig =
6047 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF));
6048 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal);
6049 RCG.emitAggregateType(CGF, Cnt);
6050 llvm::Value *SizeValInChars;
6051 llvm::Value *SizeVal;
6052 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6053 // We use delayed creation/initialization for VLAs and array sections. It is
6054 // required because runtime does not provide the way to pass the sizes of
6055 // VLAs/array sections to initializer/combiner/finalizer functions. Instead
6056 // threadprivate global variables are used to store these values and use
6057 // them in the functions.
6058 bool DelayedCreation = !!SizeVal;
6059 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6060 /*isSigned=*/false);
6061 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6062 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6063 // ElemLVal.reduce_init = init;
6064 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6065 llvm::Value *InitAddr =
6066 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6067 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6068 // ElemLVal.reduce_fini = fini;
6069 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6070 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6071 llvm::Value *FiniAddr = Fini
6072 ? CGF.EmitCastToVoidPtr(Fini)
6073 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6074 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6075 // ElemLVal.reduce_comb = comb;
6076 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6077 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6078 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6079 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6080 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6081 // ElemLVal.flags = 0;
6082 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6083 if (DelayedCreation) {
6084 CGF.EmitStoreOfScalar(
6085 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
6086 FlagsLVal);
6087 } else
6088 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF),
6089 FlagsLVal.getType());
6090 }
6091 if (Data.IsReductionWithTaskMod) {
6092 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int
6093 // is_ws, int num, void *data);
6094 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc);
6095 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
6096 CGM.IntTy, /*isSigned=*/true);
6097 llvm::Value *Args[] = {
6098 IdentTLoc, GTid,
6099 llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0,
6100 /*isSigned=*/true),
6101 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6102 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6103 TaskRedInput.getPointer(), CGM.VoidPtrTy)};
6104 return CGF.EmitRuntimeCall(
6105 OMPBuilder.getOrCreateRuntimeFunction(
6106 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
6107 Args);
6108 }
6109 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data);
6110 llvm::Value *Args[] = {
6111 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6112 /*isSigned=*/true),
6113 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6114 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6115 CGM.VoidPtrTy)};
6116 return CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
6117 CGM.getModule(), OMPRTL___kmpc_taskred_init),
6118 Args);
6119}
6120
6121void CGOpenMPRuntime::emitTaskReductionFini(CodeGenFunction &CGF,
6122 SourceLocation Loc,
6123 bool IsWorksharingReduction) {
6124 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int
6125 // is_ws, int num, void *data);
6126 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc);
6127 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
6128 CGM.IntTy, /*isSigned=*/true);
6129 llvm::Value *Args[] = {IdentTLoc, GTid,
6130 llvm::ConstantInt::get(CGM.IntTy,
6131 IsWorksharingReduction ? 1 : 0,
6132 /*isSigned=*/true)};
6133 (void)CGF.EmitRuntimeCall(
6134 OMPBuilder.getOrCreateRuntimeFunction(
6135 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6136 Args);
6137}
6138
6139void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6140 SourceLocation Loc,
6141 ReductionCodeGen &RCG,
6142 unsigned N) {
6143 auto Sizes = RCG.getSizes(N);
6144 // Emit threadprivate global variable if the type is non-constant
6145 // (Sizes.second = nullptr).
6146 if (Sizes.second) {
6147 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6148 /*isSigned=*/false);
6149 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6150 CGF, CGM.getContext().getSizeType(),
6151 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
6152 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6153 }
6154}
6155
6156Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6157 SourceLocation Loc,
6158 llvm::Value *ReductionsPtr,
6159 LValue SharedLVal) {
6160 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6161 // *d);
6162 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
6163 CGM.IntTy,
6164 /*isSigned=*/true),
6165 ReductionsPtr,
6166 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6167 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)};
6168 return Address(
6169 CGF.EmitRuntimeCall(
6170 OMPBuilder.getOrCreateRuntimeFunction(
6171 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6172 Args),
6173 SharedLVal.getAlignment());
6174}
6175
6176void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6177 SourceLocation Loc) {
6178 if (!CGF.HaveInsertPoint())
6179 return;
6180
6181 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
6182 OMPBuilder.CreateTaskwait(CGF.Builder);
6183 } else {
6184 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6185 // global_tid);
6186 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6187 // Ignore return result until untied tasks are supported.
6188 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
6189 CGM.getModule(), OMPRTL___kmpc_omp_taskwait),
6190 Args);
6191 }
6192
6193 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6194 Region->emitUntiedSwitch(CGF);
6195}
6196
6197void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
6198 OpenMPDirectiveKind InnerKind,
6199 const RegionCodeGenTy &CodeGen,
6200 bool HasCancel) {
6201 if (!CGF.HaveInsertPoint())
6202 return;
6203 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
6204 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
6205}
6206
6207namespace {
6208enum RTCancelKind {
6209 CancelNoreq = 0,
6210 CancelParallel = 1,
6211 CancelLoop = 2,
6212 CancelSections = 3,
6213 CancelTaskgroup = 4
6214};
6215} // anonymous namespace
6216
6217static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6218 RTCancelKind CancelKind = CancelNoreq;
6219 if (CancelRegion == OMPD_parallel)
6220 CancelKind = CancelParallel;
6221 else if (CancelRegion == OMPD_for)
6222 CancelKind = CancelLoop;
6223 else if (CancelRegion == OMPD_sections)
6224 CancelKind = CancelSections;
6225 else {
6226 assert(CancelRegion == OMPD_taskgroup)((CancelRegion == OMPD_taskgroup) ? static_cast<void> (
0) : __assert_fail ("CancelRegion == OMPD_taskgroup", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6226, __PRETTY_FUNCTION__))
;
6227 CancelKind = CancelTaskgroup;
6228 }
6229 return CancelKind;
6230}
6231
6232void CGOpenMPRuntime::emitCancellationPointCall(
6233 CodeGenFunction &CGF, SourceLocation Loc,
6234 OpenMPDirectiveKind CancelRegion) {
6235 if (!CGF.HaveInsertPoint())
6236 return;
6237 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6238 // global_tid, kmp_int32 cncl_kind);
6239 if (auto *OMPRegionInfo =
6240 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
6241 // For 'cancellation point taskgroup', the task region info may not have a
6242 // cancel. This may instead happen in another adjacent task.
6243 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6244 llvm::Value *Args[] = {
6245 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6246 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6247 // Ignore return result until untied tasks are supported.
6248 llvm::Value *Result = CGF.EmitRuntimeCall(
6249 OMPBuilder.getOrCreateRuntimeFunction(
6250 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6251 Args);
6252 // if (__kmpc_cancellationpoint()) {
6253 // exit from construct;
6254 // }
6255 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6256 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6257 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
6258 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6259 CGF.EmitBlock(ExitBB);
6260 // exit from construct;
6261 CodeGenFunction::JumpDest CancelDest =
6262 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6263 CGF.EmitBranchThroughCleanup(CancelDest);
6264 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6265 }
6266 }
6267}
6268
6269void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
6270 const Expr *IfCond,
6271 OpenMPDirectiveKind CancelRegion) {
6272 if (!CGF.HaveInsertPoint())
6273 return;
6274 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6275 // kmp_int32 cncl_kind);
6276 auto &M = CGM.getModule();
6277 if (auto *OMPRegionInfo =
6278 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
6279 auto &&ThenGen = [this, &M, Loc, CancelRegion,
6280 OMPRegionInfo](CodeGenFunction &CGF, PrePostActionTy &) {
6281 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
6282 llvm::Value *Args[] = {
6283 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
6284 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6285 // Ignore return result until untied tasks are supported.
6286 llvm::Value *Result = CGF.EmitRuntimeCall(
6287 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6288 // if (__kmpc_cancel()) {
6289 // exit from construct;
6290 // }
6291 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6292 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6293 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
6294 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6295 CGF.EmitBlock(ExitBB);
6296 // exit from construct;
6297 CodeGenFunction::JumpDest CancelDest =
6298 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6299 CGF.EmitBranchThroughCleanup(CancelDest);
6300 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6301 };
6302 if (IfCond) {
6303 emitIfClause(CGF, IfCond, ThenGen,
6304 [](CodeGenFunction &, PrePostActionTy &) {});
6305 } else {
6306 RegionCodeGenTy ThenRCG(ThenGen);
6307 ThenRCG(CGF);
6308 }
6309 }
6310}
6311
6312namespace {
6313/// Cleanup action for uses_allocators support.
6314class OMPUsesAllocatorsActionTy final : public PrePostActionTy {
6315 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators;
6316
6317public:
6318 OMPUsesAllocatorsActionTy(
6319 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6320 : Allocators(Allocators) {}
6321 void Enter(CodeGenFunction &CGF) override {
6322 if (!CGF.HaveInsertPoint())
6323 return;
6324 for (const auto &AllocatorData : Allocators) {
6325 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsInit(
6326 CGF, AllocatorData.first, AllocatorData.second);
6327 }
6328 }
6329 void Exit(CodeGenFunction &CGF) override {
6330 if (!CGF.HaveInsertPoint())
6331 return;
6332 for (const auto &AllocatorData : Allocators) {
6333 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsFini(CGF,
6334 AllocatorData.first);
6335 }
6336 }
6337};
6338} // namespace
6339
6340void CGOpenMPRuntime::emitTargetOutlinedFunction(
6341 const OMPExecutableDirective &D, StringRef ParentName,
6342 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6343 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
6344 assert(!ParentName.empty() && "Invalid target region parent name!")((!ParentName.empty() && "Invalid target region parent name!"
) ? static_cast<void> (0) : __assert_fail ("!ParentName.empty() && \"Invalid target region parent name!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6344, __PRETTY_FUNCTION__))
;
6345 HasEmittedTargetRegion = true;
6346 SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators;
6347 for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) {
6348 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
6349 const OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
6350 if (!D.AllocatorTraits)
6351 continue;
6352 Allocators.emplace_back(D.Allocator, D.AllocatorTraits);
6353 }
6354 }
6355 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6356 CodeGen.setAction(UsesAllocatorAction);
6357 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6358 IsOffloadEntry, CodeGen);
6359}
6360
6361void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF,
6362 const Expr *Allocator,
6363 const Expr *AllocatorTraits) {
6364 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc());
6365 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true);
6366 // Use default memspace handle.
6367 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
6368 llvm::Value *NumTraits = llvm::ConstantInt::get(
6369 CGF.IntTy, cast<ConstantArrayType>(
6370 AllocatorTraits->getType()->getAsArrayTypeUnsafe())
6371 ->getSize()
6372 .getLimitedValue());
6373 LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits);
6374 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6375 AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy);
6376 AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy,
6377 AllocatorTraitsLVal.getBaseInfo(),
6378 AllocatorTraitsLVal.getTBAAInfo());
6379 llvm::Value *Traits =
6380 CGF.EmitLoadOfScalar(AllocatorTraitsLVal, AllocatorTraits->getExprLoc());
6381
6382 llvm::Value *AllocatorVal =
6383 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
6384 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6385 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6386 // Store to allocator.
6387 CGF.EmitVarDecl(*cast<VarDecl>(
6388 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl()));
6389 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts());
6390 AllocatorVal =
6391 CGF.EmitScalarConversion(AllocatorVal, CGF.getContext().VoidPtrTy,
6392 Allocator->getType(), Allocator->getExprLoc());
6393 CGF.EmitStoreOfScalar(AllocatorVal, AllocatorLVal);
6394}
6395
6396void CGOpenMPRuntime::emitUsesAllocatorsFini(CodeGenFunction &CGF,
6397 const Expr *Allocator) {
6398 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc());
6399 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true);
6400 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts());
6401 llvm::Value *AllocatorVal =
6402 CGF.EmitLoadOfScalar(AllocatorLVal, Allocator->getExprLoc());
6403 AllocatorVal = CGF.EmitScalarConversion(AllocatorVal, Allocator->getType(),
6404 CGF.getContext().VoidPtrTy,
6405 Allocator->getExprLoc());
6406 (void)CGF.EmitRuntimeCall(
6407 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
6408 OMPRTL___kmpc_destroy_allocator),
6409 {ThreadId, AllocatorVal});
6410}
6411
6412void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6413 const OMPExecutableDirective &D, StringRef ParentName,
6414 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6415 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
6416 // Create a unique name for the entry function using the source location
6417 // information of the current target region. The name will be something like:
6418 //
6419 // __omp_offloading_DD_FFFF_PP_lBB
6420 //
6421 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
6422 // mangled name of the function that encloses the target region and BB is the
6423 // line number of the target region.
6424
6425 unsigned DeviceID;
6426 unsigned FileID;
6427 unsigned Line;
6428 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
6429 Line);
6430 SmallString<64> EntryFnName;
6431 {
6432 llvm::raw_svector_ostream OS(EntryFnName);
6433 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6434 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
6435 }
6436
6437 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6438
6439 CodeGenFunction CGF(CGM, true);
6440 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
6441 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6442
6443 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc());
6444
6445 // If this target outline function is not an offload entry, we don't need to
6446 // register it.
6447 if (!IsOffloadEntry)
6448 return;
6449
6450 // The target region ID is used by the runtime library to identify the current
6451 // target region, so it only has to be unique and not necessarily point to
6452 // anything. It could be the pointer to the outlined function that implements
6453 // the target region, but we aren't using that so that the compiler doesn't
6454 // need to keep that, and could therefore inline the host function if proven
6455 // worthwhile during optimization. In the other hand, if emitting code for the
6456 // device, the ID has to be the function address so that it can retrieved from
6457 // the offloading entry and launched by the runtime library. We also mark the
6458 // outlined function to have external linkage in case we are emitting code for
6459 // the device, because these functions will be entry points to the device.
6460
6461 if (CGM.getLangOpts().OpenMPIsDevice) {
6462 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
6463 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
6464 OutlinedFn->setDSOLocal(false);
6465 } else {
6466 std::string Name = getName({EntryFnName, "region_id"});
6467 OutlinedFnID = new llvm::GlobalVariable(
6468 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
6469 llvm::GlobalValue::WeakAnyLinkage,
6470 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
6471 }
6472
6473 // Register the information for the entry associated with this target region.
6474 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
6475 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
6476 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
6477}
6478
6479/// Checks if the expression is constant or does not have non-trivial function
6480/// calls.
6481static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6482 // We can skip constant expressions.
6483 // We can skip expressions with trivial calls or simple expressions.
6484 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6485 !E->hasNonTrivialCall(Ctx)) &&
6486 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6487}
6488
6489const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6490 const Stmt *Body) {
6491 const Stmt *Child = Body->IgnoreContainers();
6492 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6493 Child = nullptr;
6494 for (const Stmt *S : C->body()) {
6495 if (const auto *E = dyn_cast<Expr>(S)) {
6496 if (isTrivial(Ctx, E))
6497 continue;
6498 }
6499 // Some of the statements can be ignored.
6500 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6501 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6502 continue;
6503 // Analyze declarations.
6504 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6505 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6506 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6507 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6508 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6509 isa<UsingDirectiveDecl>(D) ||
6510 isa<OMPDeclareReductionDecl>(D) ||
6511 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6512 return true;
6513 const auto *VD = dyn_cast<VarDecl>(D);
6514 if (!VD)
6515 return false;
6516 return VD->isConstexpr() ||
6517 ((VD->getType().isTrivialType(Ctx) ||
6518 VD->getType()->isReferenceType()) &&
6519 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6520 }))
6521 continue;
6522 }
6523 // Found multiple children - cannot get the one child only.
6524 if (Child)
6525 return nullptr;
6526 Child = S;
6527 }
6528 if (Child)
6529 Child = Child->IgnoreContainers();
6530 }
6531 return Child;
6532}
6533
6534/// Emit the number of teams for a target directive. Inspect the num_teams
6535/// clause associated with a teams construct combined or closely nested
6536/// with the target directive.
6537///
6538/// Emit a team of size one for directives such as 'target parallel' that
6539/// have no associated teams construct.
6540///
6541/// Otherwise, return nullptr.
6542static llvm::Value *
6543emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
6544 const OMPExecutableDirective &D) {
6545 assert(!CGF.getLangOpts().OpenMPIsDevice &&((!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? static_cast<void> (0) : __assert_fail
("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6547, __PRETTY_FUNCTION__))
6546 "Clauses associated with the teams directive expected to be emitted "((!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? static_cast<void> (0) : __assert_fail
("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6547, __PRETTY_FUNCTION__))
6547 "only for the host!")((!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? static_cast<void> (0) : __assert_fail
("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6547, __PRETTY_FUNCTION__))
;
6548 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6549 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&((isOpenMPTargetExecutionDirective(DirectiveKind) && "Expected target-based executable directive."
) ? static_cast<void> (0) : __assert_fail ("isOpenMPTargetExecutionDirective(DirectiveKind) && \"Expected target-based executable directive.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6550, __PRETTY_FUNCTION__))
6550 "Expected target-based executable directive.")((isOpenMPTargetExecutionDirective(DirectiveKind) && "Expected target-based executable directive."
) ? static_cast<void> (0) : __assert_fail ("isOpenMPTargetExecutionDirective(DirectiveKind) && \"Expected target-based executable directive.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6550, __PRETTY_FUNCTION__))
;
6551 CGBuilderTy &Bld = CGF.Builder;
6552 switch (DirectiveKind) {
6553 case OMPD_target: {
6554 const auto *CS = D.getInnermostCapturedStmt();
6555 const auto *Body =
6556 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6557 const Stmt *ChildStmt =
6558 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6559 if (const auto *NestedDir =
6560 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6561 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6562 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6563 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6564 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6565 const Expr *NumTeams =
6566 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6567 llvm::Value *NumTeamsVal =
6568 CGF.EmitScalarExpr(NumTeams,
6569 /*IgnoreResultAssign*/ true);
6570 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6571 /*isSigned=*/true);
6572 }
6573 return Bld.getInt32(0);
6574 }
6575 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6576 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6577 return Bld.getInt32(1);
6578 return Bld.getInt32(0);
6579 }
6580 return nullptr;
6581 }
6582 case OMPD_target_teams:
6583 case OMPD_target_teams_distribute:
6584 case OMPD_target_teams_distribute_simd:
6585 case OMPD_target_teams_distribute_parallel_for:
6586 case OMPD_target_teams_distribute_parallel_for_simd: {
6587 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6588 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6589 const Expr *NumTeams =
6590 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6591 llvm::Value *NumTeamsVal =
6592 CGF.EmitScalarExpr(NumTeams,
6593 /*IgnoreResultAssign*/ true);
6594 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6595 /*isSigned=*/true);
6596 }
6597 return Bld.getInt32(0);
6598 }
6599 case OMPD_target_parallel:
6600 case OMPD_target_parallel_for:
6601 case OMPD_target_parallel_for_simd:
6602 case OMPD_target_simd:
6603 return Bld.getInt32(1);
6604 case OMPD_parallel:
6605 case OMPD_for:
6606 case OMPD_parallel_for:
6607 case OMPD_parallel_master:
6608 case OMPD_parallel_sections:
6609 case OMPD_for_simd:
6610 case OMPD_parallel_for_simd:
6611 case OMPD_cancel:
6612 case OMPD_cancellation_point:
6613 case OMPD_ordered:
6614 case OMPD_threadprivate:
6615 case OMPD_allocate:
6616 case OMPD_task:
6617 case OMPD_simd:
6618 case OMPD_sections:
6619 case OMPD_section:
6620 case OMPD_single:
6621 case OMPD_master:
6622 case OMPD_critical:
6623 case OMPD_taskyield:
6624 case OMPD_barrier:
6625 case OMPD_taskwait:
6626 case OMPD_taskgroup:
6627 case OMPD_atomic:
6628 case OMPD_flush:
6629 case OMPD_depobj:
6630 case OMPD_scan:
6631 case OMPD_teams:
6632 case OMPD_target_data:
6633 case OMPD_target_exit_data:
6634 case OMPD_target_enter_data:
6635 case OMPD_distribute:
6636 case OMPD_distribute_simd:
6637 case OMPD_distribute_parallel_for:
6638 case OMPD_distribute_parallel_for_simd:
6639 case OMPD_teams_distribute:
6640 case OMPD_teams_distribute_simd:
6641 case OMPD_teams_distribute_parallel_for:
6642 case OMPD_teams_distribute_parallel_for_simd:
6643 case OMPD_target_update:
6644 case OMPD_declare_simd:
6645 case OMPD_declare_variant:
6646 case OMPD_begin_declare_variant:
6647 case OMPD_end_declare_variant:
6648 case OMPD_declare_target:
6649 case OMPD_end_declare_target:
6650 case OMPD_declare_reduction:
6651 case OMPD_declare_mapper:
6652 case OMPD_taskloop:
6653 case OMPD_taskloop_simd:
6654 case OMPD_master_taskloop:
6655 case OMPD_master_taskloop_simd:
6656 case OMPD_parallel_master_taskloop:
6657 case OMPD_parallel_master_taskloop_simd:
6658 case OMPD_requires:
6659 case OMPD_unknown:
6660 break;
6661 default:
6662 break;
6663 }
6664 llvm_unreachable("Unexpected directive kind.")::llvm::llvm_unreachable_internal("Unexpected directive kind."
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6664)
;
6665}
6666
6667static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6668 llvm::Value *DefaultThreadLimitVal) {
6669 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6670 CGF.getContext(), CS->getCapturedStmt());
6671 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6672 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
6673 llvm::Value *NumThreads = nullptr;
6674 llvm::Value *CondVal = nullptr;
6675 // Handle if clause. If if clause present, the number of threads is
6676 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6677 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6678 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6679 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6680 const OMPIfClause *IfClause = nullptr;
6681 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6682 if (C->getNameModifier() == OMPD_unknown ||
6683 C->getNameModifier() == OMPD_parallel) {
6684 IfClause = C;
6685 break;
6686 }
6687 }
6688 if (IfClause) {
6689 const Expr *Cond = IfClause->getCondition();
6690 bool Result;
6691 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6692 if (!Result)
6693 return CGF.Builder.getInt32(1);
6694 } else {
6695 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6696 if (const auto *PreInit =
6697 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6698 for (const auto *I : PreInit->decls()) {
6699 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6700 CGF.EmitVarDecl(cast<VarDecl>(*I));
6701 } else {
6702 CodeGenFunction::AutoVarEmission Emission =
6703 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6704 CGF.EmitAutoVarCleanups(Emission);
6705 }
6706 }
6707 }
6708 CondVal = CGF.EvaluateExprAsBool(Cond);
6709 }
6710 }
6711 }
6712 // Check the value of num_threads clause iff if clause was not specified
6713 // or is not evaluated to false.
6714 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6715 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6716 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6717 const auto *NumThreadsClause =
6718 Dir->getSingleClause<OMPNumThreadsClause>();
6719 CodeGenFunction::LexicalScope Scope(
6720 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6721 if (const auto *PreInit =
6722 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6723 for (const auto *I : PreInit->decls()) {
6724 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6725 CGF.EmitVarDecl(cast<VarDecl>(*I));
6726 } else {
6727 CodeGenFunction::AutoVarEmission Emission =
6728 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6729 CGF.EmitAutoVarCleanups(Emission);
6730 }
6731 }
6732 }
6733 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
6734 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
6735 /*isSigned=*/false);
6736 if (DefaultThreadLimitVal)
6737 NumThreads = CGF.Builder.CreateSelect(
6738 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6739 DefaultThreadLimitVal, NumThreads);
6740 } else {
6741 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6742 : CGF.Builder.getInt32(0);
6743 }
6744 // Process condition of the if clause.
6745 if (CondVal) {
6746 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6747 CGF.Builder.getInt32(1));
6748 }
6749 return NumThreads;
6750 }
6751 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6752 return CGF.Builder.getInt32(1);
6753 return DefaultThreadLimitVal;
6754 }
6755 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6756 : CGF.Builder.getInt32(0);
6757}
6758
6759/// Emit the number of threads for a target directive. Inspect the
6760/// thread_limit clause associated with a teams construct combined or closely
6761/// nested with the target directive.
6762///
6763/// Emit the num_threads clause for directives such as 'target parallel' that
6764/// have no associated teams construct.
6765///
6766/// Otherwise, return nullptr.
6767static llvm::Value *
6768emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
6769 const OMPExecutableDirective &D) {
6770 assert(!CGF.getLangOpts().OpenMPIsDevice &&((!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? static_cast<void> (0) : __assert_fail
("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6772, __PRETTY_FUNCTION__))
6771 "Clauses associated with the teams directive expected to be emitted "((!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? static_cast<void> (0) : __assert_fail
("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6772, __PRETTY_FUNCTION__))
6772 "only for the host!")((!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the teams directive expected to be emitted "
"only for the host!") ? static_cast<void> (0) : __assert_fail
("!CGF.getLangOpts().OpenMPIsDevice && \"Clauses associated with the teams directive expected to be emitted \" \"only for the host!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6772, __PRETTY_FUNCTION__))
;
6773 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6774 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&((isOpenMPTargetExecutionDirective(DirectiveKind) && "Expected target-based executable directive."
) ? static_cast<void> (0) : __assert_fail ("isOpenMPTargetExecutionDirective(DirectiveKind) && \"Expected target-based executable directive.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6775, __PRETTY_FUNCTION__))
6775 "Expected target-based executable directive.")((isOpenMPTargetExecutionDirective(DirectiveKind) && "Expected target-based executable directive."
) ? static_cast<void> (0) : __assert_fail ("isOpenMPTargetExecutionDirective(DirectiveKind) && \"Expected target-based executable directive.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6775, __PRETTY_FUNCTION__))
;
6776 CGBuilderTy &Bld = CGF.Builder;
6777 llvm::Value *ThreadLimitVal = nullptr;
6778 llvm::Value *NumThreadsVal = nullptr;
6779 switch (DirectiveKind) {
6780 case OMPD_target: {
6781 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6782 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6783 return NumThreads;
6784 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6785 CGF.getContext(), CS->getCapturedStmt());
6786 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6787 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6788 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6789 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6790 const auto *ThreadLimitClause =
6791 Dir->getSingleClause<OMPThreadLimitClause>();
6792 CodeGenFunction::LexicalScope Scope(
6793 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6794 if (const auto *PreInit =
6795 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6796 for (const auto *I : PreInit->decls()) {
6797 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6798 CGF.EmitVarDecl(cast<VarDecl>(*I));
6799 } else {
6800 CodeGenFunction::AutoVarEmission Emission =
6801 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6802 CGF.EmitAutoVarCleanups(Emission);
6803 }
6804 }
6805 }
6806 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6807 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6808 ThreadLimitVal =
6809 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6810 }
6811 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6812 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6813 CS = Dir->getInnermostCapturedStmt();
6814 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6815 CGF.getContext(), CS->getCapturedStmt());
6816 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6817 }
6818 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6819 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6820 CS = Dir->getInnermostCapturedStmt();
6821 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6822 return NumThreads;
6823 }
6824 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6825 return Bld.getInt32(1);
6826 }
6827 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6828 }
6829 case OMPD_target_teams: {
6830 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6831 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6832 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6833 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6834 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6835 ThreadLimitVal =
6836 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6837 }
6838 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6839 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6840 return NumThreads;
6841 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6842 CGF.getContext(), CS->getCapturedStmt());
6843 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6844 if (Dir->getDirectiveKind() == OMPD_distribute) {
6845 CS = Dir->getInnermostCapturedStmt();
6846 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6847 return NumThreads;
6848 }
6849 }
6850 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6851 }
6852 case OMPD_target_teams_distribute:
6853 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6854 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6855 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6856 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6857 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6858 ThreadLimitVal =
6859 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6860 }
6861 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6862 case OMPD_target_parallel:
6863 case OMPD_target_parallel_for:
6864 case OMPD_target_parallel_for_simd:
6865 case OMPD_target_teams_distribute_parallel_for:
6866 case OMPD_target_teams_distribute_parallel_for_simd: {
6867 llvm::Value *CondVal = nullptr;
6868 // Handle if clause. If if clause present, the number of threads is
6869 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6870 if (D.hasClausesOfKind<OMPIfClause>()) {
6871 const OMPIfClause *IfClause = nullptr;
6872 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6873 if (C->getNameModifier() == OMPD_unknown ||
6874 C->getNameModifier() == OMPD_parallel) {
6875 IfClause = C;
6876 break;
6877 }
6878 }
6879 if (IfClause) {
6880 const Expr *Cond = IfClause->getCondition();
6881 bool Result;
6882 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6883 if (!Result)
6884 return Bld.getInt32(1);
6885 } else {
6886 CodeGenFunction::RunCleanupsScope Scope(CGF);
6887 CondVal = CGF.EvaluateExprAsBool(Cond);
6888 }
6889 }
6890 }
6891 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6892 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6893 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6894 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6895 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6896 ThreadLimitVal =
6897 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6898 }
6899 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
6900 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
6901 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6902 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6903 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
6904 NumThreadsVal =
6905 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
6906 ThreadLimitVal = ThreadLimitVal
6907 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
6908 ThreadLimitVal),
6909 NumThreadsVal, ThreadLimitVal)
6910 : NumThreadsVal;
6911 }
6912 if (!ThreadLimitVal)
6913 ThreadLimitVal = Bld.getInt32(0);
6914 if (CondVal)
6915 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6916 return ThreadLimitVal;
6917 }
6918 case OMPD_target_teams_distribute_simd:
6919 case OMPD_target_simd:
6920 return Bld.getInt32(1);
6921 case OMPD_parallel:
6922 case OMPD_for:
6923 case OMPD_parallel_for:
6924 case OMPD_parallel_master:
6925 case OMPD_parallel_sections:
6926 case OMPD_for_simd:
6927 case OMPD_parallel_for_simd:
6928 case OMPD_cancel:
6929 case OMPD_cancellation_point:
6930 case OMPD_ordered:
6931 case OMPD_threadprivate:
6932 case OMPD_allocate:
6933 case OMPD_task:
6934 case OMPD_simd:
6935 case OMPD_sections:
6936 case OMPD_section:
6937 case OMPD_single:
6938 case OMPD_master:
6939 case OMPD_critical:
6940 case OMPD_taskyield:
6941 case OMPD_barrier:
6942 case OMPD_taskwait:
6943 case OMPD_taskgroup:
6944 case OMPD_atomic:
6945 case OMPD_flush:
6946 case OMPD_depobj:
6947 case OMPD_scan:
6948 case OMPD_teams:
6949 case OMPD_target_data:
6950 case OMPD_target_exit_data:
6951 case OMPD_target_enter_data:
6952 case OMPD_distribute:
6953 case OMPD_distribute_simd:
6954 case OMPD_distribute_parallel_for:
6955 case OMPD_distribute_parallel_for_simd:
6956 case OMPD_teams_distribute:
6957 case OMPD_teams_distribute_simd:
6958 case OMPD_teams_distribute_parallel_for:
6959 case OMPD_teams_distribute_parallel_for_simd:
6960 case OMPD_target_update:
6961 case OMPD_declare_simd:
6962 case OMPD_declare_variant:
6963 case OMPD_begin_declare_variant:
6964 case OMPD_end_declare_variant:
6965 case OMPD_declare_target:
6966 case OMPD_end_declare_target:
6967 case OMPD_declare_reduction:
6968 case OMPD_declare_mapper:
6969 case OMPD_taskloop:
6970 case OMPD_taskloop_simd:
6971 case OMPD_master_taskloop:
6972 case OMPD_master_taskloop_simd:
6973 case OMPD_parallel_master_taskloop:
6974 case OMPD_parallel_master_taskloop_simd:
6975 case OMPD_requires:
6976 case OMPD_unknown:
6977 break;
6978 default:
6979 break;
6980 }
6981 llvm_unreachable("Unsupported directive kind.")::llvm::llvm_unreachable_internal("Unsupported directive kind."
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6981)
;
6982}
6983
6984namespace {
6985LLVM_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^=
;
6986
6987// Utility to handle information from clauses associated with a given
6988// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
6989// It provides a convenient interface to obtain the information and generate
6990// code for that information.
6991class MappableExprsHandler {
6992public:
6993 /// Values for bit flags used to specify the mapping type for
6994 /// offloading.
6995 enum OpenMPOffloadMappingFlags : uint64_t {
6996 /// No flags
6997 OMP_MAP_NONE = 0x0,
6998 /// Allocate memory on the device and move data from host to device.
6999 OMP_MAP_TO = 0x01,
7000 /// Allocate memory on the device and move data from device to host.
7001 OMP_MAP_FROM = 0x02,
7002 /// Always perform the requested mapping action on the element, even
7003 /// if it was already mapped before.
7004 OMP_MAP_ALWAYS = 0x04,
7005 /// Delete the element from the device environment, ignoring the
7006 /// current reference count associated with the element.
7007 OMP_MAP_DELETE = 0x08,
7008 /// The element being mapped is a pointer-pointee pair; both the
7009 /// pointer and the pointee should be mapped.
7010 OMP_MAP_PTR_AND_OBJ = 0x10,
7011 /// This flags signals that the base address of an entry should be
7012 /// passed to the target kernel as an argument.
7013 OMP_MAP_TARGET_PARAM = 0x20,
7014 /// Signal that the runtime library has to return the device pointer
7015 /// in the current position for the data being mapped. Used when we have the
7016 /// use_device_ptr or use_device_addr clause.
7017 OMP_MAP_RETURN_PARAM = 0x40,
7018 /// This flag signals that the reference being passed is a pointer to
7019 /// private data.
7020 OMP_MAP_PRIVATE = 0x80,
7021 /// Pass the element to the device by value.
7022 OMP_MAP_LITERAL = 0x100,
7023 /// Implicit map
7024 OMP_MAP_IMPLICIT = 0x200,
7025 /// Close is a hint to the runtime to allocate memory close to
7026 /// the target device.
7027 OMP_MAP_CLOSE = 0x400,
7028 /// 0x800 is reserved for compatibility with XLC.
7029 /// Produce a runtime error if the data is not already allocated.
7030 OMP_MAP_PRESENT = 0x1000,
7031 /// The 16 MSBs of the flags indicate whether the entry is member of some
7032 /// struct/class.
7033 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7034 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_MAP_MEMBER_OF,
7035 };
7036
7037 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7038 static unsigned getFlagMemberOffset() {
7039 unsigned Offset = 0;
7040 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7041 Remain = Remain >> 1)
7042 Offset++;
7043 return Offset;
7044 }
7045
7046 /// Class that associates information with a base pointer to be passed to the
7047 /// runtime library.
7048 class BasePointerInfo {
7049 /// The base pointer.
7050 llvm::Value *Ptr = nullptr;
7051 /// The base declaration that refers to this device pointer, or null if
7052 /// there is none.
7053 const ValueDecl *DevPtrDecl = nullptr;
7054
7055 public:
7056 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7057 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7058 llvm::Value *operator*() const { return Ptr; }
7059 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7060 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7061 };
7062
7063 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7064 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7065 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7066 using MapMappersArrayTy = SmallVector<const ValueDecl *, 4>;
7067
7068 /// This structure contains combined information generated for mappable
7069 /// clauses, including base pointers, pointers, sizes, map types, and
7070 /// user-defined mappers.
7071 struct MapCombinedInfoTy {
7072 MapBaseValuesArrayTy BasePointers;
7073 MapValuesArrayTy Pointers;
7074 MapValuesArrayTy Sizes;
7075 MapFlagsArrayTy Types;
7076 MapMappersArrayTy Mappers;
7077
7078 /// Append arrays in \a CurInfo.
7079 void append(MapCombinedInfoTy &CurInfo) {
7080 BasePointers.append(CurInfo.BasePointers.begin(),
7081 CurInfo.BasePointers.end());
7082 Pointers.append(CurInfo.Pointers.begin(), CurInfo.Pointers.end());
7083 Sizes.append(CurInfo.Sizes.begin(), CurInfo.Sizes.end());
7084 Types.append(CurInfo.Types.begin(), CurInfo.Types.end());
7085 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7086 }
7087 };
7088
7089 /// Map between a struct and the its lowest & highest elements which have been
7090 /// mapped.
7091 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7092 /// HE(FieldIndex, Pointer)}
7093 struct StructRangeInfoTy {
7094 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7095 0, Address::invalid()};
7096 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7097 0, Address::invalid()};
7098 Address Base = Address::invalid();
7099 };
7100
7101private:
7102 /// Kind that defines how a device pointer has to be returned.
7103 struct MapInfo {
7104 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7105 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
7106 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7107 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7108 bool ReturnDevicePointer = false;
7109 bool IsImplicit = false;
7110 const ValueDecl *Mapper = nullptr;
7111 bool ForDeviceAddr = false;
7112
7113 MapInfo() = default;
7114 MapInfo(
7115 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
7116 OpenMPMapClauseKind MapType,
7117 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7118 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7119 bool ReturnDevicePointer, bool IsImplicit,
7120 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false)
7121 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7122 MotionModifiers(MotionModifiers),
7123 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7124 Mapper(Mapper), ForDeviceAddr(ForDeviceAddr) {}
7125 };
7126
7127 /// If use_device_ptr or use_device_addr is used on a decl which is a struct
7128 /// member and there is no map information about it, then emission of that
7129 /// entry is deferred until the whole struct has been processed.
7130 struct DeferredDevicePtrEntryTy {
7131 const Expr *IE = nullptr;
7132 const ValueDecl *VD = nullptr;
7133 bool ForDeviceAddr = false;
7134
7135 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD,
7136 bool ForDeviceAddr)
7137 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {}
7138 };
7139
7140 /// The target directive from where the mappable clauses were extracted. It
7141 /// is either a executable directive or a user-defined mapper directive.
7142 llvm::PointerUnion<const OMPExecutableDirective *,
7143 const OMPDeclareMapperDecl *>
7144 CurDir;
7145
7146 /// Function the directive is being generated for.
7147 CodeGenFunction &CGF;
7148
7149 /// Set of all first private variables in the current directive.
7150 /// bool data is set to true if the variable is implicitly marked as
7151 /// firstprivate, false otherwise.
7152 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
7153
7154 /// Map between device pointer declarations and their expression components.
7155 /// The key value for declarations in 'this' is null.
7156 llvm::DenseMap<
7157 const ValueDecl *,
7158 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7159 DevPointersMap;
7160
7161 llvm::Value *getExprTypeSize(const Expr *E) const {
7162 QualType ExprTy = E->getType().getCanonicalType();
7163
7164 // Calculate the size for array shaping expression.
7165 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7166 llvm::Value *Size =
7167 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType());
7168 for (const Expr *SE : OAE->getDimensions()) {
7169 llvm::Value *Sz = CGF.EmitScalarExpr(SE);
7170 Sz = CGF.EmitScalarConversion(Sz, SE->getType(),
7171 CGF.getContext().getSizeType(),
7172 SE->getExprLoc());
7173 Size = CGF.Builder.CreateNUWMul(Size, Sz);
7174 }
7175 return Size;
7176 }
7177
7178 // Reference types are ignored for mapping purposes.
7179 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
7180 ExprTy = RefTy->getPointeeType().getCanonicalType();
7181
7182 // Given that an array section is considered a built-in type, we need to
7183 // do the calculation based on the length of the section instead of relying
7184 // on CGF.getTypeSize(E->getType()).
7185 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7186 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7187 OAE->getBase()->IgnoreParenImpCasts())
7188 .getCanonicalType();
7189
7190 // If there is no length associated with the expression and lower bound is
7191 // not specified too, that means we are using the whole length of the
7192 // base.
7193 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7194 !OAE->getLowerBound())
7195 return CGF.getTypeSize(BaseTy);
7196
7197 llvm::Value *ElemSize;
7198 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
7199 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
7200 } else {
7201 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
7202 assert(ATy && "Expecting array type if not a pointer type.")((ATy && "Expecting array type if not a pointer type."
) ? static_cast<void> (0) : __assert_fail ("ATy && \"Expecting array type if not a pointer type.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7202, __PRETTY_FUNCTION__))
;
7203 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7204 }
7205
7206 // If we don't have a length at this point, that is because we have an
7207 // array section with a single element.
7208 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7209 return ElemSize;
7210
7211 if (const Expr *LenExpr = OAE->getLength()) {
7212 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7213 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7214 CGF.getContext().getSizeType(),
7215 LenExpr->getExprLoc());
7216 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7217 }
7218 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&((!OAE->getLength() && OAE->getColonLocFirst().
isValid() && OAE->getLowerBound() && "expected array_section[lb:]."
) ? static_cast<void> (0) : __assert_fail ("!OAE->getLength() && OAE->getColonLocFirst().isValid() && OAE->getLowerBound() && \"expected array_section[lb:].\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7219, __PRETTY_FUNCTION__))
7219 OAE->getLowerBound() && "expected array_section[lb:].")((!OAE->getLength() && OAE->getColonLocFirst().
isValid() && OAE->getLowerBound() && "expected array_section[lb:]."
) ? static_cast<void> (0) : __assert_fail ("!OAE->getLength() && OAE->getColonLocFirst().isValid() && OAE->getLowerBound() && \"expected array_section[lb:].\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7219, __PRETTY_FUNCTION__))
;
7220 // Size = sizetype - lb * elemtype;
7221 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7222 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7223 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7224 CGF.getContext().getSizeType(),
7225 OAE->getLowerBound()->getExprLoc());
7226 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7227 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7228 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7229 LengthVal = CGF.Builder.CreateSelect(
7230 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7231 return LengthVal;
7232 }
7233 return CGF.getTypeSize(ExprTy);
7234 }
7235
7236 /// Return the corresponding bits for a given map clause modifier. Add
7237 /// a flag marking the map as a pointer if requested. Add a flag marking the
7238 /// map as the first one of a series of maps that relate to the same map
7239 /// expression.
7240 OpenMPOffloadMappingFlags getMapTypeBits(
7241 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7242 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit,
7243 bool AddPtrFlag, bool AddIsTargetParamFlag) const {
7244 OpenMPOffloadMappingFlags Bits =
7245 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
7246 switch (MapType) {
7247 case OMPC_MAP_alloc:
7248 case OMPC_MAP_release:
7249 // alloc and release is the default behavior in the runtime library, i.e.
7250 // if we don't pass any bits alloc/release that is what the runtime is
7251 // going to do. Therefore, we don't need to signal anything for these two
7252 // type modifiers.
7253 break;
7254 case OMPC_MAP_to:
7255 Bits |= OMP_MAP_TO;
7256 break;
7257 case OMPC_MAP_from:
7258 Bits |= OMP_MAP_FROM;
7259 break;
7260 case OMPC_MAP_tofrom:
7261 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
7262 break;
7263 case OMPC_MAP_delete:
7264 Bits |= OMP_MAP_DELETE;
7265 break;
7266 case OMPC_MAP_unknown:
7267 llvm_unreachable("Unexpected map type!")::llvm::llvm_unreachable_internal("Unexpected map type!", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7267)
;
7268 }
7269 if (AddPtrFlag)
7270 Bits |= OMP_MAP_PTR_AND_OBJ;
7271 if (AddIsTargetParamFlag)
7272 Bits |= OMP_MAP_TARGET_PARAM;
7273 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7274 != MapModifiers.end())
7275 Bits |= OMP_MAP_ALWAYS;
7276 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7277 != MapModifiers.end())
7278 Bits |= OMP_MAP_CLOSE;
7279 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_present)
7280 != MapModifiers.end())
7281 Bits |= OMP_MAP_PRESENT;
7282 if (llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present)
7283 != MotionModifiers.end())
7284 Bits |= OMP_MAP_PRESENT;
7285 return Bits;
7286 }
7287
7288 /// Return true if the provided expression is a final array section. A
7289 /// final array section, is one whose length can't be proved to be one.
7290 bool isFinalArraySectionExpression(const Expr *E) const {
7291 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
7292
7293 // It is not an array section and therefore not a unity-size one.
7294 if (!OASE)
7295 return false;
7296
7297 // An array section with no colon always refer to a single element.
7298 if (OASE->getColonLocFirst().isInvalid())
7299 return false;
7300
7301 const Expr *Length = OASE->getLength();
7302
7303 // If we don't have a length we have to check if the array has size 1
7304 // for this dimension. Also, we should always expect a length if the
7305 // base type is pointer.
7306 if (!Length) {
7307 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7308 OASE->getBase()->IgnoreParenImpCasts())
7309 .getCanonicalType();
7310 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
7311 return ATy->getSize().getSExtValue() != 1;
7312 // If we don't have a constant dimension length, we have to consider
7313 // the current section as having any size, so it is not necessarily
7314 // unitary. If it happen to be unity size, that's user fault.
7315 return true;
7316 }
7317
7318 // Check if the length evaluates to 1.
7319 Expr::EvalResult Result;
7320 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
7321 return true; // Can have more that size 1.
7322
7323 llvm::APSInt ConstLength = Result.Val.getInt();
7324 return ConstLength.getSExtValue() != 1;
7325 }
7326
7327 /// Generate the base pointers, section pointers, sizes, map type bits, and
7328 /// user-defined mappers (all included in \a CombinedInfo) for the provided
7329 /// map type, map or motion modifiers, and expression components.
7330 /// \a IsFirstComponent should be set to true if the provided set of
7331 /// components is the first associated with a capture.
7332 void generateInfoForComponentList(
7333 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7334 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7335 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
7336 MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct,
7337 bool IsFirstComponentList, bool IsImplicit,
7338 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false,
7339 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7340 OverlappedElements = llvm::None) const {
7341 // The following summarizes what has to be generated for each map and the
7342 // types below. The generated information is expressed in this order:
7343 // base pointer, section pointer, size, flags
7344 // (to add to the ones that come from the map type and modifier).
7345 //
7346 // double d;
7347 // int i[100];
7348 // float *p;
7349 //
7350 // struct S1 {
7351 // int i;
7352 // float f[50];
7353 // }
7354 // struct S2 {
7355 // int i;
7356 // float f[50];
7357 // S1 s;
7358 // double *p;
7359 // struct S2 *ps;
7360 // }
7361 // S2 s;
7362 // S2 *ps;
7363 //
7364 // map(d)
7365 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
7366 //
7367 // map(i)
7368 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
7369 //
7370 // map(i[1:23])
7371 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
7372 //
7373 // map(p)
7374 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
7375 //
7376 // map(p[1:24])
7377 // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ
7378 // in unified shared memory mode or for local pointers
7379 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
7380 //
7381 // map(s)
7382 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
7383 //
7384 // map(s.i)
7385 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
7386 //
7387 // map(s.s.f)
7388 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
7389 //
7390 // map(s.p)
7391 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
7392 //
7393 // map(to: s.p[:22])
7394 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7395 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7396 // &(s.p), &(s.p[0]), 22*sizeof(double),
7397 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7398 // (*) alloc space for struct members, only this is a target parameter
7399 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7400 // optimizes this entry out, same in the examples below)
7401 // (***) map the pointee (map: to)
7402 //
7403 // map(s.ps)
7404 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
7405 //
7406 // map(from: s.ps->s.i)
7407 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7408 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7409 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7410 //
7411 // map(to: s.ps->ps)
7412 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7413 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7414 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
7415 //
7416 // map(s.ps->ps->ps)
7417 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7418 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7419 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7420 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
7421 //
7422 // map(to: s.ps->ps->s.f[:22])
7423 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7424 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7425 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7426 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7427 //
7428 // map(ps)
7429 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
7430 //
7431 // map(ps->i)
7432 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
7433 //
7434 // map(ps->s.f)
7435 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
7436 //
7437 // map(from: ps->p)
7438 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
7439 //
7440 // map(to: ps->p[:22])
7441 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7442 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7443 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
7444 //
7445 // map(ps->ps)
7446 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
7447 //
7448 // map(from: ps->ps->s.i)
7449 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7450 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7451 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7452 //
7453 // map(from: ps->ps->ps)
7454 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7455 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7456 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7457 //
7458 // map(ps->ps->ps->ps)
7459 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7460 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7461 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7462 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
7463 //
7464 // map(to: ps->ps->ps->s.f[:22])
7465 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7466 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7467 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7468 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7469 //
7470 // map(to: s.f[:22]) map(from: s.p[:33])
7471 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7472 // sizeof(double*) (**), TARGET_PARAM
7473 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7474 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7475 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7476 // (*) allocate contiguous space needed to fit all mapped members even if
7477 // we allocate space for members not mapped (in this example,
7478 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7479 // them as well because they fall between &s.f[0] and &s.p)
7480 //
7481 // map(from: s.f[:22]) map(to: ps->p[:33])
7482 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7483 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7484 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7485 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7486 // (*) the struct this entry pertains to is the 2nd element in the list of
7487 // arguments, hence MEMBER_OF(2)
7488 //
7489 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7490 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7491 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7492 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7493 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7494 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7495 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7496 // (*) the struct this entry pertains to is the 4th element in the list
7497 // of arguments, hence MEMBER_OF(4)
7498
7499 // Track if the map information being generated is the first for a capture.
7500 bool IsCaptureFirstInfo = IsFirstComponentList;
7501 // When the variable is on a declare target link or in a to clause with
7502 // unified memory, a reference is needed to hold the host/device address
7503 // of the variable.
7504 bool RequiresReference = false;
7505
7506 // Scan the components from the base to the complete expression.
7507 auto CI = Components.rbegin();
7508 auto CE = Components.rend();
7509 auto I = CI;
7510
7511 // Track if the map information being generated is the first for a list of
7512 // components.
7513 bool IsExpressionFirstInfo = true;
7514 bool FirstPointerInComplexData = false;
7515 Address BP = Address::invalid();
7516 const Expr *AssocExpr = I->getAssociatedExpression();
7517 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7518 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
7519 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7520
7521 if (isa<MemberExpr>(AssocExpr)) {
7522 // The base is the 'this' pointer. The content of the pointer is going
7523 // to be the base of the field being mapped.
7524 BP = CGF.LoadCXXThisAddress();
7525 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7526 (OASE &&
7527 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7528 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
7529 } else if (OAShE &&
7530 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) {
7531 BP = Address(
7532 CGF.EmitScalarExpr(OAShE->getBase()),
7533 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType()));
7534 } else {
7535 // The base is the reference to the variable.
7536 // BP = &Var.
7537 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
7538 if (const auto *VD =
7539 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7540 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7541 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7542 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7543 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7544 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7545 RequiresReference = true;
7546 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
7547 }
7548 }
7549 }
7550
7551 // If the variable is a pointer and is being dereferenced (i.e. is not
7552 // the last component), the base has to be the pointer itself, not its
7553 // reference. References are ignored for mapping purposes.
7554 QualType Ty =
7555 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7556 if (Ty->isAnyPointerType() && std::next(I) != CE) {
7557 // No need to generate individual map information for the pointer, it
7558 // can be associated with the combined storage if shared memory mode is
7559 // active or the base declaration is not global variable.
7560 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7561 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
7562 !VD || VD->hasLocalStorage())
7563 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
7564 else
7565 FirstPointerInComplexData = true;
7566 ++I;
7567 }
7568 }
7569
7570 // Track whether a component of the list should be marked as MEMBER_OF some
7571 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7572 // in a component list should be marked as MEMBER_OF, all subsequent entries
7573 // do not belong to the base struct. E.g.
7574 // struct S2 s;
7575 // s.ps->ps->ps->f[:]
7576 // (1) (2) (3) (4)
7577 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7578 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7579 // is the pointee of ps(2) which is not member of struct s, so it should not
7580 // be marked as such (it is still PTR_AND_OBJ).
7581 // The variable is initialized to false so that PTR_AND_OBJ entries which
7582 // are not struct members are not considered (e.g. array of pointers to
7583 // data).
7584 bool ShouldBeMemberOf = false;
7585
7586 // Variable keeping track of whether or not we have encountered a component
7587 // in the component list which is a member expression. Useful when we have a
7588 // pointer or a final array section, in which case it is the previous
7589 // component in the list which tells us whether we have a member expression.
7590 // E.g. X.f[:]
7591 // While processing the final array section "[:]" it is "f" which tells us
7592 // whether we are dealing with a member of a declared struct.
7593 const MemberExpr *EncounteredME = nullptr;
7594
7595 for (; I != CE; ++I) {
7596 // If the current component is member of a struct (parent struct) mark it.
7597 if (!EncounteredME) {
7598 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7599 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7600 // as MEMBER_OF the parent struct.
7601 if (EncounteredME) {
7602 ShouldBeMemberOf = true;
7603 // Do not emit as complex pointer if this is actually not array-like
7604 // expression.
7605 if (FirstPointerInComplexData) {
7606 QualType Ty = std::prev(I)
7607 ->getAssociatedDeclaration()
7608 ->getType()
7609 .getNonReferenceType();
7610 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
7611 FirstPointerInComplexData = false;
7612 }
7613 }
7614 }
7615
7616 auto Next = std::next(I);
7617
7618 // We need to generate the addresses and sizes if this is the last
7619 // component, if the component is a pointer or if it is an array section
7620 // whose length can't be proved to be one. If this is a pointer, it
7621 // becomes the base address for the following components.
7622
7623 // A final array section, is one whose length can't be proved to be one.
7624 bool IsFinalArraySection =
7625 isFinalArraySectionExpression(I->getAssociatedExpression());
7626
7627 // Get information on whether the element is a pointer. Have to do a
7628 // special treatment for array sections given that they are built-in
7629 // types.
7630 const auto *OASE =
7631 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7632 const auto *OAShE =
7633 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
7634 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
7635 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7636 bool IsPointer =
7637 OAShE ||
7638 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7639 .getCanonicalType()
7640 ->isAnyPointerType()) ||
7641 I->getAssociatedExpression()->getType()->isAnyPointerType();
7642 bool IsNonDerefPointer = IsPointer && !UO && !BO;
7643
7644 if (Next == CE || IsNonDerefPointer || IsFinalArraySection) {
7645 // If this is not the last component, we expect the pointer to be
7646 // associated with an array expression or member expression.
7647 assert((Next == CE ||(((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") ? static_cast<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7654, __PRETTY_FUNCTION__))
7648 isa<MemberExpr>(Next->getAssociatedExpression()) ||(((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") ? static_cast<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7654, __PRETTY_FUNCTION__))
7649 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||(((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") ? static_cast<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7654, __PRETTY_FUNCTION__))
7650 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) ||(((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") ? static_cast<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7654, __PRETTY_FUNCTION__))
7651 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) ||(((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") ? static_cast<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7654, __PRETTY_FUNCTION__))
7652 isa<UnaryOperator>(Next->getAssociatedExpression()) ||(((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") ? static_cast<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7654, __PRETTY_FUNCTION__))
7653 isa<BinaryOperator>(Next->getAssociatedExpression())) &&(((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") ? static_cast<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7654, __PRETTY_FUNCTION__))
7654 "Unexpected expression")(((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") ? static_cast<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\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7654, __PRETTY_FUNCTION__))
;
7655
7656 Address LB = Address::invalid();
7657 if (OAShE) {
7658 LB = Address(CGF.EmitScalarExpr(OAShE->getBase()),
7659 CGF.getContext().getTypeAlignInChars(
7660 OAShE->getBase()->getType()));
7661 } else {
7662 LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
7663 .getAddress(CGF);
7664 }
7665
7666 // If this component is a pointer inside the base struct then we don't
7667 // need to create any entry for it - it will be combined with the object
7668 // it is pointing to into a single PTR_AND_OBJ entry.
7669 bool IsMemberPointerOrAddr =
7670 (IsPointer || ForDeviceAddr) && EncounteredME &&
7671 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7672 EncounteredME);
7673 if (!OverlappedElements.empty()) {
7674 // Handle base element with the info for overlapped elements.
7675 assert(!PartialStruct.Base.isValid() && "The base element is set.")((!PartialStruct.Base.isValid() && "The base element is set."
) ? static_cast<void> (0) : __assert_fail ("!PartialStruct.Base.isValid() && \"The base element is set.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7675, __PRETTY_FUNCTION__))
;
7676 assert(Next == CE &&((Next == CE && "Expected last element for the overlapped elements."
) ? static_cast<void> (0) : __assert_fail ("Next == CE && \"Expected last element for the overlapped elements.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7677, __PRETTY_FUNCTION__))
7677 "Expected last element for the overlapped elements.")((Next == CE && "Expected last element for the overlapped elements."
) ? static_cast<void> (0) : __assert_fail ("Next == CE && \"Expected last element for the overlapped elements.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7677, __PRETTY_FUNCTION__))
;
7678 assert(!IsPointer &&((!IsPointer && "Unexpected base element with the pointer type."
) ? static_cast<void> (0) : __assert_fail ("!IsPointer && \"Unexpected base element with the pointer type.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7679, __PRETTY_FUNCTION__))
7679 "Unexpected base element with the pointer type.")((!IsPointer && "Unexpected base element with the pointer type."
) ? static_cast<void> (0) : __assert_fail ("!IsPointer && \"Unexpected base element with the pointer type.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7679, __PRETTY_FUNCTION__))
;
7680 // Mark the whole struct as the struct that requires allocation on the
7681 // device.
7682 PartialStruct.LowestElem = {0, LB};
7683 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7684 I->getAssociatedExpression()->getType());
7685 Address HB = CGF.Builder.CreateConstGEP(
7686 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7687 CGF.VoidPtrTy),
7688 TypeSize.getQuantity() - 1);
7689 PartialStruct.HighestElem = {
7690 std::numeric_limits<decltype(
7691 PartialStruct.HighestElem.first)>::max(),
7692 HB};
7693 PartialStruct.Base = BP;
7694 // Emit data for non-overlapped data.
7695 OpenMPOffloadMappingFlags Flags =
7696 OMP_MAP_MEMBER_OF |
7697 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
7698 /*AddPtrFlag=*/false,
7699 /*AddIsTargetParamFlag=*/false);
7700 LB = BP;
7701 llvm::Value *Size = nullptr;
7702 // Do bitcopy of all non-overlapped structure elements.
7703 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7704 Component : OverlappedElements) {
7705 Address ComponentLB = Address::invalid();
7706 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7707 Component) {
7708 if (MC.getAssociatedDeclaration()) {
7709 ComponentLB =
7710 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7711 .getAddress(CGF);
7712 Size = CGF.Builder.CreatePtrDiff(
7713 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7714 CGF.EmitCastToVoidPtr(LB.getPointer()));
7715 break;
7716 }
7717 }
7718 assert(Size && "Failed to determine structure size")((Size && "Failed to determine structure size") ? static_cast
<void> (0) : __assert_fail ("Size && \"Failed to determine structure size\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7718, __PRETTY_FUNCTION__))
;
7719 CombinedInfo.BasePointers.push_back(BP.getPointer());
7720 CombinedInfo.Pointers.push_back(LB.getPointer());
7721 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
7722 Size, CGF.Int64Ty, /*isSigned=*/true));
7723 CombinedInfo.Types.push_back(Flags);
7724 CombinedInfo.Mappers.push_back(nullptr);
7725 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
7726 }
7727 CombinedInfo.BasePointers.push_back(BP.getPointer());
7728 CombinedInfo.Pointers.push_back(LB.getPointer());
7729 Size = CGF.Builder.CreatePtrDiff(
7730 CGF.EmitCastToVoidPtr(
7731 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
7732 CGF.EmitCastToVoidPtr(LB.getPointer()));
7733 CombinedInfo.Sizes.push_back(
7734 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
7735 CombinedInfo.Types.push_back(Flags);
7736 CombinedInfo.Mappers.push_back(nullptr);
7737 break;
7738 }
7739 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
7740 if (!IsMemberPointerOrAddr) {
7741 CombinedInfo.BasePointers.push_back(BP.getPointer());
7742 CombinedInfo.Pointers.push_back(LB.getPointer());
7743 CombinedInfo.Sizes.push_back(
7744 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
7745
7746 // If Mapper is valid, the last component inherits the mapper.
7747 bool HasMapper = Mapper && Next == CE;
7748 CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr);
7749
7750 // We need to add a pointer flag for each map that comes from the
7751 // same expression except for the first one. We also need to signal
7752 // this map is the first one that relates with the current capture
7753 // (there is a set of entries for each capture).
7754 OpenMPOffloadMappingFlags Flags =
7755 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
7756 !IsExpressionFirstInfo || RequiresReference ||
7757 FirstPointerInComplexData,
7758 IsCaptureFirstInfo && !RequiresReference);
7759
7760 if (!IsExpressionFirstInfo) {
7761 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
7762 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
7763 if (IsPointer)
7764 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
7765 OMP_MAP_DELETE | OMP_MAP_CLOSE);
7766
7767 if (ShouldBeMemberOf) {
7768 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7769 // should be later updated with the correct value of MEMBER_OF.
7770 Flags |= OMP_MAP_MEMBER_OF;
7771 // From now on, all subsequent PTR_AND_OBJ entries should not be
7772 // marked as MEMBER_OF.
7773 ShouldBeMemberOf = false;
7774 }
7775 }
7776
7777 CombinedInfo.Types.push_back(Flags);
7778 }
7779
7780 // If we have encountered a member expression so far, keep track of the
7781 // mapped member. If the parent is "*this", then the value declaration
7782 // is nullptr.
7783 if (EncounteredME) {
7784 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl());
7785 unsigned FieldIndex = FD->getFieldIndex();
7786
7787 // Update info about the lowest and highest elements for this struct
7788 if (!PartialStruct.Base.isValid()) {
7789 PartialStruct.LowestElem = {FieldIndex, LB};
7790 if (IsFinalArraySection) {
7791 Address HB =
7792 CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false)
7793 .getAddress(CGF);
7794 PartialStruct.HighestElem = {FieldIndex, HB};
7795 } else {
7796 PartialStruct.HighestElem = {FieldIndex, LB};
7797 }
7798 PartialStruct.Base = BP;
7799 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7800 PartialStruct.LowestElem = {FieldIndex, LB};
7801 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7802 PartialStruct.HighestElem = {FieldIndex, LB};
7803 }
7804 }
7805
7806 // If we have a final array section, we are done with this expression.
7807 if (IsFinalArraySection)
7808 break;
7809
7810 // The pointer becomes the base for the next element.
7811 if (Next != CE)
7812 BP = LB;
7813
7814 IsExpressionFirstInfo = false;
7815 IsCaptureFirstInfo = false;
7816 FirstPointerInComplexData = false;
7817 }
7818 }
7819 }
7820
7821 /// Return the adjusted map modifiers if the declaration a capture refers to
7822 /// appears in a first-private clause. This is expected to be used only with
7823 /// directives that start with 'target'.
7824 MappableExprsHandler::OpenMPOffloadMappingFlags
7825 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7826 assert(Cap.capturesVariable() && "Expected capture by reference only!")((Cap.capturesVariable() && "Expected capture by reference only!"
) ? static_cast<void> (0) : __assert_fail ("Cap.capturesVariable() && \"Expected capture by reference only!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7826, __PRETTY_FUNCTION__))
;
7827
7828 // A first private variable captured by reference will use only the
7829 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7830 // declaration is known as first-private in this handler.
7831 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7832 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7833 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7834 return MappableExprsHandler::OMP_MAP_ALWAYS |
7835 MappableExprsHandler::OMP_MAP_TO;
7836 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7837 return MappableExprsHandler::OMP_MAP_TO |
7838 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
7839 return MappableExprsHandler::OMP_MAP_PRIVATE |
7840 MappableExprsHandler::OMP_MAP_TO;
7841 }
7842 return MappableExprsHandler::OMP_MAP_TO |
7843 MappableExprsHandler::OMP_MAP_FROM;
7844 }
7845
7846 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
7847 // Rotate by getFlagMemberOffset() bits.
7848 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
7849 << getFlagMemberOffset());
7850 }
7851
7852 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7853 OpenMPOffloadMappingFlags MemberOfFlag) {
7854 // If the entry is PTR_AND_OBJ but has not been marked with the special
7855 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7856 // marked as MEMBER_OF.
7857 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7858 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7859 return;
7860
7861 // Reset the placeholder value to prepare the flag for the assignment of the
7862 // proper MEMBER_OF value.
7863 Flags &= ~OMP_MAP_MEMBER_OF;
7864 Flags |= MemberOfFlag;
7865 }
7866
7867 void getPlainLayout(const CXXRecordDecl *RD,
7868 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7869 bool AsBase) const {
7870 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7871
7872 llvm::StructType *St =
7873 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7874
7875 unsigned NumElements = St->getNumElements();
7876 llvm::SmallVector<
7877 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7878 RecordLayout(NumElements);
7879
7880 // Fill bases.
7881 for (const auto &I : RD->bases()) {
7882 if (I.isVirtual())
7883 continue;
7884 const auto *Base = I.getType()->getAsCXXRecordDecl();
7885 // Ignore empty bases.
7886 if (Base->isEmpty() || CGF.getContext()
7887 .getASTRecordLayout(Base)
7888 .getNonVirtualSize()
7889 .isZero())
7890 continue;
7891
7892 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7893 RecordLayout[FieldIndex] = Base;
7894 }
7895 // Fill in virtual bases.
7896 for (const auto &I : RD->vbases()) {
7897 const auto *Base = I.getType()->getAsCXXRecordDecl();
7898 // Ignore empty bases.
7899 if (Base->isEmpty())
7900 continue;
7901 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7902 if (RecordLayout[FieldIndex])
7903 continue;
7904 RecordLayout[FieldIndex] = Base;
7905 }
7906 // Fill in all the fields.
7907 assert(!RD->isUnion() && "Unexpected union.")((!RD->isUnion() && "Unexpected union.") ? static_cast
<void> (0) : __assert_fail ("!RD->isUnion() && \"Unexpected union.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7907, __PRETTY_FUNCTION__))
;
7908 for (const auto *Field : RD->fields()) {
7909 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7910 // will fill in later.)
7911 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
7912 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7913 RecordLayout[FieldIndex] = Field;
7914 }
7915 }
7916 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7917 &Data : RecordLayout) {
7918 if (Data.isNull())
7919 continue;
7920 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7921 getPlainLayout(Base, Layout, /*AsBase=*/true);
7922 else
7923 Layout.push_back(Data.get<const FieldDecl *>());
7924 }
7925 }
7926
7927public:
7928 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
7929 : CurDir(&Dir), CGF(CGF) {
7930 // Extract firstprivate clause information.
7931 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7932 for (const auto *D : C->varlists())
7933 FirstPrivateDecls.try_emplace(
7934 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
7935 // Extract implicit firstprivates from uses_allocators clauses.
7936 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
7937 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
7938 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
7939 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
7940 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
7941 /*Implicit=*/true);
7942 else if (const auto *VD = dyn_cast<VarDecl>(
7943 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
7944 ->getDecl()))
7945 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true);
7946 }
7947 }
7948 // Extract device pointer clause information.
7949 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7950 for (auto L : C->component_lists())
7951 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
7952 }
7953
7954 /// Constructor for the declare mapper directive.
7955 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
7956 : CurDir(&Dir), CGF(CGF) {}
7957
7958 /// Generate code for the combined entry if we have a partially mapped struct
7959 /// and take care of the mapping flags of the arguments corresponding to
7960 /// individual struct members.
7961 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
7962 MapFlagsArrayTy &CurTypes,
7963 const StructRangeInfoTy &PartialStruct,
7964 bool NotTargetParams = false) const {
7965 // Base is the base of the struct
7966 CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer());
7967 // Pointer is the address of the lowest element
7968 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7969 CombinedInfo.Pointers.push_back(LB);
7970 // There should not be a mapper for a combined entry.
7971 CombinedInfo.Mappers.push_back(nullptr);
7972 // Size is (addr of {highest+1} element) - (addr of lowest element)
7973 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7974 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7975 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7976 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7977 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
7978 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
7979 /*isSigned=*/false);
7980 CombinedInfo.Sizes.push_back(Size);
7981 // Map type is always TARGET_PARAM, if generate info for captures.
7982 CombinedInfo.Types.push_back(NotTargetParams ? OMP_MAP_NONE
7983 : OMP_MAP_TARGET_PARAM);
7984 // If any element has the present modifier, then make sure the runtime
7985 // doesn't attempt to allocate the struct.
7986 if (CurTypes.end() !=
7987 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) {
7988 return Type & OMP_MAP_PRESENT;
7989 }))
7990 CombinedInfo.Types.back() |= OMP_MAP_PRESENT;
7991 // Remove TARGET_PARAM flag from the first element
7992 CurTypes.front() &= ~OMP_MAP_TARGET_PARAM;
7993
7994 // All other current entries will be MEMBER_OF the combined entry
7995 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7996 // 0xFFFF in the MEMBER_OF field).
7997 OpenMPOffloadMappingFlags MemberOfFlag =
7998 getMemberOfFlag(CombinedInfo.BasePointers.size() - 1);
7999 for (auto &M : CurTypes)
8000 setCorrectMemberOfFlag(M, MemberOfFlag);
8001 }
8002
8003 /// Generate all the base pointers, section pointers, sizes, map types, and
8004 /// mappers for the extracted mappable expressions (all included in \a
8005 /// CombinedInfo). Also, for each item that relates with a device pointer, a
8006 /// pair of the relevant declaration and index where it occurs is appended to
8007 /// the device pointers info array.
8008 void generateAllInfo(
8009 MapCombinedInfoTy &CombinedInfo, bool NotTargetParams = false,
8010 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8011 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const {
8012 // We have to process the component lists that relate with the same
8013 // declaration in a single chunk so that we can generate the map flags
8014 // correctly. Therefore, we organize all lists in a map.
8015 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8016
8017 // Helper function to fill the information map for the different supported
8018 // clauses.
8019 auto &&InfoGen =
8020 [&Info, &SkipVarSet](
8021 const ValueDecl *D,
8022 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8023 OpenMPMapClauseKind MapType,
8024 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8025 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8026 bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper,
8027 bool ForDeviceAddr = false) {
8028 const ValueDecl *VD =
8029 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8030 if (SkipVarSet.count(VD))
8031 return;
8032 Info[VD].emplace_back(L, MapType, MapModifiers, MotionModifiers,
8033 ReturnDevicePointer, IsImplicit, Mapper,
8034 ForDeviceAddr);
8035 };
8036
8037 assert(CurDir.is<const OMPExecutableDirective *>() &&((CurDir.is<const OMPExecutableDirective *>() &&
"Expect a executable directive") ? static_cast<void> (
0) : __assert_fail ("CurDir.is<const OMPExecutableDirective *>() && \"Expect a executable directive\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8038, __PRETTY_FUNCTION__))
8038 "Expect a executable directive")((CurDir.is<const OMPExecutableDirective *>() &&
"Expect a executable directive") ? static_cast<void> (
0) : __assert_fail ("CurDir.is<const OMPExecutableDirective *>() && \"Expect a executable directive\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8038, __PRETTY_FUNCTION__))
;
8039 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8040 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
8041 for (const auto L : C->component_lists()) {
8042 InfoGen(std::get<0>(L), std::get<1>(L), C->getMapType(),
8043 C->getMapTypeModifiers(), llvm::None,
8044 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L));
8045 }
8046 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
8047 for (const auto L : C->component_lists()) {
8048 InfoGen(std::get<0>(L), std::get<1>(L), OMPC_MAP_to, llvm::None,
8049 C->getMotionModifiers(), /*ReturnDevicePointer=*/false,
8050 C->isImplicit(), std::get<2>(L));
8051 }
8052 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
8053 for (const auto L : C->component_lists()) {
8054 InfoGen(std::get<0>(L), std::get<1>(L), OMPC_MAP_from, llvm::None,
8055 C->getMotionModifiers(), /*ReturnDevicePointer=*/false,
8056 C->isImplicit(), std::get<2>(L));
8057 }
8058
8059 // Look at the use_device_ptr clause information and mark the existing map
8060 // entries as such. If there is no map information for an entry in the
8061 // use_device_ptr list, we create one with map type 'alloc' and zero size
8062 // section. It is the user fault if that was not mapped before. If there is
8063 // no map information and the pointer is a struct member, then we defer the
8064 // emission of that entry until the whole struct has been processed.
8065 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
8066 DeferredInfo;
8067 MapCombinedInfoTy UseDevicePtrCombinedInfo;
8068
8069 for (const auto *C :
8070 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
8071 for (const auto L : C->component_lists()) {
8072 OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
8073 std::get<1>(L);
8074 assert(!Components.empty() &&((!Components.empty() && "Not expecting empty list of components!"
) ? static_cast<void> (0) : __assert_fail ("!Components.empty() && \"Not expecting empty list of components!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8075, __PRETTY_FUNCTION__))
8075 "Not expecting empty list of components!")((!Components.empty() && "Not expecting empty list of components!"
) ? static_cast<void> (0) : __assert_fail ("!Components.empty() && \"Not expecting empty list of components!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8075, __PRETTY_FUNCTION__))
;
8076 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
8077 VD = cast<ValueDecl>(VD->getCanonicalDecl());
8078 const Expr *IE = Components.back().getAssociatedExpression();
8079 // If the first component is a member expression, we have to look into
8080 // 'this', which maps to null in the map of map information. Otherwise
8081 // look directly for the information.
8082 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8083
8084 // We potentially have map information for this declaration already.
8085 // Look for the first set of components that refer to it.
8086 if (It != Info.end()) {
8087 auto *CI = llvm::find_if(It->second, [VD](const MapInfo &MI) {
8088 return MI.Components.back().getAssociatedDeclaration() == VD;
8089 });
8090 // If we found a map entry, signal that the pointer has to be returned
8091 // and move on to the next declaration.
8092 // Exclude cases where the base pointer is mapped as array subscript,
8093 // array section or array shaping. The base address is passed as a
8094 // pointer to base in this case and cannot be used as a base for
8095 // use_device_ptr list item.
8096 if (CI != It->second.end()) {
8097 auto PrevCI = std::next(CI->Components.rbegin());
8098 const auto *VarD = dyn_cast<VarDecl>(VD);
8099 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8100 isa<MemberExpr>(IE) ||
8101 !VD->getType().getNonReferenceType()->isPointerType() ||
8102 PrevCI == CI->Components.rend() ||
8103 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
8104 VarD->hasLocalStorage()) {
8105 CI->ReturnDevicePointer = true;
8106 continue;
8107 }
8108 }
8109 }
8110
8111 // We didn't find any match in our map information - generate a zero
8112 // size array section - if the pointer is a struct member we defer this
8113 // action until the whole struct has been processed.
8114 if (isa<MemberExpr>(IE)) {
8115 // Insert the pointer into Info to be processed by
8116 // generateInfoForComponentList. Because it is a member pointer
8117 // without a pointee, no entry will be generated for it, therefore
8118 // we need to generate one after the whole struct has been processed.
8119 // Nonetheless, generateInfoForComponentList must be called to take
8120 // the pointer into account for the calculation of the range of the
8121 // partial struct.
8122 InfoGen(nullptr, Components, OMPC_MAP_unknown, llvm::None, llvm::None,
8123 /*ReturnDevicePointer=*/false, C->isImplicit(), nullptr);
8124 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false);
8125 } else {
8126 llvm::Value *Ptr =
8127 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
8128 UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD);
8129 UseDevicePtrCombinedInfo.Pointers.push_back(Ptr);
8130 UseDevicePtrCombinedInfo.Sizes.push_back(
8131 llvm::Constant::getNullValue(CGF.Int64Ty));
8132 UseDevicePtrCombinedInfo.Types.push_back(
8133 OMP_MAP_RETURN_PARAM |
8134 (NotTargetParams ? OMP_MAP_NONE : OMP_MAP_TARGET_PARAM));
8135 UseDevicePtrCombinedInfo.Mappers.push_back(nullptr);
8136 }
8137 }
8138 }
8139
8140 // Look at the use_device_addr clause information and mark the existing map
8141 // entries as such. If there is no map information for an entry in the
8142 // use_device_addr list, we create one with map type 'alloc' and zero size
8143 // section. It is the user fault if that was not mapped before. If there is
8144 // no map information and the pointer is a struct member, then we defer the
8145 // emission of that entry until the whole struct has been processed.
8146 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8147 for (const auto *C :
8148 CurExecDir->getClausesOfKind<OMPUseDeviceAddrClause>()) {
8149 for (const auto L : C->component_lists()) {
8150 assert(!std::get<1>(L).empty() &&((!std::get<1>(L).empty() && "Not expecting empty list of components!"
) ? static_cast<void> (0) : __assert_fail ("!std::get<1>(L).empty() && \"Not expecting empty list of components!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8151, __PRETTY_FUNCTION__))
8151 "Not expecting empty list of components!")((!std::get<1>(L).empty() && "Not expecting empty list of components!"
) ? static_cast<void> (0) : __assert_fail ("!std::get<1>(L).empty() && \"Not expecting empty list of components!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8151, __PRETTY_FUNCTION__))
;
8152 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
8153 if (!Processed.insert(VD).second)
8154 continue;
8155 VD = cast<ValueDecl>(VD->getCanonicalDecl());
8156 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
8157 // If the first component is a member expression, we have to look into
8158 // 'this', which maps to null in the map of map information. Otherwise
8159 // look directly for the information.
8160 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8161
8162 // We potentially have map information for this declaration already.
8163 // Look for the first set of components that refer to it.
8164 if (It != Info.end()) {
8165 auto *CI = llvm::find_if(It->second, [VD](const MapInfo &MI) {
8166 return MI.Components.back().getAssociatedDeclaration() == VD;
8167 });
8168 // If we found a map entry, signal that the pointer has to be returned
8169 // and move on to the next declaration.
8170 if (CI != It->second.end()) {
8171 CI->ReturnDevicePointer = true;
8172 continue;
8173 }
8174 }
8175
8176 // We didn't find any match in our map information - generate a zero
8177 // size array section - if the pointer is a struct member we defer this
8178 // action until the whole struct has been processed.
8179 if (isa<MemberExpr>(IE)) {
8180 // Insert the pointer into Info to be processed by
8181 // generateInfoForComponentList. Because it is a member pointer
8182 // without a pointee, no entry will be generated for it, therefore
8183 // we need to generate one after the whole struct has been processed.
8184 // Nonetheless, generateInfoForComponentList must be called to take
8185 // the pointer into account for the calculation of the range of the
8186 // partial struct.
8187 InfoGen(nullptr, std::get<1>(L), OMPC_MAP_unknown, llvm::None,
8188 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(),
8189 nullptr, /*ForDeviceAddr=*/true);
8190 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true);
8191 } else {
8192 llvm::Value *Ptr;
8193 if (IE->isGLValue())
8194 Ptr = CGF.EmitLValue(IE).getPointer(CGF);
8195 else
8196 Ptr = CGF.EmitScalarExpr(IE);
8197 CombinedInfo.BasePointers.emplace_back(Ptr, VD);
8198 CombinedInfo.Pointers.push_back(Ptr);
8199 CombinedInfo.Sizes.push_back(
8200 llvm::Constant::getNullValue(CGF.Int64Ty));
8201 CombinedInfo.Types.push_back(
8202 OMP_MAP_RETURN_PARAM |
8203 (NotTargetParams ? OMP_MAP_NONE : OMP_MAP_TARGET_PARAM));
8204 CombinedInfo.Mappers.push_back(nullptr);
8205 }
8206 }
8207 }
8208
8209 for (const auto &M : Info) {
8210 // We need to know when we generate information for the first component
8211 // associated with a capture, because the mapping flags depend on it.
8212 bool IsFirstComponentList = !NotTargetParams;
8213
8214 // Temporary generated information.
8215 MapCombinedInfoTy CurInfo;
8216 StructRangeInfoTy PartialStruct;
8217
8218 for (const MapInfo &L : M.second) {
8219 assert(!L.Components.empty() &&((!L.Components.empty() && "Not expecting declaration with no component lists."
) ? static_cast<void> (0) : __assert_fail ("!L.Components.empty() && \"Not expecting declaration with no component lists.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8220, __PRETTY_FUNCTION__))
8220 "Not expecting declaration with no component lists.")((!L.Components.empty() && "Not expecting declaration with no component lists."
) ? static_cast<void> (0) : __assert_fail ("!L.Components.empty() && \"Not expecting declaration with no component lists.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8220, __PRETTY_FUNCTION__))
;
8221
8222 // Remember the current base pointer index.
8223 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
8224 generateInfoForComponentList(L.MapType, L.MapModifiers,
8225 L.MotionModifiers, L.Components, CurInfo,
8226 PartialStruct, IsFirstComponentList,
8227 L.IsImplicit, L.Mapper, L.ForDeviceAddr);
8228
8229 // If this entry relates with a device pointer, set the relevant
8230 // declaration and add the 'return pointer' flag.
8231 if (L.ReturnDevicePointer) {
8232 assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx &&((CurInfo.BasePointers.size() > CurrentBasePointersIdx &&
"Unexpected number of mapped base pointers.") ? static_cast<
void> (0) : __assert_fail ("CurInfo.BasePointers.size() > CurrentBasePointersIdx && \"Unexpected number of mapped base pointers.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8233, __PRETTY_FUNCTION__))
8233 "Unexpected number of mapped base pointers.")((CurInfo.BasePointers.size() > CurrentBasePointersIdx &&
"Unexpected number of mapped base pointers.") ? static_cast<
void> (0) : __assert_fail ("CurInfo.BasePointers.size() > CurrentBasePointersIdx && \"Unexpected number of mapped base pointers.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8233, __PRETTY_FUNCTION__))
;
8234
8235 const ValueDecl *RelevantVD =
8236 L.Components.back().getAssociatedDeclaration();
8237 assert(RelevantVD &&((RelevantVD && "No relevant declaration related with device pointer??"
) ? static_cast<void> (0) : __assert_fail ("RelevantVD && \"No relevant declaration related with device pointer??\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8238, __PRETTY_FUNCTION__))
8238 "No relevant declaration related with device pointer??")((RelevantVD && "No relevant declaration related with device pointer??"
) ? static_cast<void> (0) : __assert_fail ("RelevantVD && \"No relevant declaration related with device pointer??\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8238, __PRETTY_FUNCTION__))
;
8239
8240 CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl(
8241 RelevantVD);
8242 CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
8243 }
8244 IsFirstComponentList = false;
8245 }
8246
8247 // Append any pending zero-length pointers which are struct members and
8248 // used with use_device_ptr or use_device_addr.
8249 auto CI = DeferredInfo.find(M.first);
8250 if (CI != DeferredInfo.end()) {
8251 for (const DeferredDevicePtrEntryTy &L : CI->second) {
8252 llvm::Value *BasePtr;
8253 llvm::Value *Ptr;
8254 if (L.ForDeviceAddr) {
8255 if (L.IE->isGLValue())
8256 Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
8257 else
8258 Ptr = this->CGF.EmitScalarExpr(L.IE);
8259 BasePtr = Ptr;
8260 // Entry is RETURN_PARAM. Also, set the placeholder value
8261 // MEMBER_OF=FFFF so that the entry is later updated with the
8262 // correct value of MEMBER_OF.
8263 CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF);
8264 } else {
8265 BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
8266 Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE),
8267 L.IE->getExprLoc());
8268 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8269 // value MEMBER_OF=FFFF so that the entry is later updated with the
8270 // correct value of MEMBER_OF.
8271 CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8272 OMP_MAP_MEMBER_OF);
8273 }
8274 CurInfo.BasePointers.emplace_back(BasePtr, L.VD);
8275 CurInfo.Pointers.push_back(Ptr);
8276 CurInfo.Sizes.push_back(
8277 llvm::Constant::getNullValue(this->CGF.Int64Ty));
8278 CurInfo.Mappers.push_back(nullptr);
8279 }
8280 }
8281
8282 // If there is an entry in PartialStruct it means we have a struct with
8283 // individual members mapped. Emit an extra combined entry.
8284 if (PartialStruct.Base.isValid())
8285 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
8286 NotTargetParams);
8287
8288 // We need to append the results of this capture to what we already have.
8289 CombinedInfo.append(CurInfo);
8290 }
8291 // Append data for use_device_ptr clauses.
8292 CombinedInfo.append(UseDevicePtrCombinedInfo);
8293 }
8294
8295 /// Generate all the base pointers, section pointers, sizes, map types, and
8296 /// mappers for the extracted map clauses of user-defined mapper (all included
8297 /// in \a CombinedInfo).
8298 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const {
8299 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&((CurDir.is<const OMPDeclareMapperDecl *>() && "Expect a declare mapper directive"
) ? static_cast<void> (0) : __assert_fail ("CurDir.is<const OMPDeclareMapperDecl *>() && \"Expect a declare mapper directive\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8300, __PRETTY_FUNCTION__))
8300 "Expect a declare mapper directive")((CurDir.is<const OMPDeclareMapperDecl *>() && "Expect a declare mapper directive"
) ? static_cast<void> (0) : __assert_fail ("CurDir.is<const OMPDeclareMapperDecl *>() && \"Expect a declare mapper directive\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8300, __PRETTY_FUNCTION__))
;
8301 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8302 // We have to process the component lists that relate with the same
8303 // declaration in a single chunk so that we can generate the map flags
8304 // correctly. Therefore, we organize all lists in a map.
8305 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8306
8307 // Fill the information map for map clauses.
8308 for (const auto *C : CurMapperDir->clauselists()) {
8309 const auto *MC = cast<OMPMapClause>(C);
8310 for (const auto L : MC->component_lists()) {
8311 const ValueDecl *VD =
8312 std::get<0>(L) ? cast<ValueDecl>(std::get<0>(L)->getCanonicalDecl())
8313 : nullptr;
8314 // Get the corresponding user-defined mapper.
8315 Info[VD].emplace_back(std::get<1>(L), MC->getMapType(),
8316 MC->getMapTypeModifiers(), llvm::None,
8317 /*ReturnDevicePointer=*/false, MC->isImplicit(),
8318 std::get<2>(L));
8319 }
8320 }
8321
8322 for (const auto &M : Info) {
8323 // We need to know when we generate information for the first component
8324 // associated with a capture, because the mapping flags depend on it.
8325 bool IsFirstComponentList = true;
8326
8327 // Temporary generated information.
8328 MapCombinedInfoTy CurInfo;
8329 StructRangeInfoTy PartialStruct;
8330
8331 for (const MapInfo &L : M.second) {
8332 assert(!L.Components.empty() &&((!L.Components.empty() && "Not expecting declaration with no component lists."
) ? static_cast<void> (0) : __assert_fail ("!L.Components.empty() && \"Not expecting declaration with no component lists.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8333, __PRETTY_FUNCTION__))
8333 "Not expecting declaration with no component lists.")((!L.Components.empty() && "Not expecting declaration with no component lists."
) ? static_cast<void> (0) : __assert_fail ("!L.Components.empty() && \"Not expecting declaration with no component lists.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8333, __PRETTY_FUNCTION__))
;
8334 generateInfoForComponentList(L.MapType, L.MapModifiers,
8335 L.MotionModifiers, L.Components, CurInfo,
8336 PartialStruct, IsFirstComponentList,
8337 L.IsImplicit, L.Mapper, L.ForDeviceAddr);
8338 IsFirstComponentList = false;
8339 }
8340
8341 // If there is an entry in PartialStruct it means we have a struct with
8342 // individual members mapped. Emit an extra combined entry.
8343 if (PartialStruct.Base.isValid())
8344 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct);
8345
8346 // We need to append the results of this capture to what we already have.
8347 CombinedInfo.append(CurInfo);
8348 }
8349 }
8350
8351 /// Emit capture info for lambdas for variables captured by reference.
8352 void generateInfoForLambdaCaptures(
8353 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8354 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
8355 const auto *RD = VD->getType()
8356 .getCanonicalType()
8357 .getNonReferenceType()
8358 ->getAsCXXRecordDecl();
8359 if (!RD || !RD->isLambda())
8360 return;
8361 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8362 LValue VDLVal = CGF.MakeAddrLValue(
8363 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8364 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8365 FieldDecl *ThisCapture = nullptr;
8366 RD->getCaptureFields(Captures, ThisCapture);
8367 if (ThisCapture) {
8368 LValue ThisLVal =
8369 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
8370 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
8371 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
8372 VDLVal.getPointer(CGF));
8373 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
8374 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
8375 CombinedInfo.Sizes.push_back(
8376 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8377 CGF.Int64Ty, /*isSigned=*/true));
8378 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
8379 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8380 CombinedInfo.Mappers.push_back(nullptr);
8381 }
8382 for (const LambdaCapture &LC : RD->captures()) {
8383 if (!LC.capturesVariable())
8384 continue;
8385 const VarDecl *VD = LC.getCapturedVar();
8386 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8387 continue;
8388 auto It = Captures.find(VD);
8389 assert(It != Captures.end() && "Found lambda capture without field.")((It != Captures.end() && "Found lambda capture without field."
) ? static_cast<void> (0) : __assert_fail ("It != Captures.end() && \"Found lambda capture without field.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8389, __PRETTY_FUNCTION__))
;
8390 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
8391 if (LC.getCaptureKind() == LCK_ByRef) {
8392 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8393 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8394 VDLVal.getPointer(CGF));
8395 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
8396 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
8397 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
8398 CGF.getTypeSize(
8399 VD->getType().getCanonicalType().getNonReferenceType()),
8400 CGF.Int64Ty, /*isSigned=*/true));
8401 } else {
8402 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
8403 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8404 VDLVal.getPointer(CGF));
8405 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
8406 CombinedInfo.Pointers.push_back(VarRVal.getScalarVal());
8407 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8408 }
8409 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
8410 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8411 CombinedInfo.Mappers.push_back(nullptr);
8412 }
8413 }
8414
8415 /// Set correct indices for lambdas captures.
8416 void adjustMemberOfForLambdaCaptures(
8417 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8418 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8419 MapFlagsArrayTy &Types) const {
8420 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8421 // Set correct member_of idx for all implicit lambda captures.
8422 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
8423 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8424 continue;
8425 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8426 assert(BasePtr && "Unable to find base lambda address.")((BasePtr && "Unable to find base lambda address.") ?
static_cast<void> (0) : __assert_fail ("BasePtr && \"Unable to find base lambda address.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8426, __PRETTY_FUNCTION__))
;
8427 int TgtIdx = -1;
8428 for (unsigned J = I; J > 0; --J) {
8429 unsigned Idx = J - 1;
8430 if (Pointers[Idx] != BasePtr)
8431 continue;
8432 TgtIdx = Idx;
8433 break;
8434 }
8435 assert(TgtIdx != -1 && "Unable to find parent lambda.")((TgtIdx != -1 && "Unable to find parent lambda.") ? static_cast
<void> (0) : __assert_fail ("TgtIdx != -1 && \"Unable to find parent lambda.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8435, __PRETTY_FUNCTION__))
;
8436 // All other current entries will be MEMBER_OF the combined entry
8437 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8438 // 0xFFFF in the MEMBER_OF field).
8439 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8440 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8441 }
8442 }
8443
8444 /// Generate the base pointers, section pointers, sizes, map types, and
8445 /// mappers associated to a given capture (all included in \a CombinedInfo).
8446 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
8447 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8448 StructRangeInfoTy &PartialStruct) const {
8449 assert(!Cap->capturesVariableArrayType() &&((!Cap->capturesVariableArrayType() && "Not expecting to generate map info for a variable array type!"
) ? static_cast<void> (0) : __assert_fail ("!Cap->capturesVariableArrayType() && \"Not expecting to generate map info for a variable array type!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8450, __PRETTY_FUNCTION__))
21
'?' condition is true
8450 "Not expecting to generate map info for a variable array type!")((!Cap->capturesVariableArrayType() && "Not expecting to generate map info for a variable array type!"
) ? static_cast<void> (0) : __assert_fail ("!Cap->capturesVariableArrayType() && \"Not expecting to generate map info for a variable array type!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8450, __PRETTY_FUNCTION__))
;
8451
8452 // We need to know when we generating information for the first component
8453 const ValueDecl *VD = Cap->capturesThis()
22
'?' condition is true
23
'VD' initialized to a null pointer value
8454 ? nullptr
8455 : Cap->getCapturedVar()->getCanonicalDecl();
8456
8457 // If this declaration appears in a is_device_ptr clause we just have to
8458 // pass the pointer by value. If it is a reference to a declaration, we just
8459 // pass its value.
8460 if (DevPointersMap.count(VD)) {
24
Assuming the condition is false
25
Taking false branch
8461 CombinedInfo.BasePointers.emplace_back(Arg, VD);
8462 CombinedInfo.Pointers.push_back(Arg);
8463 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
8464 CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty,
8465 /*isSigned=*/true));
8466 CombinedInfo.Types.push_back(
8467 (Cap->capturesVariable() ? OMP_MAP_TO : OMP_MAP_LITERAL) |
8468 OMP_MAP_TARGET_PARAM);
8469 CombinedInfo.Mappers.push_back(nullptr);
8470 return;
8471 }
8472
8473 using MapData =
8474 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
8475 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool,
8476 const ValueDecl *>;
8477 SmallVector<MapData, 4> DeclComponentLists;
8478 assert(CurDir.is<const OMPExecutableDirective *>() &&((CurDir.is<const OMPExecutableDirective *>() &&
"Expect a executable directive") ? static_cast<void> (
0) : __assert_fail ("CurDir.is<const OMPExecutableDirective *>() && \"Expect a executable directive\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8479, __PRETTY_FUNCTION__))
26
'?' condition is true
8479 "Expect a executable directive")((CurDir.is<const OMPExecutableDirective *>() &&
"Expect a executable directive") ? static_cast<void> (
0) : __assert_fail ("CurDir.is<const OMPExecutableDirective *>() && \"Expect a executable directive\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8479, __PRETTY_FUNCTION__))
;
8480 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8481 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
8482 for (const auto L : C->decl_component_lists(VD)) {
8483 const ValueDecl *VDecl, *Mapper;
8484 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8485 std::tie(VDecl, Components, Mapper) = L;
8486 assert(VDecl == VD && "We got information for the wrong declaration??")((VDecl == VD && "We got information for the wrong declaration??"
) ? static_cast<void> (0) : __assert_fail ("VDecl == VD && \"We got information for the wrong declaration??\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8486, __PRETTY_FUNCTION__))
;
8487 assert(!Components.empty() &&((!Components.empty() && "Not expecting declaration with no component lists."
) ? static_cast<void> (0) : __assert_fail ("!Components.empty() && \"Not expecting declaration with no component lists.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8488, __PRETTY_FUNCTION__))
8488 "Not expecting declaration with no component lists.")((!Components.empty() && "Not expecting declaration with no component lists."
) ? static_cast<void> (0) : __assert_fail ("!Components.empty() && \"Not expecting declaration with no component lists.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8488, __PRETTY_FUNCTION__))
;
8489 DeclComponentLists.emplace_back(Components, C->getMapType(),
8490 C->getMapTypeModifiers(),
8491 C->isImplicit(), Mapper);
8492 }
8493 }
8494
8495 // Find overlapping elements (including the offset from the base element).
8496 llvm::SmallDenseMap<
8497 const MapData *,
8498 llvm::SmallVector<
8499 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8500 4>
8501 OverlappedData;
8502 size_t Count = 0;
8503 for (const MapData &L : DeclComponentLists) {
27
Assuming '__begin2' is equal to '__end2'
8504 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8505 OpenMPMapClauseKind MapType;
8506 ArrayRef<OpenMPMapModifierKind> MapModifiers;
8507 bool IsImplicit;
8508 const ValueDecl *Mapper;
8509 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper) = L;
8510 ++Count;
8511 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8512 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
8513 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper) = L1;
8514 auto CI = Components.rbegin();
8515 auto CE = Components.rend();
8516 auto SI = Components1.rbegin();
8517 auto SE = Components1.rend();
8518 for (; CI != CE && SI != SE; ++CI, ++SI) {
8519 if (CI->getAssociatedExpression()->getStmtClass() !=
8520 SI->getAssociatedExpression()->getStmtClass())
8521 break;
8522 // Are we dealing with different variables/fields?
8523 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8524 break;
8525 }
8526 // Found overlapping if, at least for one component, reached the head of
8527 // the components list.
8528 if (CI == CE || SI == SE) {
8529 assert((CI != CE || SI != SE) &&(((CI != CE || SI != SE) && "Unexpected full match of the mapping components."
) ? static_cast<void> (0) : __assert_fail ("(CI != CE || SI != SE) && \"Unexpected full match of the mapping components.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8530, __PRETTY_FUNCTION__))
8530 "Unexpected full match of the mapping components.")(((CI != CE || SI != SE) && "Unexpected full match of the mapping components."
) ? static_cast<void> (0) : __assert_fail ("(CI != CE || SI != SE) && \"Unexpected full match of the mapping components.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8530, __PRETTY_FUNCTION__))
;
8531 const MapData &BaseData = CI == CE ? L : L1;
8532 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8533 SI == SE ? Components : Components1;
8534 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8535 OverlappedElements.getSecond().push_back(SubData);
8536 }
8537 }
8538 }
8539 // Sort the overlapped elements for each item.
8540 llvm::SmallVector<const FieldDecl *, 4> Layout;
8541 if (!OverlappedData.empty()) {
28
Assuming the condition is true
29
Taking true branch
8542 if (const auto *CRD =
8543 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
30
Called C++ object pointer is null
8544 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8545 else {
8546 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8547 Layout.append(RD->field_begin(), RD->field_end());
8548 }
8549 }
8550 for (auto &Pair : OverlappedData) {
8551 llvm::sort(
8552 Pair.getSecond(),
8553 [&Layout](
8554 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8555 OMPClauseMappableExprCommon::MappableExprComponentListRef
8556 Second) {
8557 auto CI = First.rbegin();
8558 auto CE = First.rend();
8559 auto SI = Second.rbegin();
8560 auto SE = Second.rend();
8561 for (; CI != CE && SI != SE; ++CI, ++SI) {
8562 if (CI->getAssociatedExpression()->getStmtClass() !=
8563 SI->getAssociatedExpression()->getStmtClass())
8564 break;
8565 // Are we dealing with different variables/fields?
8566 if (CI->getAssociatedDeclaration() !=
8567 SI->getAssociatedDeclaration())
8568 break;
8569 }
8570
8571 // Lists contain the same elements.
8572 if (CI == CE && SI == SE)
8573 return false;
8574
8575 // List with less elements is less than list with more elements.
8576 if (CI == CE || SI == SE)
8577 return CI == CE;
8578
8579 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8580 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8581 if (FD1->getParent() == FD2->getParent())
8582 return FD1->getFieldIndex() < FD2->getFieldIndex();
8583 const auto It =
8584 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8585 return FD == FD1 || FD == FD2;
8586 });
8587 return *It == FD1;
8588 });
8589 }
8590
8591 // Associated with a capture, because the mapping flags depend on it.
8592 // Go through all of the elements with the overlapped elements.
8593 for (const auto &Pair : OverlappedData) {
8594 const MapData &L = *Pair.getFirst();
8595 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8596 OpenMPMapClauseKind MapType;
8597 ArrayRef<OpenMPMapModifierKind> MapModifiers;
8598 bool IsImplicit;
8599 const ValueDecl *Mapper;
8600 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper) = L;
8601 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8602 OverlappedComponents = Pair.getSecond();
8603 bool IsFirstComponentList = true;
8604 generateInfoForComponentList(
8605 MapType, MapModifiers, llvm::None, Components, CombinedInfo,
8606 PartialStruct, IsFirstComponentList, IsImplicit, Mapper,
8607 /*ForDeviceAddr=*/false, OverlappedComponents);
8608 }
8609 // Go through other elements without overlapped elements.
8610 bool IsFirstComponentList = OverlappedData.empty();
8611 for (const MapData &L : DeclComponentLists) {
8612 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8613 OpenMPMapClauseKind MapType;
8614 ArrayRef<OpenMPMapModifierKind> MapModifiers;
8615 bool IsImplicit;
8616 const ValueDecl *Mapper;
8617 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper) = L;
8618 auto It = OverlappedData.find(&L);
8619 if (It == OverlappedData.end())
8620 generateInfoForComponentList(MapType, MapModifiers, llvm::None,
8621 Components, CombinedInfo, PartialStruct,
8622 IsFirstComponentList, IsImplicit, Mapper);
8623 IsFirstComponentList = false;
8624 }
8625 }
8626
8627 /// Generate the default map information for a given capture \a CI,
8628 /// record field declaration \a RI and captured value \a CV.
8629 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8630 const FieldDecl &RI, llvm::Value *CV,
8631 MapCombinedInfoTy &CombinedInfo) const {
8632 bool IsImplicit = true;
8633 // Do the default mapping.
8634 if (CI.capturesThis()) {
8635 CombinedInfo.BasePointers.push_back(CV);
8636 CombinedInfo.Pointers.push_back(CV);
8637 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
8638 CombinedInfo.Sizes.push_back(
8639 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8640 CGF.Int64Ty, /*isSigned=*/true));
8641 // Default map type.
8642 CombinedInfo.Types.push_back(OMP_MAP_TO | OMP_MAP_FROM);
8643 } else if (CI.capturesVariableByCopy()) {
8644 CombinedInfo.BasePointers.push_back(CV);
8645 CombinedInfo.Pointers.push_back(CV);
8646 if (!RI.getType()->isAnyPointerType()) {
8647 // We have to signal to the runtime captures passed by value that are
8648 // not pointers.
8649 CombinedInfo.Types.push_back(OMP_MAP_LITERAL);
8650 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
8651 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
8652 } else {
8653 // Pointers are implicitly mapped with a zero size and no flags
8654 // (other than first map that is added for all implicit maps).
8655 CombinedInfo.Types.push_back(OMP_MAP_NONE);
8656 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
8657 }
8658 const VarDecl *VD = CI.getCapturedVar();
8659 auto I = FirstPrivateDecls.find(VD);
8660 if (I != FirstPrivateDecls.end())
8661 IsImplicit = I->getSecond();
8662 } else {
8663 assert(CI.capturesVariable() && "Expected captured reference.")((CI.capturesVariable() && "Expected captured reference."
) ? static_cast<void> (0) : __assert_fail ("CI.capturesVariable() && \"Expected captured reference.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8663, __PRETTY_FUNCTION__))
;
8664 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
8665 QualType ElementType = PtrTy->getPointeeType();
8666 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
8667 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
8668 // The default map type for a scalar/complex type is 'to' because by
8669 // default the value doesn't have to be retrieved. For an aggregate
8670 // type, the default is 'tofrom'.
8671 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
8672 const VarDecl *VD = CI.getCapturedVar();
8673 auto I = FirstPrivateDecls.find(VD);
8674 if (I != FirstPrivateDecls.end() &&
8675 VD->getType().isConstant(CGF.getContext())) {
8676 llvm::Constant *Addr =
8677 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8678 // Copy the value of the original variable to the new global copy.
8679 CGF.Builder.CreateMemCpy(
8680 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF),
8681 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
8682 CombinedInfo.Sizes.back(), /*IsVolatile=*/false);
8683 // Use new global variable as the base pointers.
8684 CombinedInfo.BasePointers.push_back(Addr);
8685 CombinedInfo.Pointers.push_back(Addr);
8686 } else {
8687 CombinedInfo.BasePointers.push_back(CV);
8688 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
8689 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8690 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8691 AlignmentSource::Decl));
8692 CombinedInfo.Pointers.push_back(PtrAddr.getPointer());
8693 } else {
8694 CombinedInfo.Pointers.push_back(CV);
8695 }
8696 }
8697 if (I != FirstPrivateDecls.end())
8698 IsImplicit = I->getSecond();
8699 }
8700 // Every default map produces a single argument which is a target parameter.
8701 CombinedInfo.Types.back() |= OMP_MAP_TARGET_PARAM;
8702
8703 // Add flag stating this is an implicit map.
8704 if (IsImplicit)
8705 CombinedInfo.Types.back() |= OMP_MAP_IMPLICIT;
8706
8707 // No user-defined mapper for default mapping.
8708 CombinedInfo.Mappers.push_back(nullptr);
8709 }
8710};
8711} // anonymous namespace
8712
8713/// Emit the arrays used to pass the captures and map information to the
8714/// offloading runtime library. If there is no map or capture information,
8715/// return nullptr by reference.
8716static void
8717emitOffloadingArrays(CodeGenFunction &CGF,
8718 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
8719 CGOpenMPRuntime::TargetDataInfo &Info) {
8720 CodeGenModule &CGM = CGF.CGM;
8721 ASTContext &Ctx = CGF.getContext();
8722
8723 // Reset the array information.
8724 Info.clearArrayInfo();
8725 Info.NumberOfPtrs = CombinedInfo.BasePointers.size();
8726
8727 if (Info.NumberOfPtrs) {
8728 // Detect if we have any capture size requiring runtime evaluation of the
8729 // size so that a constant array could be eventually used.
8730 bool hasRuntimeEvaluationCaptureSize = false;
8731 for (llvm::Value *S : CombinedInfo.Sizes)
8732 if (!isa<llvm::Constant>(S)) {
8733 hasRuntimeEvaluationCaptureSize = true;
8734 break;
8735 }
8736
8737 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
8738 QualType PointerArrayType = Ctx.getConstantArrayType(
8739 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
8740 /*IndexTypeQuals=*/0);
8741
8742 Info.BasePointersArray =
8743 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
8744 Info.PointersArray =
8745 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8746 Address MappersArray =
8747 CGF.CreateMemTemp(PointerArrayType, ".offload_mappers");
8748 Info.MappersArray = MappersArray.getPointer();
8749
8750 // If we don't have any VLA types or other types that require runtime
8751 // evaluation, we can use a constant array for the map sizes, otherwise we
8752 // need to fill up the arrays as we do for the pointers.
8753 QualType Int64Ty =
8754 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
8755 if (hasRuntimeEvaluationCaptureSize) {
8756 QualType SizeArrayType = Ctx.getConstantArrayType(
8757 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
8758 /*IndexTypeQuals=*/0);
8759 Info.SizesArray =
8760 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8761 } else {
8762 // We expect all the sizes to be constant, so we collect them to create
8763 // a constant array.
8764 SmallVector<llvm::Constant *, 16> ConstSizes;
8765 for (llvm::Value *S : CombinedInfo.Sizes)
8766 ConstSizes.push_back(cast<llvm::Constant>(S));
8767
8768 auto *SizesArrayInit = llvm::ConstantArray::get(
8769 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
8770 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
8771 auto *SizesArrayGbl = new llvm::GlobalVariable(
8772 CGM.getModule(), SizesArrayInit->getType(),
8773 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
8774 SizesArrayInit, Name);
8775 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
8776 Info.SizesArray = SizesArrayGbl;
8777 }
8778
8779 // The map types are always constant so we don't need to generate code to
8780 // fill arrays. Instead, we create an array constant.
8781 SmallVector<uint64_t, 4> Mapping(CombinedInfo.Types.size(), 0);
8782 llvm::copy(CombinedInfo.Types, Mapping.begin());
8783 llvm::Constant *MapTypesArrayInit =
8784 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
8785 std::string MaptypesName =
8786 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
8787 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8788 CGM.getModule(), MapTypesArrayInit->getType(),
8789 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
8790 MapTypesArrayInit, MaptypesName);
8791 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
8792 Info.MapTypesArray = MapTypesArrayGbl;
8793
8794 // If there's a present map type modifier, it must not be applied to the end
8795 // of a region, so generate a separate map type array in that case.
8796 if (Info.separateBeginEndCalls()) {
8797 bool EndMapTypesDiffer = false;
8798 for (uint64_t &Type : Mapping) {
8799 if (Type & MappableExprsHandler::OMP_MAP_PRESENT) {
8800 Type &= ~MappableExprsHandler::OMP_MAP_PRESENT;
8801 EndMapTypesDiffer = true;
8802 }
8803 }
8804 if (EndMapTypesDiffer) {
8805 MapTypesArrayInit =
8806 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
8807 MaptypesName = CGM.getOpenMPRuntime().getName({"offload_maptypes"});
8808 MapTypesArrayGbl = new llvm::GlobalVariable(
8809 CGM.getModule(), MapTypesArrayInit->getType(),
8810 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
8811 MapTypesArrayInit, MaptypesName);
8812 MapTypesArrayGbl->setUnnamedAddr(
8813 llvm::GlobalValue::UnnamedAddr::Global);
8814 Info.MapTypesArrayEnd = MapTypesArrayGbl;
8815 }
8816 }
8817
8818 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8819 llvm::Value *BPVal = *CombinedInfo.BasePointers[I];
8820 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
8821 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8822 Info.BasePointersArray, 0, I);
8823 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8824 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
8825 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8826 CGF.Builder.CreateStore(BPVal, BPAddr);
8827
8828 if (Info.requiresDevicePointerInfo())
8829 if (const ValueDecl *DevVD =
8830 CombinedInfo.BasePointers[I].getDevicePtrDecl())
8831 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
8832
8833 llvm::Value *PVal = CombinedInfo.Pointers[I];
8834 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
8835 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8836 Info.PointersArray, 0, I);
8837 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8838 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
8839 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8840 CGF.Builder.CreateStore(PVal, PAddr);
8841
8842 if (hasRuntimeEvaluationCaptureSize) {
8843 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
8844 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
8845 Info.SizesArray,
8846 /*Idx0=*/0,
8847 /*Idx1=*/I);
8848 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
8849 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(CombinedInfo.Sizes[I],
8850 CGM.Int64Ty,
8851 /*isSigned=*/true),
8852 SAddr);
8853 }
8854
8855 // Fill up the mapper array.
8856 llvm::Value *MFunc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
8857 if (CombinedInfo.Mappers[I]) {
8858 MFunc = CGM.getOpenMPRuntime().getOrCreateUserDefinedMapperFunc(
8859 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
8860 MFunc = CGF.Builder.CreatePointerCast(MFunc, CGM.VoidPtrTy);
8861 Info.HasMapper = true;
8862 }
8863 Address MAddr = CGF.Builder.CreateConstArrayGEP(MappersArray, I);
8864 CGF.Builder.CreateStore(MFunc, MAddr);
8865 }
8866 }
8867}
8868
8869namespace {
8870/// Additional arguments for emitOffloadingArraysArgument function.
8871struct ArgumentsOptions {
8872 bool ForEndCall = false;
8873 ArgumentsOptions() = default;
8874 ArgumentsOptions(bool ForEndCall) : ForEndCall(ForEndCall) {}
8875};
8876} // namespace
8877
8878/// Emit the arguments to be passed to the runtime library based on the
8879/// arrays of base pointers, pointers, sizes, map types, and mappers. If
8880/// ForEndCall, emit map types to be passed for the end of the region instead of
8881/// the beginning.
8882static void emitOffloadingArraysArgument(
8883 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8884 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
8885 llvm::Value *&MapTypesArrayArg, llvm::Value *&MappersArrayArg,
8886 CGOpenMPRuntime::TargetDataInfo &Info,
8887 const ArgumentsOptions &Options = ArgumentsOptions()) {
8888 assert((!Options.ForEndCall || Info.separateBeginEndCalls()) &&(((!Options.ForEndCall || Info.separateBeginEndCalls()) &&
"expected region end call to runtime only when end call is separate"
) ? static_cast<void> (0) : __assert_fail ("(!Options.ForEndCall || Info.separateBeginEndCalls()) && \"expected region end call to runtime only when end call is separate\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8889, __PRETTY_FUNCTION__))
8889 "expected region end call to runtime only when end call is separate")(((!Options.ForEndCall || Info.separateBeginEndCalls()) &&
"expected region end call to runtime only when end call is separate"
) ? static_cast<void> (0) : __assert_fail ("(!Options.ForEndCall || Info.separateBeginEndCalls()) && \"expected region end call to runtime only when end call is separate\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8889, __PRETTY_FUNCTION__))
;
8890 CodeGenModule &CGM = CGF.CGM;
8891 if (Info.NumberOfPtrs) {
8892 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
8893 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8894 Info.BasePointersArray,
8895 /*Idx0=*/0, /*Idx1=*/0);
8896 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
8897 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8898 Info.PointersArray,
8899 /*Idx0=*/0,
8900 /*Idx1=*/0);
8901 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
8902 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
8903 /*Idx0=*/0, /*Idx1=*/0);
8904 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
8905 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
8906 Options.ForEndCall && Info.MapTypesArrayEnd ? Info.MapTypesArrayEnd
8907 : Info.MapTypesArray,
8908 /*Idx0=*/0,
8909 /*Idx1=*/0);
8910 // If there is no user-defined mapper, set the mapper array to nullptr to
8911 // avoid an unnecessary data privatization
8912 if (!Info.HasMapper)
8913 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8914 else
8915 MappersArrayArg =
8916 CGF.Builder.CreatePointerCast(Info.MappersArray, CGM.VoidPtrPtrTy);
8917 } else {
8918 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8919 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8920 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
8921 MapTypesArrayArg =
8922 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
8923 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8924 }
8925}
8926
8927/// Check for inner distribute directive.
8928static const OMPExecutableDirective *
8929getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8930 const auto *CS = D.getInnermostCapturedStmt();
8931 const auto *Body =
8932 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
8933 const Stmt *ChildStmt =
8934 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8935
8936 if (const auto *NestedDir =
8937 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
8938 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8939 switch (D.getDirectiveKind()) {
8940 case OMPD_target:
8941 if (isOpenMPDistributeDirective(DKind))
8942 return NestedDir;
8943 if (DKind == OMPD_teams) {
8944 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8945 /*IgnoreCaptured=*/true);
8946 if (!Body)
8947 return nullptr;
8948 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8949 if (const auto *NND =
8950 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
8951 DKind = NND->getDirectiveKind();
8952 if (isOpenMPDistributeDirective(DKind))
8953 return NND;
8954 }
8955 }
8956 return nullptr;
8957 case OMPD_target_teams:
8958 if (isOpenMPDistributeDirective(DKind))
8959 return NestedDir;
8960 return nullptr;
8961 case OMPD_target_parallel:
8962 case OMPD_target_simd:
8963 case OMPD_target_parallel_for:
8964 case OMPD_target_parallel_for_simd:
8965 return nullptr;
8966 case OMPD_target_teams_distribute:
8967 case OMPD_target_teams_distribute_simd:
8968 case OMPD_target_teams_distribute_parallel_for:
8969 case OMPD_target_teams_distribute_parallel_for_simd:
8970 case OMPD_parallel:
8971 case OMPD_for:
8972 case OMPD_parallel_for:
8973 case OMPD_parallel_master:
8974 case OMPD_parallel_sections:
8975 case OMPD_for_simd:
8976 case OMPD_parallel_for_simd:
8977 case OMPD_cancel:
8978 case OMPD_cancellation_point:
8979 case OMPD_ordered:
8980 case OMPD_threadprivate:
8981 case OMPD_allocate:
8982 case OMPD_task:
8983 case OMPD_simd:
8984 case OMPD_sections:
8985 case OMPD_section:
8986 case OMPD_single:
8987 case OMPD_master:
8988 case OMPD_critical:
8989 case OMPD_taskyield:
8990 case OMPD_barrier:
8991 case OMPD_taskwait:
8992 case OMPD_taskgroup:
8993 case OMPD_atomic:
8994 case OMPD_flush:
8995 case OMPD_depobj:
8996 case OMPD_scan:
8997 case OMPD_teams:
8998 case OMPD_target_data:
8999 case OMPD_target_exit_data:
9000 case OMPD_target_enter_data:
9001 case OMPD_distribute:
9002 case OMPD_distribute_simd:
9003 case OMPD_distribute_parallel_for:
9004 case OMPD_distribute_parallel_for_simd:
9005 case OMPD_teams_distribute:
9006 case OMPD_teams_distribute_simd:
9007 case OMPD_teams_distribute_parallel_for:
9008 case OMPD_teams_distribute_parallel_for_simd:
9009 case OMPD_target_update:
9010 case OMPD_declare_simd:
9011 case OMPD_declare_variant:
9012 case OMPD_begin_declare_variant:
9013 case OMPD_end_declare_variant:
9014 case OMPD_declare_target:
9015 case OMPD_end_declare_target:
9016 case OMPD_declare_reduction:
9017 case OMPD_declare_mapper:
9018 case OMPD_taskloop:
9019 case OMPD_taskloop_simd:
9020 case OMPD_master_taskloop:
9021 case OMPD_master_taskloop_simd:
9022 case OMPD_parallel_master_taskloop:
9023 case OMPD_parallel_master_taskloop_simd:
9024 case OMPD_requires:
9025 case OMPD_unknown:
9026 default:
9027 llvm_unreachable("Unexpected directive.")::llvm::llvm_unreachable_internal("Unexpected directive.", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9027)
;
9028 }
9029 }
9030
9031 return nullptr;
9032}
9033
9034/// Emit the user-defined mapper function. The code generation follows the
9035/// pattern in the example below.
9036/// \code
9037/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
9038/// void *base, void *begin,
9039/// int64_t size, int64_t type) {
9040/// // Allocate space for an array section first.
9041/// if (size > 1 && !maptype.IsDelete)
9042/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
9043/// size*sizeof(Ty), clearToFrom(type));
9044/// // Map members.
9045/// for (unsigned i = 0; i < size; i++) {
9046/// // For each component specified by this mapper:
9047/// for (auto c : all_components) {
9048/// if (c.hasMapper())
9049/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
9050/// c.arg_type);
9051/// else
9052/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
9053/// c.arg_begin, c.arg_size, c.arg_type);
9054/// }
9055/// }
9056/// // Delete the array section.
9057/// if (size > 1 && maptype.IsDelete)
9058/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
9059/// size*sizeof(Ty), clearToFrom(type));
9060/// }
9061/// \endcode
9062void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
9063 CodeGenFunction *CGF) {
9064 if (UDMMap.count(D) > 0)
9065 return;
9066 ASTContext &C = CGM.getContext();
9067 QualType Ty = D->getType();
9068 QualType PtrTy = C.getPointerType(Ty).withRestrict();
9069 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
9070 auto *MapperVarDecl =
9071 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
9072 SourceLocation Loc = D->getLocation();
9073 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
9074
9075 // Prepare mapper function arguments and attributes.
9076 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
9077 C.VoidPtrTy, ImplicitParamDecl::Other);
9078 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
9079 ImplicitParamDecl::Other);
9080 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
9081 C.VoidPtrTy, ImplicitParamDecl::Other);
9082 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
9083 ImplicitParamDecl::Other);
9084 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
9085 ImplicitParamDecl::Other);
9086 FunctionArgList Args;
9087 Args.push_back(&HandleArg);
9088 Args.push_back(&BaseArg);
9089 Args.push_back(&BeginArg);
9090 Args.push_back(&SizeArg);
9091 Args.push_back(&TypeArg);
9092 const CGFunctionInfo &FnInfo =
9093 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
9094 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
9095 SmallString<64> TyStr;
9096 llvm::raw_svector_ostream Out(TyStr);
9097 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
9098 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
9099 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
9100 Name, &CGM.getModule());
9101 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
9102 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
9103 // Start the mapper function code generation.
9104 CodeGenFunction MapperCGF(CGM);
9105 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
9106 // Compute the starting and end addreses of array elements.
9107 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
9108 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
9109 C.getPointerType(Int64Ty), Loc);
9110 // Convert the size in bytes into the number of array elements.
9111 Size = MapperCGF.Builder.CreateExactUDiv(
9112 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9113 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
9114 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
9115 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
9116 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
9117 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
9118 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
9119 C.getPointerType(Int64Ty), Loc);
9120 // Prepare common arguments for array initiation and deletion.
9121 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
9122 MapperCGF.GetAddrOfLocalVar(&HandleArg),
9123 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9124 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
9125 MapperCGF.GetAddrOfLocalVar(&BaseArg),
9126 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9127 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
9128 MapperCGF.GetAddrOfLocalVar(&BeginArg),
9129 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9130
9131 // Emit array initiation if this is an array section and \p MapType indicates
9132 // that memory allocation is required.
9133 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
9134 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9135 ElementSize, HeadBB, /*IsInit=*/true);
9136
9137 // Emit a for loop to iterate through SizeArg of elements and map all of them.
9138
9139 // Emit the loop header block.
9140 MapperCGF.EmitBlock(HeadBB);
9141 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
9142 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
9143 // Evaluate whether the initial condition is satisfied.
9144 llvm::Value *IsEmpty =
9145 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
9146 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
9147 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
9148
9149 // Emit the loop body block.
9150 MapperCGF.EmitBlock(BodyBB);
9151 llvm::BasicBlock *LastBB = BodyBB;
9152 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
9153 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
9154 PtrPHI->addIncoming(PtrBegin, EntryBB);
9155 Address PtrCurrent =
9156 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
9157 .getAlignment()
9158 .alignmentOfArrayElement(ElementSize));
9159 // Privatize the declared variable of mapper to be the current array element.
9160 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
9161 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
9162 return MapperCGF
9163 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
9164 .getAddress(MapperCGF);
9165 });
9166 (void)Scope.Privatize();
9167
9168 // Get map clause information. Fill up the arrays with all mapped variables.
9169 MappableExprsHandler::MapCombinedInfoTy Info;
9170 MappableExprsHandler MEHandler(*D, MapperCGF);
9171 MEHandler.generateAllInfoForMapper(Info);
9172
9173 // Call the runtime API __tgt_mapper_num_components to get the number of
9174 // pre-existing components.
9175 llvm::Value *OffloadingArgs[] = {Handle};
9176 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
9177 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
9178 OMPRTL___tgt_mapper_num_components),
9179 OffloadingArgs);
9180 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
9181 PreviousSize,
9182 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
9183
9184 // Fill up the runtime mapper handle for all components.
9185 for (unsigned I = 0; I < Info.BasePointers.size(); ++I) {
9186 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
9187 *Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9188 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
9189 Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9190 llvm::Value *CurSizeArg = Info.Sizes[I];
9191
9192 // Extract the MEMBER_OF field from the map type.
9193 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
9194 MapperCGF.EmitBlock(MemberBB);
9195 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(Info.Types[I]);
9196 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
9197 OriMapType,
9198 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
9199 llvm::BasicBlock *MemberCombineBB =
9200 MapperCGF.createBasicBlock("omp.member.combine");
9201 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
9202 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
9203 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
9204 // Add the number of pre-existing components to the MEMBER_OF field if it
9205 // is valid.
9206 MapperCGF.EmitBlock(MemberCombineBB);
9207 llvm::Value *CombinedMember =
9208 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
9209 // Do nothing if it is not a member of previous components.
9210 MapperCGF.EmitBlock(TypeBB);
9211 llvm::PHINode *MemberMapType =
9212 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
9213 MemberMapType->addIncoming(OriMapType, MemberBB);
9214 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
9215
9216 // Combine the map type inherited from user-defined mapper with that
9217 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
9218 // bits of the \a MapType, which is the input argument of the mapper
9219 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
9220 // bits of MemberMapType.
9221 // [OpenMP 5.0], 1.2.6. map-type decay.
9222 // | alloc | to | from | tofrom | release | delete
9223 // ----------------------------------------------------------
9224 // alloc | alloc | alloc | alloc | alloc | release | delete
9225 // to | alloc | to | alloc | to | release | delete
9226 // from | alloc | alloc | from | from | release | delete
9227 // tofrom | alloc | to | from | tofrom | release | delete
9228 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9229 MapType,
9230 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9231 MappableExprsHandler::OMP_MAP_FROM));
9232 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9233 llvm::BasicBlock *AllocElseBB =
9234 MapperCGF.createBasicBlock("omp.type.alloc.else");
9235 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9236 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9237 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9238 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9239 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9240 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9241 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9242 MapperCGF.EmitBlock(AllocBB);
9243 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9244 MemberMapType,
9245 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9246 MappableExprsHandler::OMP_MAP_FROM)));
9247 MapperCGF.Builder.CreateBr(EndBB);
9248 MapperCGF.EmitBlock(AllocElseBB);
9249 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9250 LeftToFrom,
9251 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9252 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9253 // In case of to, clear OMP_MAP_FROM.
9254 MapperCGF.EmitBlock(ToBB);
9255 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9256 MemberMapType,
9257 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9258 MapperCGF.Builder.CreateBr(EndBB);
9259 MapperCGF.EmitBlock(ToElseBB);
9260 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9261 LeftToFrom,
9262 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9263 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9264 // In case of from, clear OMP_MAP_TO.
9265 MapperCGF.EmitBlock(FromBB);
9266 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9267 MemberMapType,
9268 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9269 // In case of tofrom, do nothing.
9270 MapperCGF.EmitBlock(EndBB);
9271 LastBB = EndBB;
9272 llvm::PHINode *CurMapType =
9273 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9274 CurMapType->addIncoming(AllocMapType, AllocBB);
9275 CurMapType->addIncoming(ToMapType, ToBB);
9276 CurMapType->addIncoming(FromMapType, FromBB);
9277 CurMapType->addIncoming(MemberMapType, ToElseBB);
9278
9279 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9280 CurSizeArg, CurMapType};
9281 if (Info.Mappers[I]) {
9282 // Call the corresponding mapper function.
9283 llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc(
9284 cast<OMPDeclareMapperDecl>(Info.Mappers[I]));
9285 assert(MapperFunc && "Expect a valid mapper function is available.")((MapperFunc && "Expect a valid mapper function is available."
) ? static_cast<void> (0) : __assert_fail ("MapperFunc && \"Expect a valid mapper function is available.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9285, __PRETTY_FUNCTION__))
;
9286 MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs);
9287 } else {
9288 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9289 // data structure.
9290 MapperCGF.EmitRuntimeCall(
9291 OMPBuilder.getOrCreateRuntimeFunction(
9292 CGM.getModule(), OMPRTL___tgt_push_mapper_component),
9293 OffloadingArgs);
9294 }
9295 }
9296
9297 // Update the pointer to point to the next element that needs to be mapped,
9298 // and check whether we have mapped all elements.
9299 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9300 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9301 PtrPHI->addIncoming(PtrNext, LastBB);
9302 llvm::Value *IsDone =
9303 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9304 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9305 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9306
9307 MapperCGF.EmitBlock(ExitBB);
9308 // Emit array deletion if this is an array section and \p MapType indicates
9309 // that deletion is required.
9310 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9311 ElementSize, DoneBB, /*IsInit=*/false);
9312
9313 // Emit the function exit block.
9314 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9315 MapperCGF.FinishFunction();
9316 UDMMap.try_emplace(D, Fn);
9317 if (CGF) {
9318 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9319 Decls.second.push_back(D);
9320 }
9321}
9322
9323/// Emit the array initialization or deletion portion for user-defined mapper
9324/// code generation. First, it evaluates whether an array section is mapped and
9325/// whether the \a MapType instructs to delete this section. If \a IsInit is
9326/// true, and \a MapType indicates to not delete this array, array
9327/// initialization code is generated. If \a IsInit is false, and \a MapType
9328/// indicates to not this array, array deletion code is generated.
9329void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9330 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9331 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9332 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9333 StringRef Prefix = IsInit ? ".init" : ".del";
9334
9335 // Evaluate if this is an array section.
9336 llvm::BasicBlock *IsDeleteBB =
9337 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"}));
9338 llvm::BasicBlock *BodyBB =
9339 MapperCGF.createBasicBlock(getName({"omp.array", Prefix}));
9340 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9341 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9342 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9343
9344 // Evaluate if we are going to delete this section.
9345 MapperCGF.EmitBlock(IsDeleteBB);
9346 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9347 MapType,
9348 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9349 llvm::Value *DeleteCond;
9350 if (IsInit) {
9351 DeleteCond = MapperCGF.Builder.CreateIsNull(
9352 DeleteBit, getName({"omp.array", Prefix, ".delete"}));
9353 } else {
9354 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9355 DeleteBit, getName({"omp.array", Prefix, ".delete"}));
9356 }
9357 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9358
9359 MapperCGF.EmitBlock(BodyBB);
9360 // Get the array size by multiplying element size and element number (i.e., \p
9361 // Size).
9362 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9363 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9364 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9365 // memory allocation/deletion purpose only.
9366 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9367 MapType,
9368 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9369 MappableExprsHandler::OMP_MAP_FROM)));
9370 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9371 // data structure.
9372 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9373 MapperCGF.EmitRuntimeCall(
9374 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
9375 OMPRTL___tgt_push_mapper_component),
9376 OffloadingArgs);
9377}
9378
9379llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc(
9380 const OMPDeclareMapperDecl *D) {
9381 auto I = UDMMap.find(D);
9382 if (I != UDMMap.end())
9383 return I->second;
9384 emitUserDefinedMapper(D);
9385 return UDMMap.lookup(D);
9386}
9387
9388void CGOpenMPRuntime::emitTargetNumIterationsCall(
9389 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9390 llvm::Value *DeviceID,
9391 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9392 const OMPLoopDirective &D)>
9393 SizeEmitter) {
9394 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9395 const OMPExecutableDirective *TD = &D;
9396 // Get nested teams distribute kind directive, if any.
9397 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9398 TD = getNestedDistributeDirective(CGM.getContext(), D);
9399 if (!TD)
9400 return;
9401 const auto *LD = cast<OMPLoopDirective>(TD);
9402 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
9403 PrePostActionTy &) {
9404 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9405 llvm::Value *Args[] = {DeviceID, NumIterations};
9406 CGF.EmitRuntimeCall(
9407 OMPBuilder.getOrCreateRuntimeFunction(
9408 CGM.getModule(), OMPRTL___kmpc_push_target_tripcount),
9409 Args);
9410 }
9411 };
9412 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9413}
9414
9415void CGOpenMPRuntime::emitTargetCall(
9416 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9417 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9418 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device,
9419 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9420 const OMPLoopDirective &D)>
9421 SizeEmitter) {
9422 if (!CGF.HaveInsertPoint())
1
Taking false branch
9423 return;
9424
9425 assert(OutlinedFn && "Invalid outlined function!")((OutlinedFn && "Invalid outlined function!") ? static_cast
<void> (0) : __assert_fail ("OutlinedFn && \"Invalid outlined function!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9425, __PRETTY_FUNCTION__))
;
2
Assuming 'OutlinedFn' is non-null
3
'?' condition is true
9426
9427 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() ||
4
Assuming the condition is false
9428 D.hasClausesOfKind<OMPNowaitClause>();
9429 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
9430 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
9431 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9432 PrePostActionTy &) {
9433 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9434 };
9435 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
9436
9437 CodeGenFunction::OMPTargetDataInfo InputInfo;
9438 llvm::Value *MapTypesArray = nullptr;
9439 // Fill up the pointer arrays and transfer execution to the device.
9440 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
9441 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9442 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
9443 if (Device.getInt() == OMPC_DEVICE_ancestor) {
9444 // Reverse offloading is not supported, so just execute on the host.
9445 if (RequiresOuterTask) {
9446 CapturedVars.clear();
9447 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9448 }
9449 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
9450 return;
9451 }
9452
9453 // On top of the arrays that were filled up, the target offloading call
9454 // takes as arguments the device id as well as the host pointer. The host
9455 // pointer is used by the runtime library to identify the current target
9456 // region, so it only has to be unique and not necessarily point to
9457 // anything. It could be the pointer to the outlined function that
9458 // implements the target region, but we aren't using that so that the
9459 // compiler doesn't need to keep that, and could therefore inline the host
9460 // function if proven worthwhile during optimization.
9461
9462 // From this point on, we need to have an ID of the target region defined.
9463 assert(OutlinedFnID && "Invalid outlined function ID!")((OutlinedFnID && "Invalid outlined function ID!") ? static_cast
<void> (0) : __assert_fail ("OutlinedFnID && \"Invalid outlined function ID!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9463, __PRETTY_FUNCTION__))
;
9464
9465 // Emit device ID if any.
9466 llvm::Value *DeviceID;
9467 if (Device.getPointer()) {
9468 assert((Device.getInt() == OMPC_DEVICE_unknown ||(((Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() ==
OMPC_DEVICE_device_num) && "Expected device_num modifier."
) ? static_cast<void> (0) : __assert_fail ("(Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() == OMPC_DEVICE_device_num) && \"Expected device_num modifier.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9470, __PRETTY_FUNCTION__))
9469 Device.getInt() == OMPC_DEVICE_device_num) &&(((Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() ==
OMPC_DEVICE_device_num) && "Expected device_num modifier."
) ? static_cast<void> (0) : __assert_fail ("(Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() == OMPC_DEVICE_device_num) && \"Expected device_num modifier.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9470, __PRETTY_FUNCTION__))
9470 "Expected device_num modifier.")(((Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() ==
OMPC_DEVICE_device_num) && "Expected device_num modifier."
) ? static_cast<void> (0) : __assert_fail ("(Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() == OMPC_DEVICE_device_num) && \"Expected device_num modifier.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9470, __PRETTY_FUNCTION__))
;
9471 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer());
9472 DeviceID =
9473 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true);
9474 } else {
9475 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9476 }
9477
9478 // Emit the number of elements in the offloading arrays.
9479 llvm::Value *PointerNum =
9480 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
9481
9482 // Return value of the runtime offloading call.
9483 llvm::Value *Return;
9484
9485 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9486 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
9487
9488 // Emit tripcount for the target loop-based directive.
9489 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9490
9491 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
9492 // The target region is an outlined function launched by the runtime
9493 // via calls __tgt_target() or __tgt_target_teams().
9494 //
9495 // __tgt_target() launches a target region with one team and one thread,
9496 // executing a serial region. This master thread may in turn launch
9497 // more threads within its team upon encountering a parallel region,
9498 // however, no additional teams can be launched on the device.
9499 //
9500 // __tgt_target_teams() launches a target region with one or more teams,
9501 // each with one or more threads. This call is required for target
9502 // constructs such as:
9503 // 'target teams'
9504 // 'target' / 'teams'
9505 // 'target teams distribute parallel for'
9506 // 'target parallel'
9507 // and so on.
9508 //
9509 // Note that on the host and CPU targets, the runtime implementation of
9510 // these calls simply call the outlined function without forking threads.
9511 // The outlined functions themselves have runtime calls to
9512 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9513 // the compiler in emitTeamsCall() and emitParallelCall().
9514 //
9515 // In contrast, on the NVPTX target, the implementation of
9516 // __tgt_target_teams() launches a GPU kernel with the requested number
9517 // of teams and threads so no additional calls to the runtime are required.
9518 if (NumTeams) {
9519 // If we have NumTeams defined this means that we have an enclosed teams
9520 // region. Therefore we also expect to have NumThreads defined. These two
9521 // values should be defined in the presence of a teams directive,
9522 // regardless of having any clauses associated. If the user is using teams
9523 // but no clauses, these two values will be the default that should be
9524 // passed to the runtime library - a 32-bit integer with the value zero.
9525 assert(NumThreads && "Thread limit expression should be available along "((NumThreads && "Thread limit expression should be available along "
"with number of teams.") ? static_cast<void> (0) : __assert_fail
("NumThreads && \"Thread limit expression should be available along \" \"with number of teams.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9526, __PRETTY_FUNCTION__))
9526 "with number of teams.")((NumThreads && "Thread limit expression should be available along "
"with number of teams.") ? static_cast<void> (0) : __assert_fail
("NumThreads && \"Thread limit expression should be available along \" \"with number of teams.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9526, __PRETTY_FUNCTION__))
;
9527 llvm::Value *OffloadingArgs[] = {DeviceID,
9528 OutlinedFnID,
9529 PointerNum,
9530 InputInfo.BasePointersArray.getPointer(),
9531 InputInfo.PointersArray.getPointer(),
9532 InputInfo.SizesArray.getPointer(),
9533 MapTypesArray,
9534 InputInfo.MappersArray.getPointer(),
9535 NumTeams,
9536 NumThreads};
9537 Return = CGF.EmitRuntimeCall(
9538 OMPBuilder.getOrCreateRuntimeFunction(
9539 CGM.getModule(), HasNowait
9540 ? OMPRTL___tgt_target_teams_nowait_mapper
9541 : OMPRTL___tgt_target_teams_mapper),
9542 OffloadingArgs);
9543 } else {
9544 llvm::Value *OffloadingArgs[] = {DeviceID,
9545 OutlinedFnID,
9546 PointerNum,
9547 InputInfo.BasePointersArray.getPointer(),
9548 InputInfo.PointersArray.getPointer(),
9549 InputInfo.SizesArray.getPointer(),
9550 MapTypesArray,
9551 InputInfo.MappersArray.getPointer()};
9552 Return = CGF.EmitRuntimeCall(
9553 OMPBuilder.getOrCreateRuntimeFunction(
9554 CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper
9555 : OMPRTL___tgt_target_mapper),
9556 OffloadingArgs);
9557 }
9558
9559 // Check the error code and execute the host version if required.
9560 llvm::BasicBlock *OffloadFailedBlock =
9561 CGF.createBasicBlock("omp_offload.failed");
9562 llvm::BasicBlock *OffloadContBlock =
9563 CGF.createBasicBlock("omp_offload.cont");
9564 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9565 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9566
9567 CGF.EmitBlock(OffloadFailedBlock);
9568 if (RequiresOuterTask) {
9569 CapturedVars.clear();
9570 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9571 }
9572 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
9573 CGF.EmitBranch(OffloadContBlock);
9574
9575 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
9576 };
9577
9578 // Notify that the host version must be executed.
9579 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9580 RequiresOuterTask](CodeGenFunction &CGF,
9581 PrePostActionTy &) {
9582 if (RequiresOuterTask) {
9583 CapturedVars.clear();
9584 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9585 }
9586 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
9587 };
9588
9589 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9590 &CapturedVars, RequiresOuterTask,
9591 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9592 // Fill up the arrays with all the captured variables.
9593 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
9594
9595 // Get mappable expression information.
9596 MappableExprsHandler MEHandler(D, CGF);
9597 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
9598 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
9599
9600 auto RI = CS.getCapturedRecordDecl()->field_begin();
9601 auto CV = CapturedVars.begin();
9602 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
18
Loop condition is true. Entering loop body
9603 CE = CS.capture_end();
9604 CI != CE; ++CI, ++RI, ++CV) {
9605 MappableExprsHandler::MapCombinedInfoTy CurInfo;
9606 MappableExprsHandler::StructRangeInfoTy PartialStruct;
9607
9608 // VLA sizes are passed to the outlined region by copy and do not have map
9609 // information associated.
9610 if (CI->capturesVariableArrayType()) {
19
Taking false branch
9611 CurInfo.BasePointers.push_back(*CV);
9612 CurInfo.Pointers.push_back(*CV);
9613 CurInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
9614 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
9615 // Copy to the device as an argument. No need to retrieve it.
9616 CurInfo.Types.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
9617 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9618 MappableExprsHandler::OMP_MAP_IMPLICIT);
9619 CurInfo.Mappers.push_back(nullptr);
9620 } else {
9621 // If we have any information in the map clause, we use it, otherwise we
9622 // just do a default mapping.
9623 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct);
20
Calling 'MappableExprsHandler::generateInfoForCapture'
9624 if (!CI->capturesThis())
9625 MappedVarSet.insert(CI->getCapturedVar());
9626 else
9627 MappedVarSet.insert(nullptr);
9628 if (CurInfo.BasePointers.empty())
9629 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
9630 // Generate correct mapping for variables captured by reference in
9631 // lambdas.
9632 if (CI->capturesVariable())
9633 MEHandler.generateInfoForLambdaCaptures(CI->getCapturedVar(), *CV,
9634 CurInfo, LambdaPointers);
9635 }
9636 // We expect to have at least an element of information for this capture.
9637 assert(!CurInfo.BasePointers.empty() &&((!CurInfo.BasePointers.empty() && "Non-existing map pointer for capture!"
) ? static_cast<void> (0) : __assert_fail ("!CurInfo.BasePointers.empty() && \"Non-existing map pointer for capture!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9638, __PRETTY_FUNCTION__))
9638 "Non-existing map pointer for capture!")((!CurInfo.BasePointers.empty() && "Non-existing map pointer for capture!"
) ? static_cast<void> (0) : __assert_fail ("!CurInfo.BasePointers.empty() && \"Non-existing map pointer for capture!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9638, __PRETTY_FUNCTION__))
;
9639 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&((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!") ? static_cast<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!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9643, __PRETTY_FUNCTION__))
9640 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&((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!") ? static_cast<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!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9643, __PRETTY_FUNCTION__))
9641 CurInfo.BasePointers.size() == CurInfo.Types.size() &&((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!") ? static_cast<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!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9643, __PRETTY_FUNCTION__))
9642 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&((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!") ? static_cast<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!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9643, __PRETTY_FUNCTION__))
9643 "Inconsistent map information sizes!")((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!") ? static_cast<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!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9643, __PRETTY_FUNCTION__))
;
9644
9645 // If there is an entry in PartialStruct it means we have a struct with
9646 // individual members mapped. Emit an extra combined entry.
9647 if (PartialStruct.Base.isValid())
9648 MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct);
9649
9650 // We need to append the results of this capture to what we already have.
9651 CombinedInfo.append(CurInfo);
9652 }
9653 // Adjust MEMBER_OF flags for the lambdas captures.
9654 MEHandler.adjustMemberOfForLambdaCaptures(
9655 LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers,
9656 CombinedInfo.Types);
9657 // Map any list items in a map clause that were not captures because they
9658 // weren't referenced within the construct.
9659 MEHandler.generateAllInfo(CombinedInfo, /*NotTargetParams=*/true,
9660 MappedVarSet);
9661
9662 TargetDataInfo Info;
9663 // Fill up the arrays and create the arguments.
9664 emitOffloadingArrays(CGF, CombinedInfo, Info);
9665 emitOffloadingArraysArgument(
9666 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray,
9667 Info.MapTypesArray, Info.MappersArray, Info, {/*ForEndTask=*/false});
9668 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9669 InputInfo.BasePointersArray =
9670 Address(Info.BasePointersArray, CGM.getPointerAlign());
9671 InputInfo.PointersArray =
9672 Address(Info.PointersArray, CGM.getPointerAlign());
9673 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9674 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign());
9675 MapTypesArray = Info.MapTypesArray;
9676 if (RequiresOuterTask)
9677 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9678 else
9679 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9680 };
9681
9682 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9683 CodeGenFunction &CGF, PrePostActionTy &) {
9684 if (RequiresOuterTask) {
9685 CodeGenFunction::OMPTargetDataInfo InputInfo;
9686 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9687 } else {
9688 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9689 }
9690 };
9691
9692 // If we have a target function ID it means that we need to support
9693 // offloading, otherwise, just execute on the host. We need to execute on host
9694 // regardless of the conditional in the if clause if, e.g., the user do not
9695 // specify target triples.
9696 if (OutlinedFnID) {
5
Assuming 'OutlinedFnID' is non-null
6
Taking true branch
9697 if (IfCond) {
7
Assuming 'IfCond' is non-null
8
Taking true branch
9698 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
9
Calling 'CGOpenMPRuntime::emitIfClause'
9699 } else {
9700 RegionCodeGenTy ThenRCG(TargetThenGen);
9701 ThenRCG(CGF);
9702 }
9703 } else {
9704 RegionCodeGenTy ElseRCG(TargetElseGen);
9705 ElseRCG(CGF);
9706 }
9707}
9708
9709void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9710 StringRef ParentName) {
9711 if (!S)
9712 return;
9713
9714 // Codegen OMP target directives that offload compute to the device.
9715 bool RequiresDeviceCodegen =
9716 isa<OMPExecutableDirective>(S) &&
9717 isOpenMPTargetExecutionDirective(
9718 cast<OMPExecutableDirective>(S)->getDirectiveKind());
9719
9720 if (RequiresDeviceCodegen) {
9721 const auto &E = *cast<OMPExecutableDirective>(S);
9722 unsigned DeviceID;
9723 unsigned FileID;
9724 unsigned Line;
9725 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
9726 FileID, Line);
9727
9728 // Is this a target region that should not be emitted as an entry point? If
9729 // so just signal we are done with this target region.
9730 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9731 ParentName, Line))
9732 return;
9733
9734 switch (E.getDirectiveKind()) {
9735 case OMPD_target:
9736 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9737 cast<OMPTargetDirective>(E));
9738 break;
9739 case OMPD_target_parallel:
9740 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
9741 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
9742 break;
9743 case OMPD_target_teams:
9744 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
9745 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
9746 break;
9747 case OMPD_target_teams_distribute:
9748 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
9749 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
9750 break;
9751 case OMPD_target_teams_distribute_simd:
9752 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
9753 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
9754 break;
9755 case OMPD_target_parallel_for:
9756 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
9757 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
9758 break;
9759 case OMPD_target_parallel_for_simd:
9760 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
9761 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
9762 break;
9763 case OMPD_target_simd:
9764 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
9765 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
9766 break;
9767 case OMPD_target_teams_distribute_parallel_for:
9768 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9769 CGM, ParentName,
9770 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
9771 break;
9772 case OMPD_target_teams_distribute_parallel_for_simd:
9773 CodeGenFunction::
9774 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9775 CGM, ParentName,
9776 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
9777 break;
9778 case OMPD_parallel:
9779 case OMPD_for:
9780 case OMPD_parallel_for:
9781 case OMPD_parallel_master:
9782 case OMPD_parallel_sections:
9783 case OMPD_for_simd:
9784 case OMPD_parallel_for_simd:
9785 case OMPD_cancel:
9786 case OMPD_cancellation_point:
9787 case OMPD_ordered:
9788 case OMPD_threadprivate:
9789 case OMPD_allocate:
9790 case OMPD_task:
9791 case OMPD_simd:
9792 case OMPD_sections:
9793 case OMPD_section:
9794 case OMPD_single:
9795 case OMPD_master:
9796 case OMPD_critical:
9797 case OMPD_taskyield:
9798 case OMPD_barrier:
9799 case OMPD_taskwait:
9800 case OMPD_taskgroup:
9801 case OMPD_atomic:
9802 case OMPD_flush:
9803 case OMPD_depobj:
9804 case OMPD_scan:
9805 case OMPD_teams:
9806 case OMPD_target_data:
9807 case OMPD_target_exit_data:
9808 case OMPD_target_enter_data:
9809 case OMPD_distribute:
9810 case OMPD_distribute_simd:
9811 case OMPD_distribute_parallel_for:
9812 case OMPD_distribute_parallel_for_simd:
9813 case OMPD_teams_distribute:
9814 case OMPD_teams_distribute_simd:
9815 case OMPD_teams_distribute_parallel_for:
9816 case OMPD_teams_distribute_parallel_for_simd:
9817 case OMPD_target_update:
9818 case OMPD_declare_simd:
9819 case OMPD_declare_variant:
9820 case OMPD_begin_declare_variant:
9821 case OMPD_end_declare_variant:
9822 case OMPD_declare_target:
9823 case OMPD_end_declare_target:
9824 case OMPD_declare_reduction:
9825 case OMPD_declare_mapper:
9826 case OMPD_taskloop:
9827 case OMPD_taskloop_simd:
9828 case OMPD_master_taskloop:
9829 case OMPD_master_taskloop_simd:
9830 case OMPD_parallel_master_taskloop:
9831 case OMPD_parallel_master_taskloop_simd:
9832 case OMPD_requires:
9833 case OMPD_unknown:
9834 default:
9835 llvm_unreachable("Unknown target directive for OpenMP device codegen.")::llvm::llvm_unreachable_internal("Unknown target directive for OpenMP device codegen."
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9835)
;
9836 }
9837 return;
9838 }
9839
9840 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
9841 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
9842 return;
9843
9844 scanForTargetRegionsFunctions(E->getRawStmt(), ParentName);
9845 return;
9846 }
9847
9848 // If this is a lambda function, look into its body.
9849 if (const auto *L = dyn_cast<LambdaExpr>(S))
9850 S = L->getBody();
9851
9852 // Keep looking for target regions recursively.
9853 for (const Stmt *II : S->children())
9854 scanForTargetRegionsFunctions(II, ParentName);
9855}
9856
9857bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
9858 // If emitting code for the host, we do not process FD here. Instead we do
9859 // the normal code generation.
9860 if (!CGM.getLangOpts().OpenMPIsDevice) {
9861 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9862 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9863 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9864 // Do not emit device_type(nohost) functions for the host.
9865 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9866 return true;
9867 }
9868 return false;
9869 }
9870
9871 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
9872 // Try to detect target regions in the function.
9873 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
9874 StringRef Name = CGM.getMangledName(GD);
9875 scanForTargetRegionsFunctions(FD->getBody(), Name);
9876 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9877 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9878 // Do not emit device_type(nohost) functions for the host.
9879 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9880 return true;
9881 }
9882
9883 // Do not to emit function if it is not marked as declare target.
9884 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
9885 AlreadyEmittedTargetDecls.count(VD) == 0;
9886}
9887
9888bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9889 if (!CGM.getLangOpts().OpenMPIsDevice)
9890 return false;
9891
9892 // Check if there are Ctors/Dtors in this declaration and look for target
9893 // regions in it. We use the complete variant to produce the kernel name
9894 // mangling.
9895 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
9896 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9897 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
9898 StringRef ParentName =
9899 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9900 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9901 }
9902 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
9903 StringRef ParentName =
9904 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9905 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9906 }
9907 }
9908
9909 // Do not to emit variable if it is not marked as declare target.
9910 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9911 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9912 cast<VarDecl>(GD.getDecl()));
9913 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9914 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9915 HasRequiresUnifiedSharedMemory)) {
9916 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
9917 return true;
9918 }
9919 return false;
9920}
9921
9922llvm::Constant *
9923CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9924 const VarDecl *VD) {
9925 assert(VD->getType().isConstant(CGM.getContext()) &&((VD->getType().isConstant(CGM.getContext()) && "Expected constant variable."
) ? static_cast<void> (0) : __assert_fail ("VD->getType().isConstant(CGM.getContext()) && \"Expected constant variable.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9926, __PRETTY_FUNCTION__))
9926 "Expected constant variable.")((VD->getType().isConstant(CGM.getContext()) && "Expected constant variable."
) ? static_cast<void> (0) : __assert_fail ("VD->getType().isConstant(CGM.getContext()) && \"Expected constant variable.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9926, __PRETTY_FUNCTION__))
;
9927 StringRef VarName;
9928 llvm::Constant *Addr;
9929 llvm::GlobalValue::LinkageTypes Linkage;
9930 QualType Ty = VD->getType();
9931 SmallString<128> Buffer;
9932 {
9933 unsigned DeviceID;
9934 unsigned FileID;
9935 unsigned Line;
9936 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9937 FileID, Line);
9938 llvm::raw_svector_ostream OS(Buffer);
9939 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9940 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9941 VarName = OS.str();
9942 }
9943 Linkage = llvm::GlobalValue::InternalLinkage;
9944 Addr =
9945 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9946 getDefaultFirstprivateAddressSpace());
9947 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9948 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9949 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9950 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9951 VarName, Addr, VarSize,
9952 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9953 return Addr;
9954}
9955
9956void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9957 llvm::Constant *Addr) {
9958 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
9959 !CGM.getLangOpts().OpenMPIsDevice)
9960 return;
9961 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9962 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9963 if (!Res) {
9964 if (CGM.getLangOpts().OpenMPIsDevice) {
9965 // Register non-target variables being emitted in device code (debug info
9966 // may cause this).
9967 StringRef VarName = CGM.getMangledName(VD);
9968 EmittedNonTargetVariables.try_emplace(VarName, Addr);
9969 }
9970 return;
9971 }
9972 // Register declare target variables.
9973 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9974 StringRef VarName;
9975 CharUnits VarSize;
9976 llvm::GlobalValue::LinkageTypes Linkage;
9977
9978 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9979 !HasRequiresUnifiedSharedMemory) {
9980 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9981 VarName = CGM.getMangledName(VD);
9982 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9983 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9984 assert(!VarSize.isZero() && "Expected non-zero size of the variable")((!VarSize.isZero() && "Expected non-zero size of the variable"
) ? static_cast<void> (0) : __assert_fail ("!VarSize.isZero() && \"Expected non-zero size of the variable\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9984, __PRETTY_FUNCTION__))
;
9985 } else {
9986 VarSize = CharUnits::Zero();
9987 }
9988 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9989 // Temp solution to prevent optimizations of the internal variables.
9990 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9991 std::string RefName = getName({VarName, "ref"});
9992 if (!CGM.GetGlobalValue(RefName)) {
9993 llvm::Constant *AddrRef =
9994 getOrCreateInternalVariable(Addr->getType(), RefName);
9995 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9996 GVAddrRef->setConstant(/*Val=*/true);
9997 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9998 GVAddrRef->setInitializer(Addr);
9999 CGM.addCompilerUsedGlobal(GVAddrRef);
10000 }
10001 }
10002 } else {
10003 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||((((*Res == OMPDeclareTargetDeclAttr::MT_Link) || (*Res == OMPDeclareTargetDeclAttr
::MT_To && HasRequiresUnifiedSharedMemory)) &&
"Declare target attribute must link or to with unified memory."
) ? static_cast<void> (0) : __assert_fail ("((*Res == OMPDeclareTargetDeclAttr::MT_Link) || (*Res == OMPDeclareTargetDeclAttr::MT_To && HasRequiresUnifiedSharedMemory)) && \"Declare target attribute must link or to with unified memory.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10006, __PRETTY_FUNCTION__))
10004 (*Res == OMPDeclareTargetDeclAttr::MT_To &&((((*Res == OMPDeclareTargetDeclAttr::MT_Link) || (*Res == OMPDeclareTargetDeclAttr
::MT_To && HasRequiresUnifiedSharedMemory)) &&
"Declare target attribute must link or to with unified memory."
) ? static_cast<void> (0) : __assert_fail ("((*Res == OMPDeclareTargetDeclAttr::MT_Link) || (*Res == OMPDeclareTargetDeclAttr::MT_To && HasRequiresUnifiedSharedMemory)) && \"Declare target attribute must link or to with unified memory.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10006, __PRETTY_FUNCTION__))
10005 HasRequiresUnifiedSharedMemory)) &&((((*Res == OMPDeclareTargetDeclAttr::MT_Link) || (*Res == OMPDeclareTargetDeclAttr
::MT_To && HasRequiresUnifiedSharedMemory)) &&
"Declare target attribute must link or to with unified memory."
) ? static_cast<void> (0) : __assert_fail ("((*Res == OMPDeclareTargetDeclAttr::MT_Link) || (*Res == OMPDeclareTargetDeclAttr::MT_To && HasRequiresUnifiedSharedMemory)) && \"Declare target attribute must link or to with unified memory.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10006, __PRETTY_FUNCTION__))
10006 "Declare target attribute must link or to with unified memory.")((((*Res == OMPDeclareTargetDeclAttr::MT_Link) || (*Res == OMPDeclareTargetDeclAttr
::MT_To && HasRequiresUnifiedSharedMemory)) &&
"Declare target attribute must link or to with unified memory."
) ? static_cast<void> (0) : __assert_fail ("((*Res == OMPDeclareTargetDeclAttr::MT_Link) || (*Res == OMPDeclareTargetDeclAttr::MT_To && HasRequiresUnifiedSharedMemory)) && \"Declare target attribute must link or to with unified memory.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10006, __PRETTY_FUNCTION__))
;
10007 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
10008 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
10009 else
10010 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
10011
10012 if (CGM.getLangOpts().OpenMPIsDevice) {
10013 VarName = Addr->getName();
10014 Addr = nullptr;
10015 } else {
10016 VarName = getAddrOfDeclareTargetVar(VD).getName();
10017 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
10018 }
10019 VarSize = CGM.getPointerSize();
10020 Linkage = llvm::GlobalValue::WeakAnyLinkage;
10021 }
10022
10023 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
10024 VarName, Addr, VarSize, Flags, Linkage);
10025}
10026
10027bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
10028 if (isa<FunctionDecl>(GD.getDecl()) ||
10029 isa<OMPDeclareReductionDecl>(GD.getDecl()))
10030 return emitTargetFunctions(GD);
10031
10032 return emitTargetGlobalVariable(GD);
10033}
10034
10035void CGOpenMPRuntime::emitDeferredTargetDecls() const {
10036 for (const VarDecl *VD : DeferredGlobalVariables) {
10037 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10038 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10039 if (!Res)
10040 continue;
10041 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
10042 !HasRequiresUnifiedSharedMemory) {
10043 CGM.EmitGlobal(VD);
10044 } else {
10045 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||(((*Res == OMPDeclareTargetDeclAttr::MT_Link || (*Res == OMPDeclareTargetDeclAttr
::MT_To && HasRequiresUnifiedSharedMemory)) &&
"Expected link clause or to clause with unified memory.") ? static_cast
<void> (0) : __assert_fail ("(*Res == OMPDeclareTargetDeclAttr::MT_Link || (*Res == OMPDeclareTargetDeclAttr::MT_To && HasRequiresUnifiedSharedMemory)) && \"Expected link clause or to clause with unified memory.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10048, __PRETTY_FUNCTION__))
10046 (*Res == OMPDeclareTargetDeclAttr::MT_To &&(((*Res == OMPDeclareTargetDeclAttr::MT_Link || (*Res == OMPDeclareTargetDeclAttr
::MT_To && HasRequiresUnifiedSharedMemory)) &&
"Expected link clause or to clause with unified memory.") ? static_cast
<void> (0) : __assert_fail ("(*Res == OMPDeclareTargetDeclAttr::MT_Link || (*Res == OMPDeclareTargetDeclAttr::MT_To && HasRequiresUnifiedSharedMemory)) && \"Expected link clause or to clause with unified memory.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10048, __PRETTY_FUNCTION__))
10047 HasRequiresUnifiedSharedMemory)) &&(((*Res == OMPDeclareTargetDeclAttr::MT_Link || (*Res == OMPDeclareTargetDeclAttr
::MT_To && HasRequiresUnifiedSharedMemory)) &&
"Expected link clause or to clause with unified memory.") ? static_cast
<void> (0) : __assert_fail ("(*Res == OMPDeclareTargetDeclAttr::MT_Link || (*Res == OMPDeclareTargetDeclAttr::MT_To && HasRequiresUnifiedSharedMemory)) && \"Expected link clause or to clause with unified memory.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10048, __PRETTY_FUNCTION__))
10048 "Expected link clause or to clause with unified memory.")(((*Res == OMPDeclareTargetDeclAttr::MT_Link || (*Res == OMPDeclareTargetDeclAttr
::MT_To && HasRequiresUnifiedSharedMemory)) &&
"Expected link clause or to clause with unified memory.") ? static_cast
<void> (0) : __assert_fail ("(*Res == OMPDeclareTargetDeclAttr::MT_Link || (*Res == OMPDeclareTargetDeclAttr::MT_To && HasRequiresUnifiedSharedMemory)) && \"Expected link clause or to clause with unified memory.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10048, __PRETTY_FUNCTION__))
;
10049 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
10050 }
10051 }
10052}
10053
10054void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
10055 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
10056 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&((isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
" Expected target-based directive.") ? static_cast<void>
(0) : __assert_fail ("isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && \" Expected target-based directive.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10057, __PRETTY_FUNCTION__))
10057 " Expected target-based directive.")((isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
" Expected target-based directive.") ? static_cast<void>
(0) : __assert_fail ("isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && \" Expected target-based directive.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10057, __PRETTY_FUNCTION__))
;
10058}
10059
10060void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) {
10061 for (const OMPClause *Clause : D->clauselists()) {
10062 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
10063 HasRequiresUnifiedSharedMemory = true;
10064 } else if (const auto *AC =
10065 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
10066 switch (AC->getAtomicDefaultMemOrderKind()) {
10067 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
10068 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease;
10069 break;
10070 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
10071 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent;
10072 break;
10073 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
10074 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic;
10075 break;
10076 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown:
10077 break;
10078 }
10079 }
10080 }
10081}
10082
10083llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const {
10084 return RequiresAtomicOrdering;
10085}
10086
10087bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
10088 LangAS &AS) {
10089 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
10090 return false;
10091 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
10092 switch(A->getAllocatorType()) {
10093 case OMPAllocateDeclAttr::OMPNullMemAlloc:
10094 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
10095 // Not supported, fallback to the default mem space.
10096 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
10097 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
10098 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
10099 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
10100 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
10101 case OMPAllocateDeclAttr::OMPConstMemAlloc:
10102 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
10103 AS = LangAS::Default;
10104 return true;
10105 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
10106 llvm_unreachable("Expected predefined allocator for the variables with the "::llvm::llvm_unreachable_internal("Expected predefined allocator for the variables with the "
"static storage.", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10107)
10107 "static storage.")::llvm::llvm_unreachable_internal("Expected predefined allocator for the variables with the "
"static storage.", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10107)
;
10108 }
10109 return false;
10110}
10111
10112bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
10113 return HasRequiresUnifiedSharedMemory;
10114}
10115
10116CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
10117 CodeGenModule &CGM)
10118 : CGM(CGM) {
10119 if (CGM.getLangOpts().OpenMPIsDevice) {
10120 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
10121 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
10122 }
10123}
10124
10125CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
10126 if (CGM.getLangOpts().OpenMPIsDevice)
10127 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
10128}
10129
10130bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
10131 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
10132 return true;
10133
10134 const auto *D = cast<FunctionDecl>(GD.getDecl());
10135 // Do not to emit function if it is marked as declare target as it was already
10136 // emitted.
10137 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
10138 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) {
10139 if (auto *F = dyn_cast_or_null<llvm::Function>(
10140 CGM.GetGlobalValue(CGM.getMangledName(GD))))
10141 return !F->isDeclaration();
10142 return false;
10143 }
10144 return true;
10145 }
10146
10147 return !AlreadyEmittedTargetDecls.insert(D).second;
10148}
10149
10150llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
10151 // If we don't have entries or if we are emitting code for the device, we
10152 // don't need to do anything.
10153 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
10154 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
10155 (OffloadEntriesInfoManager.empty() &&
10156 !HasEmittedDeclareTargetRegion &&
10157 !HasEmittedTargetRegion))
10158 return nullptr;
10159
10160 // Create and register the function that handles the requires directives.
10161 ASTContext &C = CGM.getContext();
10162
10163 llvm::Function *RequiresRegFn;
10164 {
10165 CodeGenFunction CGF(CGM);
10166 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
10167 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
10168 std::string ReqName = getName({"omp_offloading", "requires_reg"});
10169 RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI);
10170 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
10171 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
10172 // TODO: check for other requires clauses.
10173 // The requires directive takes effect only when a target region is
10174 // present in the compilation unit. Otherwise it is ignored and not
10175 // passed to the runtime. This avoids the runtime from throwing an error
10176 // for mismatching requires clauses across compilation units that don't
10177 // contain at least 1 target region.
10178 assert((HasEmittedTargetRegion ||(((HasEmittedTargetRegion || HasEmittedDeclareTargetRegion ||
!OffloadEntriesInfoManager.empty()) && "Target or declare target region expected."
) ? static_cast<void> (0) : __assert_fail ("(HasEmittedTargetRegion || HasEmittedDeclareTargetRegion || !OffloadEntriesInfoManager.empty()) && \"Target or declare target region expected.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10181, __PRETTY_FUNCTION__))
10179 HasEmittedDeclareTargetRegion ||(((HasEmittedTargetRegion || HasEmittedDeclareTargetRegion ||
!OffloadEntriesInfoManager.empty()) && "Target or declare target region expected."
) ? static_cast<void> (0) : __assert_fail ("(HasEmittedTargetRegion || HasEmittedDeclareTargetRegion || !OffloadEntriesInfoManager.empty()) && \"Target or declare target region expected.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10181, __PRETTY_FUNCTION__))
10180 !OffloadEntriesInfoManager.empty()) &&(((HasEmittedTargetRegion || HasEmittedDeclareTargetRegion ||
!OffloadEntriesInfoManager.empty()) && "Target or declare target region expected."
) ? static_cast<void> (0) : __assert_fail ("(HasEmittedTargetRegion || HasEmittedDeclareTargetRegion || !OffloadEntriesInfoManager.empty()) && \"Target or declare target region expected.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10181, __PRETTY_FUNCTION__))
10181 "Target or declare target region expected.")(((HasEmittedTargetRegion || HasEmittedDeclareTargetRegion ||
!OffloadEntriesInfoManager.empty()) && "Target or declare target region expected."
) ? static_cast<void> (0) : __assert_fail ("(HasEmittedTargetRegion || HasEmittedDeclareTargetRegion || !OffloadEntriesInfoManager.empty()) && \"Target or declare target region expected.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10181, __PRETTY_FUNCTION__))
;
10182 if (HasRequiresUnifiedSharedMemory)
10183 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
10184 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
10185 CGM.getModule(), OMPRTL___tgt_register_requires),
10186 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
10187 CGF.FinishFunction();
10188 }
10189 return RequiresRegFn;
10190}
10191
10192void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
10193 const OMPExecutableDirective &D,
10194 SourceLocation Loc,
10195 llvm::Function *OutlinedFn,
10196 ArrayRef<llvm::Value *> CapturedVars) {
10197 if (!CGF.HaveInsertPoint())
10198 return;
10199
10200 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
10201 CodeGenFunction::RunCleanupsScope Scope(CGF);
10202
10203 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
10204 llvm::Value *Args[] = {
10205 RTLoc,
10206 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
10207 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
10208 llvm::SmallVector<llvm::Value *, 16> RealArgs;
10209 RealArgs.append(std::begin(Args), std::end(Args));
10210 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
10211
10212 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction(
10213 CGM.getModule(), OMPRTL___kmpc_fork_teams);
10214 CGF.EmitRuntimeCall(RTLFn, RealArgs);
10215}
10216
10217void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
10218 const Expr *NumTeams,
10219 const Expr *ThreadLimit,
10220 SourceLocation Loc) {
10221 if (!CGF.HaveInsertPoint())
10222 return;
10223
10224 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
10225
10226 llvm::Value *NumTeamsVal =
10227 NumTeams
10228 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
10229 CGF.CGM.Int32Ty, /* isSigned = */ true)
10230 : CGF.Builder.getInt32(0);
10231
10232 llvm::Value *ThreadLimitVal =
10233 ThreadLimit
10234 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
10235 CGF.CGM.Int32Ty, /* isSigned = */ true)
10236 : CGF.Builder.getInt32(0);
10237
10238 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
10239 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
10240 ThreadLimitVal};
10241 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
10242 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
10243 PushNumTeamsArgs);
10244}
10245
10246void CGOpenMPRuntime::emitTargetDataCalls(
10247 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10248 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
10249 if (!CGF.HaveInsertPoint())
10250 return;
10251
10252 // Action used to replace the default codegen action and turn privatization
10253 // off.
10254 PrePostActionTy NoPrivAction;
10255
10256 // Generate the code for the opening of the data environment. Capture all the
10257 // arguments of the runtime call by reference because they are used in the
10258 // closing of the region.
10259 auto &&BeginThenGen = [this, &D, Device, &Info,
10260 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
10261 // Fill up the arrays with all the mapped variables.
10262 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10263
10264 // Get map clause information.
10265 MappableExprsHandler MEHandler(D, CGF);
10266 MEHandler.generateAllInfo(CombinedInfo);
10267
10268 // Fill up the arrays and create the arguments.
10269 emitOffloadingArrays(CGF, CombinedInfo, Info);
10270
10271 llvm::Value *BasePointersArrayArg = nullptr;
10272 llvm::Value *PointersArrayArg = nullptr;
10273 llvm::Value *SizesArrayArg = nullptr;
10274 llvm::Value *MapTypesArrayArg = nullptr;
10275 llvm::Value *MappersArrayArg = nullptr;
10276 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
10277 SizesArrayArg, MapTypesArrayArg,
10278 MappersArrayArg, Info);
10279
10280 // Emit device ID if any.
10281 llvm::Value *DeviceID = nullptr;
10282 if (Device) {
10283 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10284 CGF.Int64Ty, /*isSigned=*/true);
10285 } else {
10286 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10287 }
10288
10289 // Emit the number of elements in the offloading arrays.
10290 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
10291
10292 llvm::Value *OffloadingArgs[] = {
10293 DeviceID, PointerNum, BasePointersArrayArg, PointersArrayArg,
10294 SizesArrayArg, MapTypesArrayArg, MappersArrayArg};
10295 CGF.EmitRuntimeCall(
10296 OMPBuilder.getOrCreateRuntimeFunction(
10297 CGM.getModule(), OMPRTL___tgt_target_data_begin_mapper),
10298 OffloadingArgs);
10299
10300 // If device pointer privatization is required, emit the body of the region
10301 // here. It will have to be duplicated: with and without privatization.
10302 if (!Info.CaptureDeviceAddrMap.empty())
10303 CodeGen(CGF);
10304 };
10305
10306 // Generate code for the closing of the data region.
10307 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10308 PrePostActionTy &) {
10309 assert(Info.isValid() && "Invalid data environment closing arguments.")((Info.isValid() && "Invalid data environment closing arguments."
) ? static_cast<void> (0) : __assert_fail ("Info.isValid() && \"Invalid data environment closing arguments.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10309, __PRETTY_FUNCTION__))
;
10310
10311 llvm::Value *BasePointersArrayArg = nullptr;
10312 llvm::Value *PointersArrayArg = nullptr;
10313 llvm::Value *SizesArrayArg = nullptr;
10314 llvm::Value *MapTypesArrayArg = nullptr;
10315 llvm::Value *MappersArrayArg = nullptr;
10316 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
10317 SizesArrayArg, MapTypesArrayArg,
10318 MappersArrayArg, Info, {/*ForEndCall=*/true});
10319
10320 // Emit device ID if any.
10321 llvm::Value *DeviceID = nullptr;
10322 if (Device) {
10323 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10324 CGF.Int64Ty, /*isSigned=*/true);
10325 } else {
10326 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10327 }
10328
10329 // Emit the number of elements in the offloading arrays.
10330 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
10331
10332 llvm::Value *OffloadingArgs[] = {
10333 DeviceID, PointerNum, BasePointersArrayArg, PointersArrayArg,
10334 SizesArrayArg, MapTypesArrayArg, MappersArrayArg};
10335 CGF.EmitRuntimeCall(
10336 OMPBuilder.getOrCreateRuntimeFunction(
10337 CGM.getModule(), OMPRTL___tgt_target_data_end_mapper),
10338 OffloadingArgs);
10339 };
10340
10341 // If we need device pointer privatization, we need to emit the body of the
10342 // region with no privatization in the 'else' branch of the conditional.
10343 // Otherwise, we don't have to do anything.
10344 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10345 PrePostActionTy &) {
10346 if (!Info.CaptureDeviceAddrMap.empty()) {
10347 CodeGen.setAction(NoPrivAction);
10348 CodeGen(CGF);
10349 }
10350 };
10351
10352 // We don't have to do anything to close the region if the if clause evaluates
10353 // to false.
10354 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
10355
10356 if (IfCond) {
10357 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
10358 } else {
10359 RegionCodeGenTy RCG(BeginThenGen);
10360 RCG(CGF);
10361 }
10362
10363 // If we don't require privatization of device pointers, we emit the body in
10364 // between the runtime calls. This avoids duplicating the body code.
10365 if (Info.CaptureDeviceAddrMap.empty()) {
10366 CodeGen.setAction(NoPrivAction);
10367 CodeGen(CGF);
10368 }
10369
10370 if (IfCond) {
10371 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen);
10372 } else {
10373 RegionCodeGenTy RCG(EndThenGen);
10374 RCG(CGF);
10375 }
10376}
10377
10378void CGOpenMPRuntime::emitTargetDataStandAloneCall(
10379 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10380 const Expr *Device) {
10381 if (!CGF.HaveInsertPoint())
10382 return;
10383
10384 assert((isa<OMPTargetEnterDataDirective>(D) ||(((isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective
>(D) || isa<OMPTargetUpdateDirective>(D)) &&
"Expecting either target enter, exit data, or update directives."
) ? static_cast<void> (0) : __assert_fail ("(isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective>(D) || isa<OMPTargetUpdateDirective>(D)) && \"Expecting either target enter, exit data, or update directives.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10387, __PRETTY_FUNCTION__))
10385 isa<OMPTargetExitDataDirective>(D) ||(((isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective
>(D) || isa<OMPTargetUpdateDirective>(D)) &&
"Expecting either target enter, exit data, or update directives."
) ? static_cast<void> (0) : __assert_fail ("(isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective>(D) || isa<OMPTargetUpdateDirective>(D)) && \"Expecting either target enter, exit data, or update directives.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10387, __PRETTY_FUNCTION__))
10386 isa<OMPTargetUpdateDirective>(D)) &&(((isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective
>(D) || isa<OMPTargetUpdateDirective>(D)) &&
"Expecting either target enter, exit data, or update directives."
) ? static_cast<void> (0) : __assert_fail ("(isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective>(D) || isa<OMPTargetUpdateDirective>(D)) && \"Expecting either target enter, exit data, or update directives.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10387, __PRETTY_FUNCTION__))
10387 "Expecting either target enter, exit data, or update directives.")(((isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective
>(D) || isa<OMPTargetUpdateDirective>(D)) &&
"Expecting either target enter, exit data, or update directives."
) ? static_cast<void> (0) : __assert_fail ("(isa<OMPTargetEnterDataDirective>(D) || isa<OMPTargetExitDataDirective>(D) || isa<OMPTargetUpdateDirective>(D)) && \"Expecting either target enter, exit data, or update directives.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10387, __PRETTY_FUNCTION__))
;
10388
10389 CodeGenFunction::OMPTargetDataInfo InputInfo;
10390 llvm::Value *MapTypesArray = nullptr;
10391 // Generate the code for the opening of the data environment.
10392 auto &&ThenGen = [this, &D, Device, &InputInfo,
10393 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
10394 // Emit device ID if any.
10395 llvm::Value *DeviceID = nullptr;
10396 if (Device) {
10397 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10398 CGF.Int64Ty, /*isSigned=*/true);
10399 } else {
10400 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10401 }
10402
10403 // Emit the number of elements in the offloading arrays.
10404 llvm::Constant *PointerNum =
10405 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
10406
10407 llvm::Value *OffloadingArgs[] = {DeviceID,
10408 PointerNum,
10409 InputInfo.BasePointersArray.getPointer(),
10410 InputInfo.PointersArray.getPointer(),
10411 InputInfo.SizesArray.getPointer(),
10412 MapTypesArray,
10413 InputInfo.MappersArray.getPointer()};
10414
10415 // Select the right runtime function call for each standalone
10416 // directive.
10417 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
10418 RuntimeFunction RTLFn;
10419 switch (D.getDirectiveKind()) {
10420 case OMPD_target_enter_data:
10421 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
10422 : OMPRTL___tgt_target_data_begin_mapper;
10423 break;
10424 case OMPD_target_exit_data:
10425 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
10426 : OMPRTL___tgt_target_data_end_mapper;
10427 break;
10428 case OMPD_target_update:
10429 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
10430 : OMPRTL___tgt_target_data_update_mapper;
10431 break;
10432 case OMPD_parallel:
10433 case OMPD_for:
10434 case OMPD_parallel_for:
10435 case OMPD_parallel_master:
10436 case OMPD_parallel_sections:
10437 case OMPD_for_simd:
10438 case OMPD_parallel_for_simd:
10439 case OMPD_cancel:
10440 case OMPD_cancellation_point:
10441 case OMPD_ordered:
10442 case OMPD_threadprivate:
10443 case OMPD_allocate:
10444 case OMPD_task:
10445 case OMPD_simd:
10446 case OMPD_sections:
10447 case OMPD_section:
10448 case OMPD_single:
10449 case OMPD_master:
10450 case OMPD_critical:
10451 case OMPD_taskyield:
10452 case OMPD_barrier:
10453 case OMPD_taskwait:
10454 case OMPD_taskgroup:
10455 case OMPD_atomic:
10456 case OMPD_flush:
10457 case OMPD_depobj:
10458 case OMPD_scan:
10459 case OMPD_teams:
10460 case OMPD_target_data:
10461 case OMPD_distribute:
10462 case OMPD_distribute_simd:
10463 case OMPD_distribute_parallel_for:
10464 case OMPD_distribute_parallel_for_simd:
10465 case OMPD_teams_distribute:
10466 case OMPD_teams_distribute_simd:
10467 case OMPD_teams_distribute_parallel_for:
10468 case OMPD_teams_distribute_parallel_for_simd:
10469 case OMPD_declare_simd:
10470 case OMPD_declare_variant:
10471 case OMPD_begin_declare_variant:
10472 case OMPD_end_declare_variant:
10473 case OMPD_declare_target:
10474 case OMPD_end_declare_target:
10475 case OMPD_declare_reduction:
10476 case OMPD_declare_mapper:
10477 case OMPD_taskloop:
10478 case OMPD_taskloop_simd:
10479 case OMPD_master_taskloop:
10480 case OMPD_master_taskloop_simd:
10481 case OMPD_parallel_master_taskloop:
10482 case OMPD_parallel_master_taskloop_simd:
10483 case OMPD_target:
10484 case OMPD_target_simd:
10485 case OMPD_target_teams_distribute:
10486 case OMPD_target_teams_distribute_simd:
10487 case OMPD_target_teams_distribute_parallel_for:
10488 case OMPD_target_teams_distribute_parallel_for_simd:
10489 case OMPD_target_teams:
10490 case OMPD_target_parallel:
10491 case OMPD_target_parallel_for:
10492 case OMPD_target_parallel_for_simd:
10493 case OMPD_requires:
10494 case OMPD_unknown:
10495 default:
10496 llvm_unreachable("Unexpected standalone target data directive.")::llvm::llvm_unreachable_internal("Unexpected standalone target data directive."
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10496)
;
10497 break;
10498 }
10499 CGF.EmitRuntimeCall(
10500 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), RTLFn),
10501 OffloadingArgs);
10502 };
10503
10504 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10505 CodeGenFunction &CGF, PrePostActionTy &) {
10506 // Fill up the arrays with all the mapped variables.
10507 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10508
10509 // Get map clause information.
10510 MappableExprsHandler MEHandler(D, CGF);
10511 MEHandler.generateAllInfo(CombinedInfo);
10512
10513 TargetDataInfo Info;
10514 // Fill up the arrays and create the arguments.
10515 emitOffloadingArrays(CGF, CombinedInfo, Info);
10516 bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() ||
10517 D.hasClausesOfKind<OMPNowaitClause>();
10518 emitOffloadingArraysArgument(
10519 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray,
10520 Info.MapTypesArray, Info.MappersArray, Info, {/*ForEndTask=*/false});
10521 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10522 InputInfo.BasePointersArray =
10523 Address(Info.BasePointersArray, CGM.getPointerAlign());
10524 InputInfo.PointersArray =
10525 Address(Info.PointersArray, CGM.getPointerAlign());
10526 InputInfo.SizesArray =
10527 Address(Info.SizesArray, CGM.getPointerAlign());
10528 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign());
10529 MapTypesArray = Info.MapTypesArray;
10530 if (RequiresOuterTask)
10531 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10532 else
10533 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
10534 };
10535
10536 if (IfCond) {
10537 emitIfClause(CGF, IfCond, TargetThenGen,
10538 [](CodeGenFunction &CGF, PrePostActionTy &) {});
10539 } else {
10540 RegionCodeGenTy ThenRCG(TargetThenGen);
10541 ThenRCG(CGF);
10542 }
10543}
10544
10545namespace {
10546 /// Kind of parameter in a function with 'declare simd' directive.
10547 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10548 /// Attribute set of the parameter.
10549 struct ParamAttrTy {
10550 ParamKindTy Kind = Vector;
10551 llvm::APSInt StrideOrArg;
10552 llvm::APSInt Alignment;
10553 };
10554} // namespace
10555
10556static unsigned evaluateCDTSize(const FunctionDecl *FD,
10557 ArrayRef<ParamAttrTy> ParamAttrs) {
10558 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10559 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10560 // of that clause. The VLEN value must be power of 2.
10561 // In other case the notion of the function`s "characteristic data type" (CDT)
10562 // is used to compute the vector length.
10563 // CDT is defined in the following order:
10564 // a) For non-void function, the CDT is the return type.
10565 // b) If the function has any non-uniform, non-linear parameters, then the
10566 // CDT is the type of the first such parameter.
10567 // c) If the CDT determined by a) or b) above is struct, union, or class
10568 // type which is pass-by-value (except for the type that maps to the
10569 // built-in complex data type), the characteristic data type is int.
10570 // d) If none of the above three cases is applicable, the CDT is int.
10571 // The VLEN is then determined based on the CDT and the size of vector
10572 // register of that ISA for which current vector version is generated. The
10573 // VLEN is computed using the formula below:
10574 // VLEN = sizeof(vector_register) / sizeof(CDT),
10575 // where vector register size specified in section 3.2.1 Registers and the
10576 // Stack Frame of original AMD64 ABI document.
10577 QualType RetType = FD->getReturnType();
10578 if (RetType.isNull())
10579 return 0;
10580 ASTContext &C = FD->getASTContext();
10581 QualType CDT;
10582 if (!RetType.isNull() && !RetType->isVoidType()) {
10583 CDT = RetType;
10584 } else {
10585 unsigned Offset = 0;
10586 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
10587 if (ParamAttrs[Offset].Kind == Vector)
10588 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10589 ++Offset;
10590 }
10591 if (CDT.isNull()) {
10592 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10593 if (ParamAttrs[I + Offset].Kind == Vector) {
10594 CDT = FD->getParamDecl(I)->getType();
10595 break;
10596 }
10597 }
10598 }
10599 }
10600 if (CDT.isNull())
10601 CDT = C.IntTy;
10602 CDT = CDT->getCanonicalTypeUnqualified();
10603 if (CDT->isRecordType() || CDT->isUnionType())
10604 CDT = C.IntTy;
10605 return C.getTypeSize(CDT);
10606}
10607
10608static void
10609emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
10610 const llvm::APSInt &VLENVal,
10611 ArrayRef<ParamAttrTy> ParamAttrs,
10612 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10613 struct ISADataTy {
10614 char ISA;
10615 unsigned VecRegSize;
10616 };
10617 ISADataTy ISAData[] = {
10618 {
10619 'b', 128
10620 }, // SSE
10621 {
10622 'c', 256
10623 }, // AVX
10624 {
10625 'd', 256
10626 }, // AVX2
10627 {
10628 'e', 512
10629 }, // AVX512
10630 };
10631 llvm::SmallVector<char, 2> Masked;
10632 switch (State) {
10633 case OMPDeclareSimdDeclAttr::BS_Undefined:
10634 Masked.push_back('N');
10635 Masked.push_back('M');
10636 break;
10637 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10638 Masked.push_back('N');
10639 break;
10640 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10641 Masked.push_back('M');
10642 break;
10643 }
10644 for (char Mask : Masked) {
10645 for (const ISADataTy &Data : ISAData) {
10646 SmallString<256> Buffer;
10647 llvm::raw_svector_ostream Out(Buffer);
10648 Out << "_ZGV" << Data.ISA << Mask;
10649 if (!VLENVal) {
10650 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10651 assert(NumElts && "Non-zero simdlen/cdtsize expected")((NumElts && "Non-zero simdlen/cdtsize expected") ? static_cast
<void> (0) : __assert_fail ("NumElts && \"Non-zero simdlen/cdtsize expected\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10651, __PRETTY_FUNCTION__))
;
10652 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
10653 } else {
10654 Out << VLENVal;
10655 }
10656 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
10657 switch (ParamAttr.Kind){
10658 case LinearWithVarStride:
10659 Out << 's' << ParamAttr.StrideOrArg;
10660 break;
10661 case Linear:
10662 Out << 'l';
10663 if (ParamAttr.StrideOrArg != 1)
10664 Out << ParamAttr.StrideOrArg;
10665 break;
10666 case Uniform:
10667 Out << 'u';
10668 break;
10669 case Vector:
10670 Out << 'v';
10671 break;
10672 }
10673 if (!!ParamAttr.Alignment)
10674 Out << 'a' << ParamAttr.Alignment;
10675 }
10676 Out << '_' << Fn->getName();
10677 Fn->addFnAttr(Out.str());
10678 }
10679 }
10680}
10681
10682// This are the Functions that are needed to mangle the name of the
10683// vector functions generated by the compiler, according to the rules
10684// defined in the "Vector Function ABI specifications for AArch64",
10685// available at
10686// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10687
10688/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10689///
10690/// TODO: Need to implement the behavior for reference marked with a
10691/// var or no linear modifiers (1.b in the section). For this, we
10692/// need to extend ParamKindTy to support the linear modifiers.
10693static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10694 QT = QT.getCanonicalType();
10695
10696 if (QT->isVoidType())
10697 return false;
10698
10699 if (Kind == ParamKindTy::Uniform)
10700 return false;
10701
10702 if (Kind == ParamKindTy::Linear)
10703 return false;
10704
10705 // TODO: Handle linear references with modifiers
10706
10707 if (Kind == ParamKindTy::LinearWithVarStride)
10708 return false;
10709
10710 return true;
10711}
10712
10713/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10714static bool getAArch64PBV(QualType QT, ASTContext &C) {
10715 QT = QT.getCanonicalType();
10716 unsigned Size = C.getTypeSize(QT);
10717
10718 // Only scalars and complex within 16 bytes wide set PVB to true.
10719 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10720 return false;
10721
10722 if (QT->isFloatingType())
10723 return true;
10724
10725 if (QT->isIntegerType())
10726 return true;
10727
10728 if (QT->isPointerType())
10729 return true;
10730
10731 // TODO: Add support for complex types (section 3.1.2, item 2).
10732
10733 return false;
10734}
10735
10736/// Computes the lane size (LS) of a return type or of an input parameter,
10737/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10738/// TODO: Add support for references, section 3.2.1, item 1.
10739static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10740 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10741 QualType PTy = QT.getCanonicalType()->getPointeeType();
10742 if (getAArch64PBV(PTy, C))
10743 return C.getTypeSize(PTy);
10744 }
10745 if (getAArch64PBV(QT, C))
10746 return C.getTypeSize(QT);
10747
10748 return C.getTypeSize(C.getUIntPtrType());
10749}
10750
10751// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10752// signature of the scalar function, as defined in 3.2.2 of the
10753// AAVFABI.
10754static std::tuple<unsigned, unsigned, bool>
10755getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10756 QualType RetType = FD->getReturnType().getCanonicalType();
10757
10758 ASTContext &C = FD->getASTContext();
10759
10760 bool OutputBecomesInput = false;
10761
10762 llvm::SmallVector<unsigned, 8> Sizes;
10763 if (!RetType->isVoidType()) {
10764 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10765 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10766 OutputBecomesInput = true;
10767 }
10768 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10769 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10770 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10771 }
10772
10773 assert(!Sizes.empty() && "Unable to determine NDS and WDS.")((!Sizes.empty() && "Unable to determine NDS and WDS."
) ? static_cast<void> (0) : __assert_fail ("!Sizes.empty() && \"Unable to determine NDS and WDS.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10773, __PRETTY_FUNCTION__))
;
10774 // The LS of a function parameter / return value can only be a power
10775 // of 2, starting from 8 bits, up to 128.
10776 assert(std::all_of(Sizes.begin(), Sizes.end(),((std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) {
return Size == 8 || Size == 16 || Size == 32 || Size == 64 ||
Size == 128; }) && "Invalid size") ? static_cast<
void> (0) : __assert_fail ("std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10781, __PRETTY_FUNCTION__))
10777 [](unsigned Size) {((std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) {
return Size == 8 || Size == 16 || Size == 32 || Size == 64 ||
Size == 128; }) && "Invalid size") ? static_cast<
void> (0) : __assert_fail ("std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10781, __PRETTY_FUNCTION__))
10778 return Size == 8 || Size == 16 || Size == 32 ||((std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) {
return Size == 8 || Size == 16 || Size == 32 || Size == 64 ||
Size == 128; }) && "Invalid size") ? static_cast<
void> (0) : __assert_fail ("std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10781, __PRETTY_FUNCTION__))
10779 Size == 64 || Size == 128;((std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) {
return Size == 8 || Size == 16 || Size == 32 || Size == 64 ||
Size == 128; }) && "Invalid size") ? static_cast<
void> (0) : __assert_fail ("std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10781, __PRETTY_FUNCTION__))
10780 }) &&((std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) {
return Size == 8 || Size == 16 || Size == 32 || Size == 64 ||
Size == 128; }) && "Invalid size") ? static_cast<
void> (0) : __assert_fail ("std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10781, __PRETTY_FUNCTION__))
10781 "Invalid size")((std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) {
return Size == 8 || Size == 16 || Size == 32 || Size == 64 ||
Size == 128; }) && "Invalid size") ? static_cast<
void> (0) : __assert_fail ("std::all_of(Sizes.begin(), Sizes.end(), [](unsigned Size) { return Size == 8 || Size == 16 || Size == 32 || Size == 64 || Size == 128; }) && \"Invalid size\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10781, __PRETTY_FUNCTION__))
;
10782
10783 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10784 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10785 OutputBecomesInput);
10786}
10787
10788/// Mangle the parameter part of the vector function name according to
10789/// their OpenMP classification. The mangling function is defined in
10790/// section 3.5 of the AAVFABI.
10791static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10792 SmallString<256> Buffer;
10793 llvm::raw_svector_ostream Out(Buffer);
10794 for (const auto &ParamAttr : ParamAttrs) {
10795 switch (ParamAttr.Kind) {
10796 case LinearWithVarStride:
10797 Out << "ls" << ParamAttr.StrideOrArg;
10798 break;
10799 case Linear:
10800 Out << 'l';
10801 // Don't print the step value if it is not present or if it is
10802 // equal to 1.
10803 if (ParamAttr.StrideOrArg != 1)
10804 Out << ParamAttr.StrideOrArg;
10805 break;
10806 case Uniform:
10807 Out << 'u';
10808 break;
10809 case Vector:
10810 Out << 'v';
10811 break;
10812 }
10813
10814 if (!!ParamAttr.Alignment)
10815 Out << 'a' << ParamAttr.Alignment;
10816 }
10817
10818 return std::string(Out.str());
10819}
10820
10821// Function used to add the attribute. The parameter `VLEN` is
10822// templated to allow the use of "x" when targeting scalable functions
10823// for SVE.
10824template <typename T>
10825static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10826 char ISA, StringRef ParSeq,
10827 StringRef MangledName, bool OutputBecomesInput,
10828 llvm::Function *Fn) {
10829 SmallString<256> Buffer;
10830 llvm::raw_svector_ostream Out(Buffer);
10831 Out << Prefix << ISA << LMask << VLEN;
10832 if (OutputBecomesInput)
10833 Out << "v";
10834 Out << ParSeq << "_" << MangledName;
10835 Fn->addFnAttr(Out.str());
10836}
10837
10838// Helper function to generate the Advanced SIMD names depending on
10839// the value of the NDS when simdlen is not present.
10840static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10841 StringRef Prefix, char ISA,
10842 StringRef ParSeq, StringRef MangledName,
10843 bool OutputBecomesInput,
10844 llvm::Function *Fn) {
10845 switch (NDS) {
10846 case 8:
10847 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10848 OutputBecomesInput, Fn);
10849 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10850 OutputBecomesInput, Fn);
10851 break;
10852 case 16:
10853 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10854 OutputBecomesInput, Fn);
10855 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10856 OutputBecomesInput, Fn);
10857 break;
10858 case 32:
10859 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10860 OutputBecomesInput, Fn);
10861 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10862 OutputBecomesInput, Fn);
10863 break;
10864 case 64:
10865 case 128:
10866 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10867 OutputBecomesInput, Fn);
10868 break;
10869 default:
10870 llvm_unreachable("Scalar type is too wide.")::llvm::llvm_unreachable_internal("Scalar type is too wide.",
"/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10870)
;
10871 }
10872}
10873
10874/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10875static void emitAArch64DeclareSimdFunction(
10876 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10877 ArrayRef<ParamAttrTy> ParamAttrs,
10878 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10879 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10880
10881 // Get basic data for building the vector signature.
10882 const auto Data = getNDSWDS(FD, ParamAttrs);
10883 const unsigned NDS = std::get<0>(Data);
10884 const unsigned WDS = std::get<1>(Data);
10885 const bool OutputBecomesInput = std::get<2>(Data);
10886
10887 // Check the values provided via `simdlen` by the user.
10888 // 1. A `simdlen(1)` doesn't produce vector signatures,
10889 if (UserVLEN == 1) {
10890 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10891 DiagnosticsEngine::Warning,
10892 "The clause simdlen(1) has no effect when targeting aarch64.");
10893 CGM.getDiags().Report(SLoc, DiagID);
10894 return;
10895 }
10896
10897 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10898 // Advanced SIMD output.
10899 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10900 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10901 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10902 "power of 2 when targeting Advanced SIMD.");
10903 CGM.getDiags().Report(SLoc, DiagID);
10904 return;
10905 }
10906
10907 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10908 // limits.
10909 if (ISA == 's' && UserVLEN != 0) {
10910 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10911 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10912 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10913 "lanes in the architectural constraints "
10914 "for SVE (min is 128-bit, max is "
10915 "2048-bit, by steps of 128-bit)");
10916 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10917 return;
10918 }
10919 }
10920
10921 // Sort out parameter sequence.
10922 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10923 StringRef Prefix = "_ZGV";
10924 // Generate simdlen from user input (if any).
10925 if (UserVLEN) {
10926 if (ISA == 's') {
10927 // SVE generates only a masked function.
10928 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10929 OutputBecomesInput, Fn);
10930 } else {
10931 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.")((ISA == 'n' && "Expected ISA either 's' or 'n'.") ? static_cast
<void> (0) : __assert_fail ("ISA == 'n' && \"Expected ISA either 's' or 'n'.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10931, __PRETTY_FUNCTION__))
;
10932 // Advanced SIMD generates one or two functions, depending on
10933 // the `[not]inbranch` clause.
10934 switch (State) {
10935 case OMPDeclareSimdDeclAttr::BS_Undefined:
10936 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10937 OutputBecomesInput, Fn);
10938 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10939 OutputBecomesInput, Fn);
10940 break;
10941 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10942 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10943 OutputBecomesInput, Fn);
10944 break;
10945 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10946 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10947 OutputBecomesInput, Fn);
10948 break;
10949 }
10950 }
10951 } else {
10952 // If no user simdlen is provided, follow the AAVFABI rules for
10953 // generating the vector length.
10954 if (ISA == 's') {
10955 // SVE, section 3.4.1, item 1.
10956 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10957 OutputBecomesInput, Fn);
10958 } else {
10959 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.")((ISA == 'n' && "Expected ISA either 's' or 'n'.") ? static_cast
<void> (0) : __assert_fail ("ISA == 'n' && \"Expected ISA either 's' or 'n'.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10959, __PRETTY_FUNCTION__))
;
10960 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10961 // two vector names depending on the use of the clause
10962 // `[not]inbranch`.
10963 switch (State) {
10964 case OMPDeclareSimdDeclAttr::BS_Undefined:
10965 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10966 OutputBecomesInput, Fn);
10967 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10968 OutputBecomesInput, Fn);
10969 break;
10970 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10971 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10972 OutputBecomesInput, Fn);
10973 break;
10974 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10975 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10976 OutputBecomesInput, Fn);
10977 break;
10978 }
10979 }
10980 }
10981}
10982
10983void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10984 llvm::Function *Fn) {
10985 ASTContext &C = CGM.getContext();
10986 FD = FD->getMostRecentDecl();
10987 // Map params to their positions in function decl.
10988 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10989 if (isa<CXXMethodDecl>(FD))
10990 ParamPositions.try_emplace(FD, 0);
10991 unsigned ParamPos = ParamPositions.size();
10992 for (const ParmVarDecl *P : FD->parameters()) {
10993 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
10994 ++ParamPos;
10995 }
10996 while (FD) {
10997 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
10998 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10999 // Mark uniform parameters.
11000 for (const Expr *E : Attr->uniforms()) {
11001 E = E->IgnoreParenImpCasts();
11002 unsigned Pos;
11003 if (isa<CXXThisExpr>(E)) {
11004 Pos = ParamPositions[FD];
11005 } else {
11006 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
11007 ->getCanonicalDecl();
11008 Pos = ParamPositions[PVD];
11009 }
11010 ParamAttrs[Pos].Kind = Uniform;
11011 }
11012 // Get alignment info.
11013 auto NI = Attr->alignments_begin();
11014 for (const Expr *E : Attr->aligneds()) {
11015 E = E->IgnoreParenImpCasts();
11016 unsigned Pos;
11017 QualType ParmTy;
11018 if (isa<CXXThisExpr>(E)) {
11019 Pos = ParamPositions[FD];
11020 ParmTy = E->getType();
11021 } else {
11022 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
11023 ->getCanonicalDecl();
11024 Pos = ParamPositions[PVD];
11025 ParmTy = PVD->getType();
11026 }
11027 ParamAttrs[Pos].Alignment =
11028 (*NI)
11029 ? (*NI)->EvaluateKnownConstInt(C)
11030 : llvm::APSInt::getUnsigned(
11031 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
11032 .getQuantity());
11033 ++NI;
11034 }
11035 // Mark linear parameters.
11036 auto SI = Attr->steps_begin();
11037 auto MI = Attr->modifiers_begin();
11038 for (const Expr *E : Attr->linears()) {
11039 E = E->IgnoreParenImpCasts();
11040 unsigned Pos;
11041 // Rescaling factor needed to compute the linear parameter
11042 // value in the mangled name.
11043 unsigned PtrRescalingFactor = 1;
11044 if (isa<CXXThisExpr>(E)) {
11045 Pos = ParamPositions[FD];
11046 } else {
11047 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
11048 ->getCanonicalDecl();
11049 Pos = ParamPositions[PVD];
11050 if (auto *P = dyn_cast<PointerType>(PVD->getType()))
11051 PtrRescalingFactor = CGM.getContext()
11052 .getTypeSizeInChars(P->getPointeeType())
11053 .getQuantity();
11054 }
11055 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
11056 ParamAttr.Kind = Linear;
11057 // Assuming a stride of 1, for `linear` without modifiers.
11058 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
11059 if (*SI) {
11060 Expr::EvalResult Result;
11061 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
11062 if (const auto *DRE =
11063 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
11064 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
11065 ParamAttr.Kind = LinearWithVarStride;
11066 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
11067 ParamPositions[StridePVD->getCanonicalDecl()]);
11068 }
11069 }
11070 } else {
11071 ParamAttr.StrideOrArg = Result.Val.getInt();
11072 }
11073 }
11074 // If we are using a linear clause on a pointer, we need to
11075 // rescale the value of linear_step with the byte size of the
11076 // pointee type.
11077 if (Linear == ParamAttr.Kind)
11078 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
11079 ++SI;
11080 ++MI;
11081 }
11082 llvm::APSInt VLENVal;
11083 SourceLocation ExprLoc;
11084 const Expr *VLENExpr = Attr->getSimdlen();
11085 if (VLENExpr) {
11086 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
11087 ExprLoc = VLENExpr->getExprLoc();
11088 }
11089 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
11090 if (CGM.getTriple().isX86()) {
11091 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
11092 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
11093 unsigned VLEN = VLENVal.getExtValue();
11094 StringRef MangledName = Fn->getName();
11095 if (CGM.getTarget().hasFeature("sve"))
11096 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
11097 MangledName, 's', 128, Fn, ExprLoc);
11098 if (CGM.getTarget().hasFeature("neon"))
11099 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
11100 MangledName, 'n', 128, Fn, ExprLoc);
11101 }
11102 }
11103 FD = FD->getPreviousDecl();
11104 }
11105}
11106
11107namespace {
11108/// Cleanup action for doacross support.
11109class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
11110public:
11111 static const int DoacrossFinArgs = 2;
11112
11113private:
11114 llvm::FunctionCallee RTLFn;
11115 llvm::Value *Args[DoacrossFinArgs];
11116
11117public:
11118 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
11119 ArrayRef<llvm::Value *> CallArgs)
11120 : RTLFn(RTLFn) {
11121 assert(CallArgs.size() == DoacrossFinArgs)((CallArgs.size() == DoacrossFinArgs) ? static_cast<void>
(0) : __assert_fail ("CallArgs.size() == DoacrossFinArgs", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11121, __PRETTY_FUNCTION__))
;
11122 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11123 }
11124 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
11125 if (!CGF.HaveInsertPoint())
11126 return;
11127 CGF.EmitRuntimeCall(RTLFn, Args);
11128 }
11129};
11130} // namespace
11131
11132void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
11133 const OMPLoopDirective &D,
11134 ArrayRef<Expr *> NumIterations) {
11135 if (!CGF.HaveInsertPoint())
11136 return;
11137
11138 ASTContext &C = CGM.getContext();
11139 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
11140 RecordDecl *RD;
11141 if (KmpDimTy.isNull()) {
11142 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
11143 // kmp_int64 lo; // lower
11144 // kmp_int64 up; // upper
11145 // kmp_int64 st; // stride
11146 // };
11147 RD = C.buildImplicitRecord("kmp_dim");
11148 RD->startDefinition();
11149 addFieldToRecordDecl(C, RD, Int64Ty);
11150 addFieldToRecordDecl(C, RD, Int64Ty);
11151 addFieldToRecordDecl(C, RD, Int64Ty);
11152 RD->completeDefinition();
11153 KmpDimTy = C.getRecordType(RD);
11154 } else {
11155 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
11156 }
11157 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
11158 QualType ArrayTy =
11159 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
11160
11161 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
11162 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
11163 enum { LowerFD = 0, UpperFD, StrideFD };
11164 // Fill dims with data.
11165 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
11166 LValue DimsLVal = CGF.MakeAddrLValue(
11167 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
11168 // dims.upper = num_iterations;
11169 LValue UpperLVal = CGF.EmitLValueForField(
11170 DimsLVal, *std::next(RD->field_begin(), UpperFD));
11171 llvm::Value *NumIterVal = CGF.EmitScalarConversion(
11172 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
11173 Int64Ty, NumIterations[I]->getExprLoc());
11174 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
11175 // dims.stride = 1;
11176 LValue StrideLVal = CGF.EmitLValueForField(
11177 DimsLVal, *std::next(RD->field_begin(), StrideFD));
11178 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
11179 StrideLVal);
11180 }
11181
11182 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
11183 // kmp_int32 num_dims, struct kmp_dim * dims);
11184 llvm::Value *Args[] = {
11185 emitUpdateLocation(CGF, D.getBeginLoc()),
11186 getThreadID(CGF, D.getBeginLoc()),
11187 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
11188 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11189 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
11190 CGM.VoidPtrTy)};
11191
11192 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction(
11193 CGM.getModule(), OMPRTL___kmpc_doacross_init);
11194 CGF.EmitRuntimeCall(RTLFn, Args);
11195 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
11196 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
11197 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction(
11198 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
11199 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11200 llvm::makeArrayRef(FiniArgs));
11201}
11202
11203void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11204 const OMPDependClause *C) {
11205 QualType Int64Ty =
11206 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
11207 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
11208 QualType ArrayTy = CGM.getContext().getConstantArrayType(
11209 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
11210 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
11211 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
11212 const Expr *CounterVal = C->getLoopData(I);
11213 assert(CounterVal)((CounterVal) ? static_cast<void> (0) : __assert_fail (
"CounterVal", "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11213, __PRETTY_FUNCTION__))
;
11214 llvm::Value *CntVal = CGF.EmitScalarConversion(
11215 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
11216 CounterVal->getExprLoc());
11217 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
11218 /*Volatile=*/false, Int64Ty);
11219 }
11220 llvm::Value *Args[] = {
11221 emitUpdateLocation(CGF, C->getBeginLoc()),
11222 getThreadID(CGF, C->getBeginLoc()),
11223 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
11224 llvm::FunctionCallee RTLFn;
11225 if (C->getDependencyKind() == OMPC_DEPEND_source) {
11226 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
11227 OMPRTL___kmpc_doacross_post);
11228 } else {
11229 assert(C->getDependencyKind() == OMPC_DEPEND_sink)((C->getDependencyKind() == OMPC_DEPEND_sink) ? static_cast
<void> (0) : __assert_fail ("C->getDependencyKind() == OMPC_DEPEND_sink"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11229, __PRETTY_FUNCTION__))
;
11230 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
11231 OMPRTL___kmpc_doacross_wait);
11232 }
11233 CGF.EmitRuntimeCall(RTLFn, Args);
11234}
11235
11236void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
11237 llvm::FunctionCallee Callee,
11238 ArrayRef<llvm::Value *> Args) const {
11239 assert(Loc.isValid() && "Outlined function call location must be valid.")((Loc.isValid() && "Outlined function call location must be valid."
) ? static_cast<void> (0) : __assert_fail ("Loc.isValid() && \"Outlined function call location must be valid.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11239, __PRETTY_FUNCTION__))
;
11240 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
11241
11242 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
11243 if (Fn->doesNotThrow()) {
11244 CGF.EmitNounwindRuntimeCall(Fn, Args);
11245 return;
11246 }
11247 }
11248 CGF.EmitRuntimeCall(Callee, Args);
11249}
11250
11251void CGOpenMPRuntime::emitOutlinedFunctionCall(
11252 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
11253 ArrayRef<llvm::Value *> Args) const {
11254 emitCall(CGF, Loc, OutlinedFn, Args);
11255}
11256
11257void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
11258 if (const auto *FD = dyn_cast<FunctionDecl>(D))
11259 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
11260 HasEmittedDeclareTargetRegion = true;
11261}
11262
11263Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
11264 const VarDecl *NativeParam,
11265 const VarDecl *TargetParam) const {
11266 return CGF.GetAddrOfLocalVar(NativeParam);
11267}
11268
11269Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
11270 const VarDecl *VD) {
11271 if (!VD)
11272 return Address::invalid();
11273 Address UntiedAddr = Address::invalid();
11274 Address UntiedRealAddr = Address::invalid();
11275 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn);
11276 if (It != FunctionToUntiedTaskStackMap.end()) {
11277 const UntiedLocalVarsAddressesMap &UntiedData =
11278 UntiedLocalVarsStack[It->second];
11279 auto I = UntiedData.find(VD);
11280 if (I != UntiedData.end()) {
11281 UntiedAddr = I->second.first;
11282 UntiedRealAddr = I->second.second;
11283 }
11284 }
11285 const VarDecl *CVD = VD->getCanonicalDecl();
11286 if (CVD->hasAttr<OMPAllocateDeclAttr>()) {
11287 // Use the default allocation.
11288 if (!isAllocatableDecl(VD))
11289 return UntiedAddr;
11290 llvm::Value *Size;
11291 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
11292 if (CVD->getType()->isVariablyModifiedType()) {
11293 Size = CGF.getTypeSize(CVD->getType());
11294 // Align the size: ((size + align - 1) / align) * align
11295 Size = CGF.Builder.CreateNUWAdd(
11296 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
11297 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
11298 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
11299 } else {
11300 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
11301 Size = CGM.getSize(Sz.alignTo(Align));
11302 }
11303 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11304 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
11305 assert(AA->getAllocator() &&((AA->getAllocator() && "Expected allocator expression for non-default allocator."
) ? static_cast<void> (0) : __assert_fail ("AA->getAllocator() && \"Expected allocator expression for non-default allocator.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11306, __PRETTY_FUNCTION__))
11306 "Expected allocator expression for non-default allocator.")((AA->getAllocator() && "Expected allocator expression for non-default allocator."
) ? static_cast<void> (0) : __assert_fail ("AA->getAllocator() && \"Expected allocator expression for non-default allocator.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11306, __PRETTY_FUNCTION__))
;
11307 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
11308 // According to the standard, the original allocator type is a enum
11309 // (integer). Convert to pointer type, if required.
11310 Allocator = CGF.EmitScalarConversion(
11311 Allocator, AA->getAllocator()->getType(), CGF.getContext().VoidPtrTy,
11312 AA->getAllocator()->getExprLoc());
11313 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11314
11315 llvm::Value *Addr =
11316 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
11317 CGM.getModule(), OMPRTL___kmpc_alloc),
11318 Args, getName({CVD->getName(), ".void.addr"}));
11319 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction(
11320 CGM.getModule(), OMPRTL___kmpc_free);
11321 QualType Ty = CGM.getContext().getPointerType(CVD->getType());
11322 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11323 Addr, CGF.ConvertTypeForMem(Ty), getName({CVD->getName(), ".addr"}));
11324 if (UntiedAddr.isValid())
11325 CGF.EmitStoreOfScalar(Addr, UntiedAddr, /*Volatile=*/false, Ty);
11326
11327 // Cleanup action for allocate support.
11328 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
11329 llvm::FunctionCallee RTLFn;
11330 unsigned LocEncoding;
11331 Address Addr;
11332 const Expr *Allocator;
11333
11334 public:
11335 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, unsigned LocEncoding,
11336 Address Addr, const Expr *Allocator)
11337 : RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr),
11338 Allocator(Allocator) {}
11339 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
11340 if (!CGF.HaveInsertPoint())
11341 return;
11342 llvm::Value *Args[3];
11343 Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID(
11344 CGF, SourceLocation::getFromRawEncoding(LocEncoding));
11345 Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11346 Addr.getPointer(), CGF.VoidPtrTy);
11347 llvm::Value *AllocVal = CGF.EmitScalarExpr(Allocator);
11348 // According to the standard, the original allocator type is a enum
11349 // (integer). Convert to pointer type, if required.
11350 AllocVal = CGF.EmitScalarConversion(AllocVal, Allocator->getType(),
11351 CGF.getContext().VoidPtrTy,
11352 Allocator->getExprLoc());
11353 Args[2] = AllocVal;
11354
11355 CGF.EmitRuntimeCall(RTLFn, Args);
11356 }
11357 };
11358 Address VDAddr =
11359 UntiedRealAddr.isValid() ? UntiedRealAddr : Address(Addr, Align);
11360 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(
11361 NormalAndEHCleanup, FiniRTLFn, CVD->getLocation().getRawEncoding(),
11362 VDAddr, AA->getAllocator());
11363 if (UntiedRealAddr.isValid())
11364 if (auto *Region =
11365 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
11366 Region->emitUntiedSwitch(CGF);
11367 return VDAddr;
11368 }
11369 return UntiedAddr;
11370}
11371
11372bool CGOpenMPRuntime::isLocalVarInUntiedTask(CodeGenFunction &CGF,
11373 const VarDecl *VD) const {
11374 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn);
11375 if (It == FunctionToUntiedTaskStackMap.end())
11376 return false;
11377 return UntiedLocalVarsStack[It->second].count(VD) > 0;
11378}
11379
11380CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII(
11381 CodeGenModule &CGM, const OMPLoopDirective &S)
11382 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) {
11383 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.")((CGM.getLangOpts().OpenMP && "Not in OpenMP mode.") ?
static_cast<void> (0) : __assert_fail ("CGM.getLangOpts().OpenMP && \"Not in OpenMP mode.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11383, __PRETTY_FUNCTION__))
;
11384 if (!NeedToPush)
11385 return;
11386 NontemporalDeclsSet &DS =
11387 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
11388 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) {
11389 for (const Stmt *Ref : C->private_refs()) {
11390 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts();
11391 const ValueDecl *VD;
11392 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
11393 VD = DRE->getDecl();
11394 } else {
11395 const auto *ME = cast<MemberExpr>(SimpleRefExpr);
11396 assert((ME->isImplicitCXXThis() ||(((ME->isImplicitCXXThis() || isa<CXXThisExpr>(ME->
getBase()->IgnoreParenImpCasts())) && "Expected member of current class."
) ? static_cast<void> (0) : __assert_fail ("(ME->isImplicitCXXThis() || isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && \"Expected member of current class.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11398, __PRETTY_FUNCTION__))
11397 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) &&(((ME->isImplicitCXXThis() || isa<CXXThisExpr>(ME->
getBase()->IgnoreParenImpCasts())) && "Expected member of current class."
) ? static_cast<void> (0) : __assert_fail ("(ME->isImplicitCXXThis() || isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && \"Expected member of current class.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11398, __PRETTY_FUNCTION__))
11398 "Expected member of current class.")(((ME->isImplicitCXXThis() || isa<CXXThisExpr>(ME->
getBase()->IgnoreParenImpCasts())) && "Expected member of current class."
) ? static_cast<void> (0) : __assert_fail ("(ME->isImplicitCXXThis() || isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && \"Expected member of current class.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11398, __PRETTY_FUNCTION__))
;
11399 VD = ME->getMemberDecl();
11400 }
11401 DS.insert(VD);
11402 }
11403 }
11404}
11405
11406CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() {
11407 if (!NeedToPush)
11408 return;
11409 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
11410}
11411
11412CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII(
11413 CodeGenFunction &CGF,
11414 const llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
11415 std::pair<Address, Address>> &LocalVars)
11416 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
11417 if (!NeedToPush)
11418 return;
11419 CGM.getOpenMPRuntime().FunctionToUntiedTaskStackMap.try_emplace(
11420 CGF.CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
11421 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
11422}
11423
11424CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::~UntiedTaskLocalDeclsRAII() {
11425 if (!NeedToPush)
11426 return;
11427 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
11428}
11429
11430bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const {
11431 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.")((CGM.getLangOpts().OpenMP && "Not in OpenMP mode.") ?
static_cast<void> (0) : __assert_fail ("CGM.getLangOpts().OpenMP && \"Not in OpenMP mode.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11431, __PRETTY_FUNCTION__))
;
11432
11433 return llvm::any_of(
11434 CGM.getOpenMPRuntime().NontemporalDeclsStack,
11435 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; });
11436}
11437
11438void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
11439 const OMPExecutableDirective &S,
11440 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled)
11441 const {
11442 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
11443 // Vars in target/task regions must be excluded completely.
11444 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) ||
11445 isOpenMPTaskingDirective(S.getDirectiveKind())) {
11446 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
11447 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind());
11448 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
11449 for (const CapturedStmt::Capture &Cap : CS->captures()) {
11450 if (Cap.capturesVariable() || Cap.capturesVariableByCopy())
11451 NeedToCheckForLPCs.insert(Cap.getCapturedVar());
11452 }
11453 }
11454 // Exclude vars in private clauses.
11455 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
11456 for (const Expr *Ref : C->varlists()) {
11457 if (!Ref->getType()->isScalarType())
11458 continue;
11459 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11460 if (!DRE)
11461 continue;
11462 NeedToCheckForLPCs.insert(DRE->getDecl());
11463 }
11464 }
11465 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
11466 for (const Expr *Ref : C->varlists()) {
11467 if (!Ref->getType()->isScalarType())
11468 continue;
11469 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11470 if (!DRE)
11471 continue;
11472 NeedToCheckForLPCs.insert(DRE->getDecl());
11473 }
11474 }
11475 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
11476 for (const Expr *Ref : C->varlists()) {
11477 if (!Ref->getType()->isScalarType())
11478 continue;
11479 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11480 if (!DRE)
11481 continue;
11482 NeedToCheckForLPCs.insert(DRE->getDecl());
11483 }
11484 }
11485 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
11486 for (const Expr *Ref : C->varlists()) {
11487 if (!Ref->getType()->isScalarType())
11488 continue;
11489 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11490 if (!DRE)
11491 continue;
11492 NeedToCheckForLPCs.insert(DRE->getDecl());
11493 }
11494 }
11495 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
11496 for (const Expr *Ref : C->varlists()) {
11497 if (!Ref->getType()->isScalarType())
11498 continue;
11499 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11500 if (!DRE)
11501 continue;
11502 NeedToCheckForLPCs.insert(DRE->getDecl());
11503 }
11504 }
11505 for (const Decl *VD : NeedToCheckForLPCs) {
11506 for (const LastprivateConditionalData &Data :
11507 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
11508 if (Data.DeclToUniqueName.count(VD) > 0) {
11509 if (!Data.Disabled)
11510 NeedToAddForLPCsAsDisabled.insert(VD);
11511 break;
11512 }
11513 }
11514 }
11515}
11516
11517CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11518 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal)
11519 : CGM(CGF.CGM),
11520 Action((CGM.getLangOpts().OpenMP >= 50 &&
11521 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
11522 [](const OMPLastprivateClause *C) {
11523 return C->getKind() ==
11524 OMPC_LASTPRIVATE_conditional;
11525 }))
11526 ? ActionToDo::PushAsLastprivateConditional
11527 : ActionToDo::DoNotPush) {
11528 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.")((CGM.getLangOpts().OpenMP && "Not in OpenMP mode.") ?
static_cast<void> (0) : __assert_fail ("CGM.getLangOpts().OpenMP && \"Not in OpenMP mode.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11528, __PRETTY_FUNCTION__))
;
11529 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
11530 return;
11531 assert(Action == ActionToDo::PushAsLastprivateConditional &&((Action == ActionToDo::PushAsLastprivateConditional &&
"Expected a push action.") ? static_cast<void> (0) : __assert_fail
("Action == ActionToDo::PushAsLastprivateConditional && \"Expected a push action.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11532, __PRETTY_FUNCTION__))
11532 "Expected a push action.")((Action == ActionToDo::PushAsLastprivateConditional &&
"Expected a push action.") ? static_cast<void> (0) : __assert_fail
("Action == ActionToDo::PushAsLastprivateConditional && \"Expected a push action.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11532, __PRETTY_FUNCTION__))
;
11533 LastprivateConditionalData &Data =
11534 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
11535 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
11536 if (C->getKind() != OMPC_LASTPRIVATE_conditional)
11537 continue;
11538
11539 for (const Expr *Ref : C->varlists()) {
11540 Data.DeclToUniqueName.insert(std::make_pair(
11541 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(),
11542 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref))));
11543 }
11544 }
11545 Data.IVLVal = IVLVal;
11546 Data.Fn = CGF.CurFn;
11547}
11548
11549CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11550 CodeGenFunction &CGF, const OMPExecutableDirective &S)
11551 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) {
11552 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.")((CGM.getLangOpts().OpenMP && "Not in OpenMP mode.") ?
static_cast<void> (0) : __assert_fail ("CGM.getLangOpts().OpenMP && \"Not in OpenMP mode.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11552, __PRETTY_FUNCTION__))
;
11553 if (CGM.getLangOpts().OpenMP < 50)
11554 return;
11555 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
11556 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
11557 if (!NeedToAddForLPCsAsDisabled.empty()) {
11558 Action = ActionToDo::DisableLastprivateConditional;
11559 LastprivateConditionalData &Data =
11560 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
11561 for (const Decl *VD : NeedToAddForLPCsAsDisabled)
11562 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>()));
11563 Data.Fn = CGF.CurFn;
11564 Data.Disabled = true;
11565 }
11566}
11567
11568CGOpenMPRuntime::LastprivateConditionalRAII
11569CGOpenMPRuntime::LastprivateConditionalRAII::disable(
11570 CodeGenFunction &CGF, const OMPExecutableDirective &S) {
11571 return LastprivateConditionalRAII(CGF, S);
11572}
11573
11574CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() {
11575 if (CGM.getLangOpts().OpenMP < 50)
11576 return;
11577 if (Action == ActionToDo::DisableLastprivateConditional) {
11578 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&((CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled
&& "Expected list of disabled private vars.") ? static_cast
<void> (0) : __assert_fail ("CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && \"Expected list of disabled private vars.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11579, __PRETTY_FUNCTION__))
11579 "Expected list of disabled private vars.")((CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled
&& "Expected list of disabled private vars.") ? static_cast
<void> (0) : __assert_fail ("CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && \"Expected list of disabled private vars.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11579, __PRETTY_FUNCTION__))
;
11580 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
11581 }
11582 if (Action == ActionToDo::PushAsLastprivateConditional) {
11583 assert(((!CGM.getOpenMPRuntime().LastprivateConditionalStack.back().
Disabled && "Expected list of lastprivate conditional vars."
) ? static_cast<void> (0) : __assert_fail ("!CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && \"Expected list of lastprivate conditional vars.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11585, __PRETTY_FUNCTION__))
11584 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&((!CGM.getOpenMPRuntime().LastprivateConditionalStack.back().
Disabled && "Expected list of lastprivate conditional vars."
) ? static_cast<void> (0) : __assert_fail ("!CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && \"Expected list of lastprivate conditional vars.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11585, __PRETTY_FUNCTION__))
11585 "Expected list of lastprivate conditional vars.")((!CGM.getOpenMPRuntime().LastprivateConditionalStack.back().
Disabled && "Expected list of lastprivate conditional vars."
) ? static_cast<void> (0) : __assert_fail ("!CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && \"Expected list of lastprivate conditional vars.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11585, __PRETTY_FUNCTION__))
;
11586 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
11587 }
11588}
11589
11590Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF,
11591 const VarDecl *VD) {
11592 ASTContext &C = CGM.getContext();
11593 auto I = LastprivateConditionalToTypes.find(CGF.CurFn);
11594 if (I == LastprivateConditionalToTypes.end())
11595 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first;
11596 QualType NewType;
11597 const FieldDecl *VDField;
11598 const FieldDecl *FiredField;
11599 LValue BaseLVal;
11600 auto VI = I->getSecond().find(VD);
11601 if (VI == I->getSecond().end()) {
11602 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional");
11603 RD->startDefinition();
11604 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType());
11605 FiredField = addFieldToRecordDecl(C, RD, C.CharTy);
11606 RD->completeDefinition();
11607 NewType = C.getRecordType(RD);
11608 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName());
11609 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl);
11610 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
11611 } else {
11612 NewType = std::get<0>(VI->getSecond());
11613 VDField = std::get<1>(VI->getSecond());
11614 FiredField = std::get<2>(VI->getSecond());
11615 BaseLVal = std::get<3>(VI->getSecond());
11616 }
11617 LValue FiredLVal =
11618 CGF.EmitLValueForField(BaseLVal, FiredField);
11619 CGF.EmitStoreOfScalar(
11620 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)),
11621 FiredLVal);
11622 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF);
11623}
11624
11625namespace {
11626/// Checks if the lastprivate conditional variable is referenced in LHS.
11627class LastprivateConditionalRefChecker final
11628 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> {
11629 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM;
11630 const Expr *FoundE = nullptr;
11631 const Decl *FoundD = nullptr;
11632 StringRef UniqueDeclName;
11633 LValue IVLVal;
11634 llvm::Function *FoundFn = nullptr;
11635 SourceLocation Loc;
11636
11637public:
11638 bool VisitDeclRefExpr(const DeclRefExpr *E) {
11639 for (const CGOpenMPRuntime::LastprivateConditionalData &D :
11640 llvm::reverse(LPM)) {
11641 auto It = D.DeclToUniqueName.find(E->getDecl());
11642 if (It == D.DeclToUniqueName.end())
11643 continue;
11644 if (D.Disabled)
11645 return false;
11646 FoundE = E;
11647 FoundD = E->getDecl()->getCanonicalDecl();
11648 UniqueDeclName = It->second;
11649 IVLVal = D.IVLVal;
11650 FoundFn = D.Fn;
11651 break;
11652 }
11653 return FoundE == E;
11654 }
11655 bool VisitMemberExpr(const MemberExpr *E) {
11656 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase()))
11657 return false;
11658 for (const CGOpenMPRuntime::LastprivateConditionalData &D :
11659 llvm::reverse(LPM)) {
11660 auto It = D.DeclToUniqueName.find(E->getMemberDecl());
11661 if (It == D.DeclToUniqueName.end())
11662 continue;
11663 if (D.Disabled)
11664 return false;
11665 FoundE = E;
11666 FoundD = E->getMemberDecl()->getCanonicalDecl();
11667 UniqueDeclName = It->second;
11668 IVLVal = D.IVLVal;
11669 FoundFn = D.Fn;
11670 break;
11671 }
11672 return FoundE == E;
11673 }
11674 bool VisitStmt(const Stmt *S) {
11675 for (const Stmt *Child : S->children()) {
11676 if (!Child)
11677 continue;
11678 if (const auto *E = dyn_cast<Expr>(Child))
11679 if (!E->isGLValue())
11680 continue;
11681 if (Visit(Child))
11682 return true;
11683 }
11684 return false;
11685 }
11686 explicit LastprivateConditionalRefChecker(
11687 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
11688 : LPM(LPM) {}
11689 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
11690 getFoundData() const {
11691 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
11692 }
11693};
11694} // namespace
11695
11696void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF,
11697 LValue IVLVal,
11698 StringRef UniqueDeclName,
11699 LValue LVal,
11700 SourceLocation Loc) {
11701 // Last updated loop counter for the lastprivate conditional var.
11702 // int<xx> last_iv = 0;
11703 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType());
11704 llvm::Constant *LastIV =
11705 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"}));
11706 cast<llvm::GlobalVariable>(LastIV)->setAlignment(
11707 IVLVal.getAlignment().getAsAlign());
11708 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType());
11709
11710 // Last value of the lastprivate conditional.
11711 // decltype(priv_a) last_a;
11712 llvm::Constant *Last = getOrCreateInternalVariable(
11713 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName);
11714 cast<llvm::GlobalVariable>(Last)->setAlignment(
11715 LVal.getAlignment().getAsAlign());
11716 LValue LastLVal =
11717 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment());
11718
11719 // Global loop counter. Required to handle inner parallel-for regions.
11720 // iv
11721 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc);
11722
11723 // #pragma omp critical(a)
11724 // if (last_iv <= iv) {
11725 // last_iv = iv;
11726 // last_a = priv_a;
11727 // }
11728 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
11729 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
11730 Action.Enter(CGF);
11731 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc);
11732 // (last_iv <= iv) ? Check if the variable is updated and store new
11733 // value in global var.
11734 llvm::Value *CmpRes;
11735 if (IVLVal.getType()->isSignedIntegerType()) {
11736 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal);
11737 } else {
11738 assert(IVLVal.getType()->isUnsignedIntegerType() &&((IVLVal.getType()->isUnsignedIntegerType() && "Loop iteration variable must be integer."
) ? static_cast<void> (0) : __assert_fail ("IVLVal.getType()->isUnsignedIntegerType() && \"Loop iteration variable must be integer.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11739, __PRETTY_FUNCTION__))
11739 "Loop iteration variable must be integer.")((IVLVal.getType()->isUnsignedIntegerType() && "Loop iteration variable must be integer."
) ? static_cast<void> (0) : __assert_fail ("IVLVal.getType()->isUnsignedIntegerType() && \"Loop iteration variable must be integer.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11739, __PRETTY_FUNCTION__))
;
11740 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal);
11741 }
11742 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then");
11743 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit");
11744 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
11745 // {
11746 CGF.EmitBlock(ThenBB);
11747
11748 // last_iv = iv;
11749 CGF.EmitStoreOfScalar(IVVal, LastIVLVal);
11750
11751 // last_a = priv_a;
11752 switch (CGF.getEvaluationKind(LVal.getType())) {
11753 case TEK_Scalar: {
11754 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc);
11755 CGF.EmitStoreOfScalar(PrivVal, LastLVal);
11756 break;
11757 }
11758 case TEK_Complex: {
11759 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc);
11760 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false);
11761 break;
11762 }
11763 case TEK_Aggregate:
11764 llvm_unreachable(::llvm::llvm_unreachable_internal("Aggregates are not supported in lastprivate conditional."
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11765)
11765 "Aggregates are not supported in lastprivate conditional.")::llvm::llvm_unreachable_internal("Aggregates are not supported in lastprivate conditional."
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11765)
;
11766 }
11767 // }
11768 CGF.EmitBranch(ExitBB);
11769 // There is no need to emit line number for unconditional branch.
11770 (void)ApplyDebugLocation::CreateEmpty(CGF);
11771 CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
11772 };
11773
11774 if (CGM.getLangOpts().OpenMPSimd) {
11775 // Do not emit as a critical region as no parallel region could be emitted.
11776 RegionCodeGenTy ThenRCG(CodeGen);
11777 ThenRCG(CGF);
11778 } else {
11779 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc);
11780 }
11781}
11782
11783void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF,
11784 const Expr *LHS) {
11785 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
11786 return;
11787 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack);
11788 if (!Checker.Visit(LHS))
11789 return;
11790 const Expr *FoundE;
11791 const Decl *FoundD;
11792 StringRef UniqueDeclName;
11793 LValue IVLVal;
11794 llvm::Function *FoundFn;
11795 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
11796 Checker.getFoundData();
11797 if (FoundFn != CGF.CurFn) {
11798 // Special codegen for inner parallel regions.
11799 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1;
11800 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD);
11801 assert(It != LastprivateConditionalToTypes[FoundFn].end() &&((It != LastprivateConditionalToTypes[FoundFn].end() &&
"Lastprivate conditional is not found in outer region.") ? static_cast
<void> (0) : __assert_fail ("It != LastprivateConditionalToTypes[FoundFn].end() && \"Lastprivate conditional is not found in outer region.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11802, __PRETTY_FUNCTION__))
11802 "Lastprivate conditional is not found in outer region.")((It != LastprivateConditionalToTypes[FoundFn].end() &&
"Lastprivate conditional is not found in outer region.") ? static_cast
<void> (0) : __assert_fail ("It != LastprivateConditionalToTypes[FoundFn].end() && \"Lastprivate conditional is not found in outer region.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11802, __PRETTY_FUNCTION__))
;
11803 QualType StructTy = std::get<0>(It->getSecond());
11804 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
11805 LValue PrivLVal = CGF.EmitLValue(FoundE);
11806 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11807 PrivLVal.getAddress(CGF),
11808 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy)));
11809 LValue BaseLVal =
11810 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl);
11811 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl);
11812 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get(
11813 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)),
11814 FiredLVal, llvm::AtomicOrdering::Unordered,
11815 /*IsVolatile=*/true, /*isInit=*/false);
11816 return;
11817 }
11818
11819 // Private address of the lastprivate conditional in the current context.
11820 // priv_a
11821 LValue LVal = CGF.EmitLValue(FoundE);
11822 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal,
11823 FoundE->getExprLoc());
11824}
11825
11826void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional(
11827 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11828 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) {
11829 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
11830 return;
11831 auto Range = llvm::reverse(LastprivateConditionalStack);
11832 auto It = llvm::find_if(
11833 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; });
11834 if (It == Range.end() || It->Fn != CGF.CurFn)
11835 return;
11836 auto LPCI = LastprivateConditionalToTypes.find(It->Fn);
11837 assert(LPCI != LastprivateConditionalToTypes.end() &&((LPCI != LastprivateConditionalToTypes.end() && "Lastprivates must be registered already."
) ? static_cast<void> (0) : __assert_fail ("LPCI != LastprivateConditionalToTypes.end() && \"Lastprivates must be registered already.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11838, __PRETTY_FUNCTION__))
11838 "Lastprivates must be registered already.")((LPCI != LastprivateConditionalToTypes.end() && "Lastprivates must be registered already."
) ? static_cast<void> (0) : __assert_fail ("LPCI != LastprivateConditionalToTypes.end() && \"Lastprivates must be registered already.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11838, __PRETTY_FUNCTION__))
;
11839 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
11840 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind());
11841 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
11842 for (const auto &Pair : It->DeclToUniqueName) {
11843 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl());
11844 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0)
11845 continue;
11846 auto I = LPCI->getSecond().find(Pair.first);
11847 assert(I != LPCI->getSecond().end() &&((I != LPCI->getSecond().end() && "Lastprivate must be rehistered already."
) ? static_cast<void> (0) : __assert_fail ("I != LPCI->getSecond().end() && \"Lastprivate must be rehistered already.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11848, __PRETTY_FUNCTION__))
11848 "Lastprivate must be rehistered already.")((I != LPCI->getSecond().end() && "Lastprivate must be rehistered already."
) ? static_cast<void> (0) : __assert_fail ("I != LPCI->getSecond().end() && \"Lastprivate must be rehistered already.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11848, __PRETTY_FUNCTION__))
;
11849 // bool Cmp = priv_a.Fired != 0;
11850 LValue BaseLVal = std::get<3>(I->getSecond());
11851 LValue FiredLVal =
11852 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond()));
11853 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc());
11854 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res);
11855 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then");
11856 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done");
11857 // if (Cmp) {
11858 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
11859 CGF.EmitBlock(ThenBB);
11860 Address Addr = CGF.GetAddrOfLocalVar(VD);
11861 LValue LVal;
11862 if (VD->getType()->isReferenceType())
11863 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
11864 AlignmentSource::Decl);
11865 else
11866 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(),
11867 AlignmentSource::Decl);
11868 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal,
11869 D.getBeginLoc());
11870 auto AL = ApplyDebugLocation::CreateArtificial(CGF);
11871 CGF.EmitBlock(DoneBB, /*IsFinal=*/true);
11872 // }
11873 }
11874}
11875
11876void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate(
11877 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD,
11878 SourceLocation Loc) {
11879 if (CGF.getLangOpts().OpenMP < 50)
11880 return;
11881 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD);
11882 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() &&((It != LastprivateConditionalStack.back().DeclToUniqueName.end
() && "Unknown lastprivate conditional variable.") ? static_cast
<void> (0) : __assert_fail ("It != LastprivateConditionalStack.back().DeclToUniqueName.end() && \"Unknown lastprivate conditional variable.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11883, __PRETTY_FUNCTION__))
11883 "Unknown lastprivate conditional variable.")((It != LastprivateConditionalStack.back().DeclToUniqueName.end
() && "Unknown lastprivate conditional variable.") ? static_cast
<void> (0) : __assert_fail ("It != LastprivateConditionalStack.back().DeclToUniqueName.end() && \"Unknown lastprivate conditional variable.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11883, __PRETTY_FUNCTION__))
;
11884 StringRef UniqueName = It->second;
11885 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName);
11886 // The variable was not updated in the region - exit.
11887 if (!GV)
11888 return;
11889 LValue LPLVal = CGF.MakeAddrLValue(
11890 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment());
11891 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc);
11892 CGF.EmitStoreOfScalar(Res, PrivLVal);
11893}
11894
11895llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
11896 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11897 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11898 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11898)
;
11899}
11900
11901llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
11902 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11903 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11904 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11904)
;
11905}
11906
11907llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
11908 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11909 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11910 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11911 bool Tied, unsigned &NumberOfParts) {
11912 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11912)
;
11913}
11914
11915void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11916 SourceLocation Loc,
11917 llvm::Function *OutlinedFn,
11918 ArrayRef<llvm::Value *> CapturedVars,
11919 const Expr *IfCond) {
11920 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11920)
;
11921}
11922
11923void CGOpenMPSIMDRuntime::emitCriticalRegion(
11924 CodeGenFunction &CGF, StringRef CriticalName,
11925 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11926 const Expr *Hint) {
11927 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11927)
;
11928}
11929
11930void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11931 const RegionCodeGenTy &MasterOpGen,
11932 SourceLocation Loc) {
11933 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11933)
;
11934}
11935
11936void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11937 SourceLocation Loc) {
11938 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11938)
;
11939}
11940
11941void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11942 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11943 SourceLocation Loc) {
11944 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11944)
;
11945}
11946
11947void CGOpenMPSIMDRuntime::emitSingleRegion(
11948 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11949 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11950 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11951 ArrayRef<const Expr *> AssignmentOps) {
11952 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11952)
;
11953}
11954
11955void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11956 const RegionCodeGenTy &OrderedOpGen,
11957 SourceLocation Loc,
11958 bool IsThreads) {
11959 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11959)
;
11960}
11961
11962void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11963 SourceLocation Loc,
11964 OpenMPDirectiveKind Kind,
11965 bool EmitChecks,
11966 bool ForceSimpleCall) {
11967 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11967)
;
11968}
11969
11970void CGOpenMPSIMDRuntime::emitForDispatchInit(
11971 CodeGenFunction &CGF, SourceLocation Loc,
11972 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11973 bool Ordered, const DispatchRTInput &DispatchValues) {
11974 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11974)
;
11975}
11976
11977void CGOpenMPSIMDRuntime::emitForStaticInit(
11978 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11979 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11980 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11980)
;
11981}
11982
11983void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11984 CodeGenFunction &CGF, SourceLocation Loc,
11985 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11986 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11986)
;
11987}
11988
11989void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11990 SourceLocation Loc,
11991 unsigned IVSize,
11992 bool IVSigned) {
11993 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11993)
;
11994}
11995
11996void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11997 SourceLocation Loc,
11998 OpenMPDirectiveKind DKind) {
11999 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11999)
;
12000}
12001
12002llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
12003 SourceLocation Loc,
12004 unsigned IVSize, bool IVSigned,
12005 Address IL, Address LB,
12006 Address UB, Address ST) {
12007 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12007)
;
12008}
12009
12010void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
12011 llvm::Value *NumThreads,
12012 SourceLocation Loc) {
12013 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12013)
;
12014}
12015
12016void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
12017 ProcBindKind ProcBind,
12018 SourceLocation Loc) {
12019 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12019)
;
12020}
12021
12022Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
12023 const VarDecl *VD,
12024 Address VDAddr,
12025 SourceLocation Loc) {
12026 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12026)
;
12027}
12028
12029llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
12030 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
12031 CodeGenFunction *CGF) {
12032 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12032)
;
12033}
12034
12035Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
12036 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
12037 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12037)
;
12038}
12039
12040void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
12041 ArrayRef<const Expr *> Vars,
12042 SourceLocation Loc,
12043 llvm::AtomicOrdering AO) {
12044 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12044)
;
12045}
12046
12047void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
12048 const OMPExecutableDirective &D,
12049 llvm::Function *TaskFunction,
12050 QualType SharedsTy, Address Shareds,
12051 const Expr *IfCond,
12052 const OMPTaskDataTy &Data) {
12053 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12053)
;
12054}
12055
12056void CGOpenMPSIMDRuntime::emitTaskLoopCall(
12057 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
12058 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
12059 const Expr *IfCond, const OMPTaskDataTy &Data) {
12060 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12060)
;
12061}
12062
12063void CGOpenMPSIMDRuntime::emitReduction(
12064 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
12065 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
12066 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
12067 assert(Options.SimpleReduction && "Only simple reduction is expected.")((Options.SimpleReduction && "Only simple reduction is expected."
) ? static_cast<void> (0) : __assert_fail ("Options.SimpleReduction && \"Only simple reduction is expected.\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12067, __PRETTY_FUNCTION__))
;
12068 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
12069 ReductionOps, Options);
12070}
12071
12072llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
12073 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
12074 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
12075 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12075)
;
12076}
12077
12078void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF,
12079 SourceLocation Loc,
12080 bool IsWorksharingReduction) {
12081 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12081)
;
12082}
12083
12084void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
12085 SourceLocation Loc,
12086 ReductionCodeGen &RCG,
12087 unsigned N) {
12088 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12088)
;
12089}
12090
12091Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
12092 SourceLocation Loc,
12093 llvm::Value *ReductionsPtr,
12094 LValue SharedLVal) {
12095 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12095)
;
12096}
12097
12098void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
12099 SourceLocation Loc) {
12100 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12100)
;
12101}
12102
12103void CGOpenMPSIMDRuntime::emitCancellationPointCall(
12104 CodeGenFunction &CGF, SourceLocation Loc,
12105 OpenMPDirectiveKind CancelRegion) {
12106 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12106)
;
12107}
12108
12109void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
12110 SourceLocation Loc, const Expr *IfCond,
12111 OpenMPDirectiveKind CancelRegion) {
12112 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12112)
;
12113}
12114
12115void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
12116 const OMPExecutableDirective &D, StringRef ParentName,
12117 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
12118 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
12119 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12119)
;
12120}
12121
12122void CGOpenMPSIMDRuntime::emitTargetCall(
12123 CodeGenFunction &CGF, const OMPExecutableDirective &D,
12124 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
12125 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device,
12126 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
12127 const OMPLoopDirective &D)>
12128 SizeEmitter) {
12129 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12129)
;
12130}
12131
12132bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
12133 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12133)
;
12134}
12135
12136bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
12137 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12137)
;
12138}
12139
12140bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
12141 return false;
12142}
12143
12144void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
12145 const OMPExecutableDirective &D,
12146 SourceLocation Loc,
12147 llvm::Function *OutlinedFn,
12148 ArrayRef<llvm::Value *> CapturedVars) {
12149 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12149)
;
12150}
12151
12152void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
12153 const Expr *NumTeams,
12154 const Expr *ThreadLimit,
12155 SourceLocation Loc) {
12156 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12156)
;
12157}
12158
12159void CGOpenMPSIMDRuntime::emitTargetDataCalls(
12160 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
12161 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
12162 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12162)
;
12163}
12164
12165void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
12166 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
12167 const Expr *Device) {
12168 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12168)
;
12169}
12170
12171void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
12172 const OMPLoopDirective &D,
12173 ArrayRef<Expr *> NumIterations) {
12174 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12174)
;
12175}
12176
12177void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
12178 const OMPDependClause *C) {
12179 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12179)
;
12180}
12181
12182const VarDecl *
12183CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
12184 const VarDecl *NativeParam) const {
12185 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12185)
;
12186}
12187
12188Address
12189CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
12190 const VarDecl *NativeParam,
12191 const VarDecl *TargetParam) const {
12192 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12192)
;
12193}

/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.h

1//===----- CGOpenMPRuntime.h - Interface to OpenMP Runtimes -----*- 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 provides a class for OpenMP runtime code generation.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H
14#define LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H
15
16#include "CGValue.h"
17#include "clang/AST/DeclOpenMP.h"
18#include "clang/AST/GlobalDecl.h"
19#include "clang/AST/Type.h"
20#include "clang/Basic/OpenMPKinds.h"
21#include "clang/Basic/SourceLocation.h"
22#include "llvm/ADT/DenseMap.h"
23#include "llvm/ADT/PointerIntPair.h"
24#include "llvm/ADT/SmallPtrSet.h"
25#include "llvm/ADT/StringMap.h"
26#include "llvm/ADT/StringSet.h"
27#include "llvm/Frontend/OpenMP/OMPConstants.h"
28#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
29#include "llvm/IR/Function.h"
30#include "llvm/IR/ValueHandle.h"
31#include "llvm/Support/AtomicOrdering.h"
32
33namespace llvm {
34class ArrayType;
35class Constant;
36class FunctionType;
37class GlobalVariable;
38class StructType;
39class Type;
40class Value;
41class OpenMPIRBuilder;
42} // namespace llvm
43
44namespace clang {
45class Expr;
46class OMPDependClause;
47class OMPExecutableDirective;
48class OMPLoopDirective;
49class VarDecl;
50class OMPDeclareReductionDecl;
51class IdentifierInfo;
52
53namespace CodeGen {
54class Address;
55class CodeGenFunction;
56class CodeGenModule;
57
58/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
59/// region.
60class PrePostActionTy {
61public:
62 explicit PrePostActionTy() {}
63 virtual void Enter(CodeGenFunction &CGF) {}
64 virtual void Exit(CodeGenFunction &CGF) {}
65 virtual ~PrePostActionTy() {}
66};
67
68/// Class provides a way to call simple version of codegen for OpenMP region, or
69/// an advanced with possible pre|post-actions in codegen.
70class RegionCodeGenTy final {
71 intptr_t CodeGen;
72 typedef void (*CodeGenTy)(intptr_t, CodeGenFunction &, PrePostActionTy &);
73 CodeGenTy Callback;
74 mutable PrePostActionTy *PrePostAction;
75 RegionCodeGenTy() = delete;
76 RegionCodeGenTy &operator=(const RegionCodeGenTy &) = delete;
77 template <typename Callable>
78 static void CallbackFn(intptr_t CodeGen, CodeGenFunction &CGF,
79 PrePostActionTy &Action) {
80 return (*reinterpret_cast<Callable *>(CodeGen))(CGF, Action);
17
Calling 'operator()'
81 }
82
83public:
84 template <typename Callable>
85 RegionCodeGenTy(
86 Callable &&CodeGen,
87 std::enable_if_t<!std::is_same<std::remove_reference_t<Callable>,
88 RegionCodeGenTy>::value> * = nullptr)
89 : CodeGen(reinterpret_cast<intptr_t>(&CodeGen)),
90 Callback(CallbackFn<std::remove_reference_t<Callable>>),
91 PrePostAction(nullptr) {}
92 void setAction(PrePostActionTy &Action) const { PrePostAction = &Action; }
93 void operator()(CodeGenFunction &CGF) const;
94};
95
96struct OMPTaskDataTy final {
97 SmallVector<const Expr *, 4> PrivateVars;
98 SmallVector<const Expr *, 4> PrivateCopies;
99 SmallVector<const Expr *, 4> FirstprivateVars;
100 SmallVector<const Expr *, 4> FirstprivateCopies;
101 SmallVector<const Expr *, 4> FirstprivateInits;
102 SmallVector<const Expr *, 4> LastprivateVars;
103 SmallVector<const Expr *, 4> LastprivateCopies;
104 SmallVector<const Expr *, 4> ReductionVars;
105 SmallVector<const Expr *, 4> ReductionOrigs;
106 SmallVector<const Expr *, 4> ReductionCopies;
107 SmallVector<const Expr *, 4> ReductionOps;
108 SmallVector<CanonicalDeclPtr<const VarDecl>, 4> PrivateLocals;
109 struct DependData {
110 OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
111 const Expr *IteratorExpr = nullptr;
112 SmallVector<const Expr *, 4> DepExprs;
113 explicit DependData() = default;
114 DependData(OpenMPDependClauseKind DepKind, const Expr *IteratorExpr)
115 : DepKind(DepKind), IteratorExpr(IteratorExpr) {}
116 };
117 SmallVector<DependData, 4> Dependences;
118 llvm::PointerIntPair<llvm::Value *, 1, bool> Final;
119 llvm::PointerIntPair<llvm::Value *, 1, bool> Schedule;
120 llvm::PointerIntPair<llvm::Value *, 1, bool> Priority;
121 llvm::Value *Reductions = nullptr;
122 unsigned NumberOfParts = 0;
123 bool Tied = true;
124 bool Nogroup = false;
125 bool IsReductionWithTaskMod = false;
126 bool IsWorksharingReduction = false;
127};
128
129/// Class intended to support codegen of all kind of the reduction clauses.
130class ReductionCodeGen {
131private:
132 /// Data required for codegen of reduction clauses.
133 struct ReductionData {
134 /// Reference to the item shared between tasks to reduce into.
135 const Expr *Shared = nullptr;
136 /// Reference to the original item.
137 const Expr *Ref = nullptr;
138 /// Helper expression for generation of private copy.
139 const Expr *Private = nullptr;
140 /// Helper expression for generation reduction operation.
141 const Expr *ReductionOp = nullptr;
142 ReductionData(const Expr *Shared, const Expr *Ref, const Expr *Private,
143 const Expr *ReductionOp)
144 : Shared(Shared), Ref(Ref), Private(Private), ReductionOp(ReductionOp) {
145 }
146 };
147 /// List of reduction-based clauses.
148 SmallVector<ReductionData, 4> ClausesData;
149
150 /// List of addresses of shared variables/expressions.
151 SmallVector<std::pair<LValue, LValue>, 4> SharedAddresses;
152 /// List of addresses of original variables/expressions.
153 SmallVector<std::pair<LValue, LValue>, 4> OrigAddresses;
154 /// Sizes of the reduction items in chars.
155 SmallVector<std::pair<llvm::Value *, llvm::Value *>, 4> Sizes;
156 /// Base declarations for the reduction items.
157 SmallVector<const VarDecl *, 4> BaseDecls;
158
159 /// Emits lvalue for shared expression.
160 LValue emitSharedLValue(CodeGenFunction &CGF, const Expr *E);
161 /// Emits upper bound for shared expression (if array section).
162 LValue emitSharedLValueUB(CodeGenFunction &CGF, const Expr *E);
163 /// Performs aggregate initialization.
164 /// \param N Number of reduction item in the common list.
165 /// \param PrivateAddr Address of the corresponding private item.
166 /// \param SharedLVal Address of the original shared variable.
167 /// \param DRD Declare reduction construct used for reduction item.
168 void emitAggregateInitialization(CodeGenFunction &CGF, unsigned N,
169 Address PrivateAddr, LValue SharedLVal,
170 const OMPDeclareReductionDecl *DRD);
171
172public:
173 ReductionCodeGen(ArrayRef<const Expr *> Shareds, ArrayRef<const Expr *> Origs,
174 ArrayRef<const Expr *> Privates,
175 ArrayRef<const Expr *> ReductionOps);
176 /// Emits lvalue for the shared and original reduction item.
177 /// \param N Number of the reduction item.
178 void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N);
179 /// Emits the code for the variable-modified type, if required.
180 /// \param N Number of the reduction item.
181 void emitAggregateType(CodeGenFunction &CGF, unsigned N);
182 /// Emits the code for the variable-modified type, if required.
183 /// \param N Number of the reduction item.
184 /// \param Size Size of the type in chars.
185 void emitAggregateType(CodeGenFunction &CGF, unsigned N, llvm::Value *Size);
186 /// Performs initialization of the private copy for the reduction item.
187 /// \param N Number of the reduction item.
188 /// \param PrivateAddr Address of the corresponding private item.
189 /// \param DefaultInit Default initialization sequence that should be
190 /// performed if no reduction specific initialization is found.
191 /// \param SharedLVal Address of the original shared variable.
192 void
193 emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr,
194 LValue SharedLVal,
195 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit);
196 /// Returns true if the private copy requires cleanups.
197 bool needCleanups(unsigned N);
198 /// Emits cleanup code for the reduction item.
199 /// \param N Number of the reduction item.
200 /// \param PrivateAddr Address of the corresponding private item.
201 void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr);
202 /// Adjusts \p PrivatedAddr for using instead of the original variable
203 /// address in normal operations.
204 /// \param N Number of the reduction item.
205 /// \param PrivateAddr Address of the corresponding private item.
206 Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
207 Address PrivateAddr);
208 /// Returns LValue for the reduction item.
209 LValue getSharedLValue(unsigned N) const { return SharedAddresses[N].first; }
210 /// Returns LValue for the original reduction item.
211 LValue getOrigLValue(unsigned N) const { return OrigAddresses[N].first; }
212 /// Returns the size of the reduction item (in chars and total number of
213 /// elements in the item), or nullptr, if the size is a constant.
214 std::pair<llvm::Value *, llvm::Value *> getSizes(unsigned N) const {
215 return Sizes[N];
216 }
217 /// Returns the base declaration of the reduction item.
218 const VarDecl *getBaseDecl(unsigned N) const { return BaseDecls[N]; }
219 /// Returns the base declaration of the reduction item.
220 const Expr *getRefExpr(unsigned N) const { return ClausesData[N].Ref; }
221 /// Returns true if the initialization of the reduction item uses initializer
222 /// from declare reduction construct.
223 bool usesReductionInitializer(unsigned N) const;
224};
225
226class CGOpenMPRuntime {
227public:
228 /// Allows to disable automatic handling of functions used in target regions
229 /// as those marked as `omp declare target`.
230 class DisableAutoDeclareTargetRAII {
231 CodeGenModule &CGM;
232 bool SavedShouldMarkAsGlobal;
233
234 public:
235 DisableAutoDeclareTargetRAII(CodeGenModule &CGM);
236 ~DisableAutoDeclareTargetRAII();
237 };
238
239 /// Manages list of nontemporal decls for the specified directive.
240 class NontemporalDeclsRAII {
241 CodeGenModule &CGM;
242 const bool NeedToPush;
243
244 public:
245 NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S);
246 ~NontemporalDeclsRAII();
247 };
248
249 /// Manages list of nontemporal decls for the specified directive.
250 class UntiedTaskLocalDeclsRAII {
251 CodeGenModule &CGM;
252 const bool NeedToPush;
253
254 public:
255 UntiedTaskLocalDeclsRAII(
256 CodeGenFunction &CGF,
257 const llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
258 std::pair<Address, Address>> &LocalVars);
259 ~UntiedTaskLocalDeclsRAII();
260 };
261
262 /// Maps the expression for the lastprivate variable to the global copy used
263 /// to store new value because original variables are not mapped in inner
264 /// parallel regions. Only private copies are captured but we need also to
265 /// store private copy in shared address.
266 /// Also, stores the expression for the private loop counter and it
267 /// threaprivate name.
268 struct LastprivateConditionalData {
269 llvm::MapVector<CanonicalDeclPtr<const Decl>, SmallString<16>>
270 DeclToUniqueName;
271 LValue IVLVal;
272 llvm::Function *Fn = nullptr;
273 bool Disabled = false;
274 };
275 /// Manages list of lastprivate conditional decls for the specified directive.
276 class LastprivateConditionalRAII {
277 enum class ActionToDo {
278 DoNotPush,
279 PushAsLastprivateConditional,
280 DisableLastprivateConditional,
281 };
282 CodeGenModule &CGM;
283 ActionToDo Action = ActionToDo::DoNotPush;
284
285 /// Check and try to disable analysis of inner regions for changes in
286 /// lastprivate conditional.
287 void tryToDisableInnerAnalysis(const OMPExecutableDirective &S,
288 llvm::DenseSet<CanonicalDeclPtr<const Decl>>
289 &NeedToAddForLPCsAsDisabled) const;
290
291 LastprivateConditionalRAII(CodeGenFunction &CGF,
292 const OMPExecutableDirective &S);
293
294 public:
295 explicit LastprivateConditionalRAII(CodeGenFunction &CGF,
296 const OMPExecutableDirective &S,
297 LValue IVLVal);
298 static LastprivateConditionalRAII disable(CodeGenFunction &CGF,
299 const OMPExecutableDirective &S);
300 ~LastprivateConditionalRAII();
301 };
302
303 llvm::OpenMPIRBuilder &getOMPBuilder() { return OMPBuilder; }
304
305protected:
306 CodeGenModule &CGM;
307 StringRef FirstSeparator, Separator;
308
309 /// An OpenMP-IR-Builder instance.
310 llvm::OpenMPIRBuilder OMPBuilder;
311
312 /// Constructor allowing to redefine the name separator for the variables.
313 explicit CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
314 StringRef Separator);
315
316 /// Creates offloading entry for the provided entry ID \a ID,
317 /// address \a Addr, size \a Size, and flags \a Flags.
318 virtual void createOffloadEntry(llvm::Constant *ID, llvm::Constant *Addr,
319 uint64_t Size, int32_t Flags,
320 llvm::GlobalValue::LinkageTypes Linkage);
321
322 /// Helper to emit outlined function for 'target' directive.
323 /// \param D Directive to emit.
324 /// \param ParentName Name of the function that encloses the target region.
325 /// \param OutlinedFn Outlined function value to be defined by this call.
326 /// \param OutlinedFnID Outlined function ID value to be defined by this call.
327 /// \param IsOffloadEntry True if the outlined function is an offload entry.
328 /// \param CodeGen Lambda codegen specific to an accelerator device.
329 /// An outlined function may not be an entry if, e.g. the if clause always
330 /// evaluates to false.
331 virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D,
332 StringRef ParentName,
333 llvm::Function *&OutlinedFn,
334 llvm::Constant *&OutlinedFnID,
335 bool IsOffloadEntry,
336 const RegionCodeGenTy &CodeGen);
337
338 /// Emits object of ident_t type with info for source location.
339 /// \param Flags Flags for OpenMP location.
340 ///
341 llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc,
342 unsigned Flags = 0);
343
344 /// Returns pointer to ident_t type.
345 llvm::Type *getIdentTyPointerTy();
346
347 /// Gets thread id value for the current thread.
348 ///
349 llvm::Value *getThreadID(CodeGenFunction &CGF, SourceLocation Loc);
350
351 /// Get the function name of an outlined region.
352 // The name can be customized depending on the target.
353 //
354 virtual StringRef getOutlinedHelperName() const { return ".omp_outlined."; }
355
356 /// Emits \p Callee function call with arguments \p Args with location \p Loc.
357 void emitCall(CodeGenFunction &CGF, SourceLocation Loc,
358 llvm::FunctionCallee Callee,
359 ArrayRef<llvm::Value *> Args = llvm::None) const;
360
361 /// Emits address of the word in a memory where current thread id is
362 /// stored.
363 virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc);
364
365 void setLocThreadIdInsertPt(CodeGenFunction &CGF,
366 bool AtCurrentPoint = false);
367 void clearLocThreadIdInsertPt(CodeGenFunction &CGF);
368
369 /// Check if the default location must be constant.
370 /// Default is false to support OMPT/OMPD.
371 virtual bool isDefaultLocationConstant() const { return false; }
372
373 /// Returns additional flags that can be stored in reserved_2 field of the
374 /// default location.
375 virtual unsigned getDefaultLocationReserved2Flags() const { return 0; }
376
377 /// Returns default flags for the barriers depending on the directive, for
378 /// which this barier is going to be emitted.
379 static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind);
380
381 /// Get the LLVM type for the critical name.
382 llvm::ArrayType *getKmpCriticalNameTy() const {return KmpCriticalNameTy;}
383
384 /// Returns corresponding lock object for the specified critical region
385 /// name. If the lock object does not exist it is created, otherwise the
386 /// reference to the existing copy is returned.
387 /// \param CriticalName Name of the critical region.
388 ///
389 llvm::Value *getCriticalRegionLock(StringRef CriticalName);
390
391private:
392
393 /// Map for SourceLocation and OpenMP runtime library debug locations.
394 typedef llvm::DenseMap<SourceLocation, llvm::Value *> OpenMPDebugLocMapTy;
395 OpenMPDebugLocMapTy OpenMPDebugLocMap;
396 /// The type for a microtask which gets passed to __kmpc_fork_call().
397 /// Original representation is:
398 /// typedef void (kmpc_micro)(kmp_int32 global_tid, kmp_int32 bound_tid,...);
399 llvm::FunctionType *Kmpc_MicroTy = nullptr;
400 /// Stores debug location and ThreadID for the function.
401 struct DebugLocThreadIdTy {
402 llvm::Value *DebugLoc;
403 llvm::Value *ThreadID;
404 /// Insert point for the service instructions.
405 llvm::AssertingVH<llvm::Instruction> ServiceInsertPt = nullptr;
406 };
407 /// Map of local debug location, ThreadId and functions.
408 typedef llvm::DenseMap<llvm::Function *, DebugLocThreadIdTy>
409 OpenMPLocThreadIDMapTy;
410 OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap;
411 /// Map of UDRs and corresponding combiner/initializer.
412 typedef llvm::DenseMap<const OMPDeclareReductionDecl *,
413 std::pair<llvm::Function *, llvm::Function *>>
414 UDRMapTy;
415 UDRMapTy UDRMap;
416 /// Map of functions and locally defined UDRs.
417 typedef llvm::DenseMap<llvm::Function *,
418 SmallVector<const OMPDeclareReductionDecl *, 4>>
419 FunctionUDRMapTy;
420 FunctionUDRMapTy FunctionUDRMap;
421 /// Map from the user-defined mapper declaration to its corresponding
422 /// functions.
423 llvm::DenseMap<const OMPDeclareMapperDecl *, llvm::Function *> UDMMap;
424 /// Map of functions and their local user-defined mappers.
425 using FunctionUDMMapTy =
426 llvm::DenseMap<llvm::Function *,
427 SmallVector<const OMPDeclareMapperDecl *, 4>>;
428 FunctionUDMMapTy FunctionUDMMap;
429 /// Maps local variables marked as lastprivate conditional to their internal
430 /// types.
431 llvm::DenseMap<llvm::Function *,
432 llvm::DenseMap<CanonicalDeclPtr<const Decl>,
433 std::tuple<QualType, const FieldDecl *,
434 const FieldDecl *, LValue>>>
435 LastprivateConditionalToTypes;
436 /// Maps function to the position of the untied task locals stack.
437 llvm::DenseMap<llvm::Function *, unsigned> FunctionToUntiedTaskStackMap;
438 /// Type kmp_critical_name, originally defined as typedef kmp_int32
439 /// kmp_critical_name[8];
440 llvm::ArrayType *KmpCriticalNameTy;
441 /// An ordered map of auto-generated variables to their unique names.
442 /// It stores variables with the following names: 1) ".gomp_critical_user_" +
443 /// <critical_section_name> + ".var" for "omp critical" directives; 2)
444 /// <mangled_name_for_global_var> + ".cache." for cache for threadprivate
445 /// variables.
446 llvm::StringMap<llvm::AssertingVH<llvm::Constant>, llvm::BumpPtrAllocator>
447 InternalVars;
448 /// Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);
449 llvm::Type *KmpRoutineEntryPtrTy = nullptr;
450 QualType KmpRoutineEntryPtrQTy;
451 /// Type typedef struct kmp_task {
452 /// void * shareds; /**< pointer to block of pointers to
453 /// shared vars */
454 /// kmp_routine_entry_t routine; /**< pointer to routine to call for
455 /// executing task */
456 /// kmp_int32 part_id; /**< part id for the task */
457 /// kmp_routine_entry_t destructors; /* pointer to function to invoke
458 /// deconstructors of firstprivate C++ objects */
459 /// } kmp_task_t;
460 QualType KmpTaskTQTy;
461 /// Saved kmp_task_t for task directive.
462 QualType SavedKmpTaskTQTy;
463 /// Saved kmp_task_t for taskloop-based directive.
464 QualType SavedKmpTaskloopTQTy;
465 /// Type typedef struct kmp_depend_info {
466 /// kmp_intptr_t base_addr;
467 /// size_t len;
468 /// struct {
469 /// bool in:1;
470 /// bool out:1;
471 /// } flags;
472 /// } kmp_depend_info_t;
473 QualType KmpDependInfoTy;
474 /// Type typedef struct kmp_task_affinity_info {
475 /// kmp_intptr_t base_addr;
476 /// size_t len;
477 /// struct {
478 /// bool flag1 : 1;
479 /// bool flag2 : 1;
480 /// kmp_int32 reserved : 30;
481 /// } flags;
482 /// } kmp_task_affinity_info_t;
483 QualType KmpTaskAffinityInfoTy;
484 /// struct kmp_dim { // loop bounds info casted to kmp_int64
485 /// kmp_int64 lo; // lower
486 /// kmp_int64 up; // upper
487 /// kmp_int64 st; // stride
488 /// };
489 QualType KmpDimTy;
490 /// Type struct __tgt_offload_entry{
491 /// void *addr; // Pointer to the offload entry info.
492 /// // (function or global)
493 /// char *name; // Name of the function or global.
494 /// size_t size; // Size of the entry info (0 if it a function).
495 /// int32_t flags;
496 /// int32_t reserved;
497 /// };
498 QualType TgtOffloadEntryQTy;
499 /// Entity that registers the offloading constants that were emitted so
500 /// far.
501 class OffloadEntriesInfoManagerTy {
502 CodeGenModule &CGM;
503
504 /// Number of entries registered so far.
505 unsigned OffloadingEntriesNum = 0;
506
507 public:
508 /// Base class of the entries info.
509 class OffloadEntryInfo {
510 public:
511 /// Kind of a given entry.
512 enum OffloadingEntryInfoKinds : unsigned {
513 /// Entry is a target region.
514 OffloadingEntryInfoTargetRegion = 0,
515 /// Entry is a declare target variable.
516 OffloadingEntryInfoDeviceGlobalVar = 1,
517 /// Invalid entry info.
518 OffloadingEntryInfoInvalid = ~0u
519 };
520
521 protected:
522 OffloadEntryInfo() = delete;
523 explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind) : Kind(Kind) {}
524 explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind, unsigned Order,
525 uint32_t Flags)
526 : Flags(Flags), Order(Order), Kind(Kind) {}
527 ~OffloadEntryInfo() = default;
528
529 public:
530 bool isValid() const { return Order != ~0u; }
531 unsigned getOrder() const { return Order; }
532 OffloadingEntryInfoKinds getKind() const { return Kind; }
533 uint32_t getFlags() const { return Flags; }
534 void setFlags(uint32_t NewFlags) { Flags = NewFlags; }
535 llvm::Constant *getAddress() const {
536 return cast_or_null<llvm::Constant>(Addr);
537 }
538 void setAddress(llvm::Constant *V) {
539 assert(!Addr.pointsToAliveValue() && "Address has been set before!")((!Addr.pointsToAliveValue() && "Address has been set before!"
) ? static_cast<void> (0) : __assert_fail ("!Addr.pointsToAliveValue() && \"Address has been set before!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.h"
, 539, __PRETTY_FUNCTION__))
;
540 Addr = V;
541 }
542 static bool classof(const OffloadEntryInfo *Info) { return true; }
543
544 private:
545 /// Address of the entity that has to be mapped for offloading.
546 llvm::WeakTrackingVH Addr;
547
548 /// Flags associated with the device global.
549 uint32_t Flags = 0u;
550
551 /// Order this entry was emitted.
552 unsigned Order = ~0u;
553
554 OffloadingEntryInfoKinds Kind = OffloadingEntryInfoInvalid;
555 };
556
557 /// Return true if a there are no entries defined.
558 bool empty() const;
559 /// Return number of entries defined so far.
560 unsigned size() const { return OffloadingEntriesNum; }
561 OffloadEntriesInfoManagerTy(CodeGenModule &CGM) : CGM(CGM) {}
562
563 //
564 // Target region entries related.
565 //
566
567 /// Kind of the target registry entry.
568 enum OMPTargetRegionEntryKind : uint32_t {
569 /// Mark the entry as target region.
570 OMPTargetRegionEntryTargetRegion = 0x0,
571 /// Mark the entry as a global constructor.
572 OMPTargetRegionEntryCtor = 0x02,
573 /// Mark the entry as a global destructor.
574 OMPTargetRegionEntryDtor = 0x04,
575 };
576
577 /// Target region entries info.
578 class OffloadEntryInfoTargetRegion final : public OffloadEntryInfo {
579 /// Address that can be used as the ID of the entry.
580 llvm::Constant *ID = nullptr;
581
582 public:
583 OffloadEntryInfoTargetRegion()
584 : OffloadEntryInfo(OffloadingEntryInfoTargetRegion) {}
585 explicit OffloadEntryInfoTargetRegion(unsigned Order,
586 llvm::Constant *Addr,
587 llvm::Constant *ID,
588 OMPTargetRegionEntryKind Flags)
589 : OffloadEntryInfo(OffloadingEntryInfoTargetRegion, Order, Flags),
590 ID(ID) {
591 setAddress(Addr);
592 }
593
594 llvm::Constant *getID() const { return ID; }
595 void setID(llvm::Constant *V) {
596 assert(!ID && "ID has been set before!")((!ID && "ID has been set before!") ? static_cast<
void> (0) : __assert_fail ("!ID && \"ID has been set before!\""
, "/build/llvm-toolchain-snapshot-12.0.0~++20201102111116+1ed2ca68191/clang/lib/CodeGen/CGOpenMPRuntime.h"
, 596, __PRETTY_FUNCTION__))
;
597 ID = V;
598 }
599 static bool classof(const OffloadEntryInfo *Info) {
600 return Info->getKind() == OffloadingEntryInfoTargetRegion;
601 }
602 };
603
604 /// Initialize target region entry.
605 void initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
606 StringRef ParentName, unsigned LineNum,
607 unsigned Order);
608 /// Register target region entry.
609 void registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
610 StringRef ParentName, unsigned LineNum,
611 llvm::Constant *Addr, llvm::Constant *ID,
612 OMPTargetRegionEntryKind Flags);
613 /// Return true if a target region entry with the provided information
614 /// exists.
615 bool hasTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
616 StringRef ParentName, unsigned LineNum) const;
617 /// brief Applies action \a Action on all registered entries.
618 typedef llvm::function_ref<void(unsigned, unsigned, StringRef, unsigned,
619 const OffloadEntryInfoTargetRegion &)>
620 OffloadTargetRegionEntryInfoActTy;
621 void actOnTargetRegionEntriesInfo(
622 const OffloadTargetRegionEntryInfoActTy &Action);
623
624 //
625 // Device global variable entries related.
626 //
627
628 /// Kind of the global variable entry..
629 enum OMPTargetGlobalVarEntryKind : uint32_t {
630 /// Mark the entry as a to declare target.
631 OMPTargetGlobalVarEntryTo = 0x0,
632 /// Mark the entry as a to declare target link.
633 OMPTargetGlobalVarEntryLink = 0x1,
634 };
635
636 /// Device global variable entries info.
637 class OffloadEntryInfoDeviceGlobalVar final : public OffloadEntryInfo {
638 /// Type of the global variable.
639 CharUnits VarSize;
640 llvm::GlobalValue::LinkageTypes Linkage;
641
642 public:
643 OffloadEntryInfoDeviceGlobalVar()
644 : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar) {}
645 explicit OffloadEntryInfoDeviceGlobalVar(unsigned Order,
646 OMPTargetGlobalVarEntryKind Flags)
647 : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar, Order, Flags) {}
648 explicit OffloadEntryInfoDeviceGlobalVar(
649 unsigned Order, llvm::Constant *Addr, CharUnits VarSize,
650 OMPTargetGlobalVarEntryKind Flags,
651 llvm::GlobalValue::LinkageTypes Linkage)
652 : OffloadEntryInfo(OffloadingEntryInfoDeviceGlobalVar, Order, Flags),
653 VarSize(VarSize), Linkage(Linkage) {
654 setAddress(Addr);
655 }
656
657 CharUnits getVarSize() const { return VarSize; }
658 void setVarSize(CharUnits Size) { VarSize = Size; }
659 llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; }
660 void setLinkage(llvm::GlobalValue::LinkageTypes LT) { Linkage = LT; }
661 static bool classof(const OffloadEntryInfo *Info) {
662 return Info->getKind() == OffloadingEntryInfoDeviceGlobalVar;
663 }
664 };
665
666 /// Initialize device global variable entry.
667 void initializeDeviceGlobalVarEntryInfo(StringRef Name,
668 OMPTargetGlobalVarEntryKind Flags,
669 unsigned Order);
670
671 /// Register device global variable entry.
672 void
673 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
674 CharUnits VarSize,
675 OMPTargetGlobalVarEntryKind Flags,
676 llvm::GlobalValue::LinkageTypes Linkage);
677 /// Checks if the variable with the given name has been registered already.
678 bool hasDeviceGlobalVarEntryInfo(StringRef VarName) const {
679 return OffloadEntriesDeviceGlobalVar.count(VarName) > 0;
680 }
681 /// Applies action \a Action on all registered entries.
682 typedef llvm::function_ref<void(StringRef,
683 const OffloadEntryInfoDeviceGlobalVar &)>
684 OffloadDeviceGlobalVarEntryInfoActTy;
685 void actOnDeviceGlobalVarEntriesInfo(
686 const OffloadDeviceGlobalVarEntryInfoActTy &Action);
687
688 private:
689 // Storage for target region entries kind. The storage is to be indexed by
690 // file ID, device ID, parent function name and line number.
691 typedef llvm::DenseMap<unsigned, OffloadEntryInfoTargetRegion>
692 OffloadEntriesTargetRegionPerLine;
693 typedef llvm::StringMap<OffloadEntriesTargetRegionPerLine>
694 OffloadEntriesTargetRegionPerParentName;
695 typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerParentName>
696 OffloadEntriesTargetRegionPerFile;
697 typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerFile>
698 OffloadEntriesTargetRegionPerDevice;
699 typedef OffloadEntriesTargetRegionPerDevice OffloadEntriesTargetRegionTy;
700 OffloadEntriesTargetRegionTy OffloadEntriesTargetRegion;
701 /// Storage for device global variable entries kind. The storage is to be
702 /// indexed by mangled name.
703 typedef llvm::StringMap<OffloadEntryInfoDeviceGlobalVar>
704 OffloadEntriesDeviceGlobalVarTy;
705 OffloadEntriesDeviceGlobalVarTy OffloadEntriesDeviceGlobalVar;
706 };
707 OffloadEntriesInfoManagerTy OffloadEntriesInfoManager;
708
709 bool ShouldMarkAsGlobal = true;
710 /// List of the emitted declarations.
711 llvm::DenseSet<CanonicalDeclPtr<const Decl>> AlreadyEmittedTargetDecls;
712 /// List of the global variables with their addresses that should not be
713 /// emitted for the target.
714 llvm::StringMap<llvm::WeakTrackingVH> EmittedNonTargetVariables;
715
716 /// List of variables that can become declare target implicitly and, thus,
717 /// must be emitted.
718 llvm::SmallDenseSet<const VarDecl *> DeferredGlobalVariables;
719
720 using NontemporalDeclsSet = llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>>;
721 /// Stack for list of declarations in current context marked as nontemporal.
722 /// The set is the union of all current stack elements.
723 llvm::SmallVector<NontemporalDeclsSet, 4> NontemporalDeclsStack;
724
725 using UntiedLocalVarsAddressesMap =
726 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
727 std::pair<Address, Address>>;
728 llvm::SmallVector<UntiedLocalVarsAddressesMap, 4> UntiedLocalVarsStack;
729
730 /// Stack for list of addresses of declarations in current context marked as
731 /// lastprivate conditional. The set is the union of all current stack
732 /// elements.
733 llvm::SmallVector<LastprivateConditionalData, 4> LastprivateConditionalStack;
734
735 /// Flag for keeping track of weather a requires unified_shared_memory
736 /// directive is present.
737 bool HasRequiresUnifiedSharedMemory = false;
738
739 /// Atomic ordering from the omp requires directive.
740 llvm::AtomicOrdering RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic;
741
742 /// Flag for keeping track of weather a target region has been emitted.
743 bool HasEmittedTargetRegion = false;
744
745 /// Flag for keeping track of weather a device routine has been emitted.
746 /// Device routines are specific to the
747 bool HasEmittedDeclareTargetRegion = false;
748
749 /// Loads all the offload entries information from the host IR
750 /// metadata.
751 void loadOffloadInfoMetadata();
752
753 /// Returns __tgt_offload_entry type.
754 QualType getTgtOffloadEntryQTy();
755
756 /// Start scanning from statement \a S and and emit all target regions
757 /// found along the way.
758 /// \param S Starting statement.
759 /// \param ParentName Name of the function declaration that is being scanned.
760 void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName);
761
762 /// Build type kmp_routine_entry_t (if not built yet).
763 void emitKmpRoutineEntryT(QualType KmpInt32Ty);
764
765 /// Returns pointer to kmpc_micro type.
766 llvm::Type *getKmpc_MicroPointerTy();
767
768 /// Returns __kmpc_for_static_init_* runtime function for the specified
769 /// size \a IVSize and sign \a IVSigned.
770 llvm::FunctionCallee createForStaticInitFunction(unsigned IVSize,
771 bool IVSigned);
772
773 /// Returns __kmpc_dispatch_init_* runtime function for the specified
774 /// size \a IVSize and sign \a IVSigned.
775 llvm::FunctionCallee createDispatchInitFunction(unsigned IVSize,
776 bool IVSigned);
777
778 /// Returns __kmpc_dispatch_next_* runtime function for the specified
779 /// size \a IVSize and sign \a IVSigned.
780 llvm::FunctionCallee createDispatchNextFunction(unsigned IVSize,
781 bool IVSigned);
782
783 /// Returns __kmpc_dispatch_fini_* runtime function for the specified
784 /// size \a IVSize and sign \a IVSigned.
785 llvm::FunctionCallee createDispatchFiniFunction(unsigned IVSize,
786 bool IVSigned);
787
788 /// If the specified mangled name is not in the module, create and
789 /// return threadprivate cache object. This object is a pointer's worth of
790 /// storage that's reserved for use by the OpenMP runtime.
791 /// \param VD Threadprivate variable.
792 /// \return Cache variable for the specified threadprivate.
793 llvm::Constant *getOrCreateThreadPrivateCache(const VarDecl *VD);
794
795 /// Gets (if variable with the given name already exist) or creates
796 /// internal global variable with the specified Name. The created variable has
797 /// linkage CommonLinkage by default and is initialized by null value.
798 /// \param Ty Type of the global variable. If it is exist already the type
799 /// must be the same.
800 /// \param Name Name of the variable.
801 llvm::Constant *getOrCreateInternalVariable(llvm::Type *Ty,
802 const llvm::Twine &Name,
803 unsigned AddressSpace = 0);
804
805 /// Set of threadprivate variables with the generated initializer.
806 llvm::StringSet<> ThreadPrivateWithDefinition;
807
808 /// Set of declare target variables with the generated initializer.
809 llvm::StringSet<> DeclareTargetWithDefinition;
810
811 /// Emits initialization code for the threadprivate variables.
812 /// \param VDAddr Address of the global variable \a VD.
813 /// \param Ctor Pointer to a global init function for \a VD.
814 /// \param CopyCtor Pointer to a global copy function for \a VD.
815 /// \param Dtor Pointer to a global destructor function for \a VD.
816 /// \param Loc Location of threadprivate declaration.
817 void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr,
818 llvm::Value *Ctor, llvm::Value *CopyCtor,
819 llvm::Value *Dtor, SourceLocation Loc);
820
821 /// Emit the array initialization or deletion portion for user-defined mapper
822 /// code generation.
823 void emitUDMapperArrayInitOrDel(CodeGenFunction &MapperCGF,
824 llvm::Value *Handle, llvm::Value *BasePtr,
825 llvm::Value *Ptr, llvm::Value *Size,
826 llvm::Value *MapType, CharUnits ElementSize,
827 llvm::BasicBlock *ExitBB, bool IsInit);
828
829 struct TaskResultTy {
830 llvm::Value *NewTask = nullptr;
831 llvm::Function *TaskEntry = nullptr;
832 llvm::Value *NewTaskNewTaskTTy = nullptr;
833 LValue TDBase;
834 const RecordDecl *KmpTaskTQTyRD = nullptr;
835 llvm::Value *TaskDupFn = nullptr;
836 };
837 /// Emit task region for the task directive. The task region is emitted in
838 /// several steps:
839 /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
840 /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
841 /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
842 /// function:
843 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
844 /// TaskFunction(gtid, tt->part_id, tt->shareds);
845 /// return 0;
846 /// }
847 /// 2. Copy a list of shared variables to field shareds of the resulting
848 /// structure kmp_task_t returned by the previous call (if any).
849 /// 3. Copy a pointer to destructions function to field destructions of the
850 /// resulting structure kmp_task_t.
851 /// \param D Current task directive.
852 /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
853 /// /*part_id*/, captured_struct */*__context*/);
854 /// \param SharedsTy A type which contains references the shared variables.
855 /// \param Shareds Context with the list of shared variables from the \p
856 /// TaskFunction.
857 /// \param Data Additional data for task generation like tiednsee, final
858 /// state, list of privates etc.
859 TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
860 const OMPExecutableDirective &D,
861 llvm::Function *TaskFunction, QualType SharedsTy,
862 Address Shareds, const OMPTaskDataTy &Data);
863
864 /// Returns default address space for the constant firstprivates, 0 by
865 /// default.
866 virtual unsigned getDefaultFirstprivateAddressSpace() const { return 0; }
867
868 /// Emit code that pushes the trip count of loops associated with constructs
869 /// 'target teams distribute' and 'teams distribute parallel for'.
870 /// \param SizeEmitter Emits the int64 value for the number of iterations of
871 /// the associated loop.
872 void emitTargetNumIterationsCall(
873 CodeGenFunction &CGF, const OMPExecutableDirective &D,
874 llvm::Value *DeviceID,
875 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
876 const OMPLoopDirective &D)>
877 SizeEmitter);
878
879 /// Emit update for lastprivate conditional data.
880 void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal,
881 StringRef UniqueDeclName, LValue LVal,
882 SourceLocation Loc);
883
884 /// Returns the number of the elements and the address of the depobj
885 /// dependency array.
886 /// \return Number of elements in depobj array and the pointer to the array of
887 /// dependencies.
888 std::pair<llvm::Value *, LValue> getDepobjElements(CodeGenFunction &CGF,
889 LValue DepobjLVal,
890 SourceLocation Loc);
891
892public:
893 explicit CGOpenMPRuntime(CodeGenModule &CGM)
894 : CGOpenMPRuntime(CGM, ".", ".") {}
895 virtual ~CGOpenMPRuntime() {}
896 virtual void clear();
897
898 /// Emits code for OpenMP 'if' clause using specified \a CodeGen
899 /// function. Here is the logic:
900 /// if (Cond) {
901 /// ThenGen();
902 /// } else {
903 /// ElseGen();
904 /// }
905 void emitIfClause(CodeGenFunction &CGF, const Expr *Cond,
906 const RegionCodeGenTy &ThenGen,
907 const RegionCodeGenTy &ElseGen);
908
909 /// Checks if the \p Body is the \a CompoundStmt and returns its child
910 /// statement iff there is only one that is not evaluatable at the compile
911 /// time.
912 static const Stmt *getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body);
913
914 /// Get the platform-specific name separator.
915 std::string getName(ArrayRef<StringRef> Parts) const;
916
917 /// Emit code for the specified user defined reduction construct.
918 virtual void emitUserDefinedReduction(CodeGenFunction *CGF,
919 const OMPDeclareReductionDecl *D);
920 /// Get combiner/initializer for the specified user-defined reduction, if any.
921 virtual std::pair<llvm::Function *, llvm::Function *>
922 getUserDefinedReduction(const OMPDeclareReductionDecl *D);
923
924 /// Emit the function for the user defined mapper construct.
925 void emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
926 CodeGenFunction *CGF = nullptr);
927 /// Get the function for the specified user-defined mapper. If it does not
928 /// exist, create one.
929 llvm::Function *
930 getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D);
931
932 /// Emits outlined function for the specified OpenMP parallel directive
933 /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
934 /// kmp_int32 BoundID, struct context_vars*).
935 /// \param D OpenMP directive.
936 /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
937 /// \param InnermostKind Kind of innermost directive (for simple directives it
938 /// is a directive itself, for combined - its innermost directive).
939 /// \param CodeGen Code generation sequence for the \a D directive.
940 virtual llvm::Function *emitParallelOutlinedFunction(
941 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
942 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
943
944 /// Emits outlined function for the specified OpenMP teams directive
945 /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
946 /// kmp_int32 BoundID, struct context_vars*).
947 /// \param D OpenMP directive.
948 /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
949 /// \param InnermostKind Kind of innermost directive (for simple directives it
950 /// is a directive itself, for combined - its innermost directive).
951 /// \param CodeGen Code generation sequence for the \a D directive.
952 virtual llvm::Function *emitTeamsOutlinedFunction(
953 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
954 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen);
955
956 /// Emits outlined function for the OpenMP task directive \a D. This
957 /// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t*
958 /// TaskT).
959 /// \param D OpenMP directive.
960 /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
961 /// \param PartIDVar Variable for partition id in the current OpenMP untied
962 /// task region.
963 /// \param TaskTVar Variable for task_t argument.
964 /// \param InnermostKind Kind of innermost directive (for simple directives it
965 /// is a directive itself, for combined - its innermost directive).
966 /// \param CodeGen Code generation sequence for the \a D directive.
967 /// \param Tied true if task is generated for tied task, false otherwise.
968 /// \param NumberOfParts Number of parts in untied task. Ignored for tied
969 /// tasks.
970 ///
971 virtual llvm::Function *emitTaskOutlinedFunction(
972 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
973 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
974 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
975 bool Tied, unsigned &NumberOfParts);
976
977 /// Cleans up references to the objects in finished function.
978 ///
979 virtual void functionFinished(CodeGenFunction &CGF);
980
981 /// Emits code for parallel or serial call of the \a OutlinedFn with
982 /// variables captured in a record which address is stored in \a
983 /// CapturedStruct.
984 /// \param OutlinedFn Outlined function to be run in parallel threads. Type of
985 /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
986 /// \param CapturedVars A pointer to the record with the references to
987 /// variables used in \a OutlinedFn function.
988 /// \param IfCond Condition in the associated 'if' clause, if it was
989 /// specified, nullptr otherwise.
990 ///
991 virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
992 llvm::Function *OutlinedFn,
993 ArrayRef<llvm::Value *> CapturedVars,
994 const Expr *IfCond);
995
996 /// Emits a critical region.
997 /// \param CriticalName Name of the critical region.
998 /// \param CriticalOpGen Generator for the statement associated with the given
999 /// critical region.
1000 /// \param Hint Value of the 'hint' clause (optional).
1001 virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
1002 const RegionCodeGenTy &CriticalOpGen,
1003 SourceLocation Loc,
1004 const Expr *Hint = nullptr);
1005
1006 /// Emits a master region.
1007 /// \param MasterOpGen Generator for the statement associated with the given
1008 /// master region.
1009 virtual void emitMasterRegion(CodeGenFunction &CGF,
1010 const RegionCodeGenTy &MasterOpGen,
1011 SourceLocation Loc);
1012
1013 /// Emits code for a taskyield directive.
1014 virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc);
1015
1016 /// Emit a taskgroup region.
1017 /// \param TaskgroupOpGen Generator for the statement associated with the
1018 /// given taskgroup region.
1019 virtual void emitTaskgroupRegion(CodeGenFunction &CGF,
1020 const RegionCodeGenTy &TaskgroupOpGen,
1021 SourceLocation Loc);
1022
1023 /// Emits a single region.
1024 /// \param SingleOpGen Generator for the statement associated with the given
1025 /// single region.
1026 virtual void emitSingleRegion(CodeGenFunction &CGF,
1027 const RegionCodeGenTy &SingleOpGen,
1028 SourceLocation Loc,
1029 ArrayRef<const Expr *> CopyprivateVars,
1030 ArrayRef<const Expr *> DestExprs,
1031 ArrayRef<const Expr *> SrcExprs,
1032 ArrayRef<const Expr *> AssignmentOps);
1033
1034 /// Emit an ordered region.
1035 /// \param OrderedOpGen Generator for the statement associated with the given
1036 /// ordered region.
1037 virtual void emitOrderedRegion(CodeGenFunction &CGF,
1038 const RegionCodeGenTy &OrderedOpGen,
1039 SourceLocation Loc, bool IsThreads);
1040
1041 /// Emit an implicit/explicit barrier for OpenMP threads.
1042 /// \param Kind Directive for which this implicit barrier call must be
1043 /// generated. Must be OMPD_barrier for explicit barrier generation.
1044 /// \param EmitChecks true if need to emit checks for cancellation barriers.
1045 /// \param ForceSimpleCall true simple barrier call must be emitted, false if
1046 /// runtime class decides which one to emit (simple or with cancellation
1047 /// checks).
1048 ///
1049 virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
1050 OpenMPDirectiveKind Kind,
1051 bool EmitChecks = true,
1052 bool ForceSimpleCall = false);
1053
1054 /// Check if the specified \a ScheduleKind is static non-chunked.
1055 /// This kind of worksharing directive is emitted without outer loop.
1056 /// \param ScheduleKind Schedule kind specified in the 'schedule' clause.
1057 /// \param Chunked True if chunk is specified in the clause.
1058 ///
1059 virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
1060 bool Chunked) const;
1061
1062 /// Check if the specified \a ScheduleKind is static non-chunked.
1063 /// This kind of distribute directive is emitted without outer loop.
1064 /// \param ScheduleKind Schedule kind specified in the 'dist_schedule' clause.
1065 /// \param Chunked True if chunk is specified in the clause.
1066 ///
1067 virtual bool isStaticNonchunked(OpenMPDistScheduleClauseKind ScheduleKind,
1068 bool Chunked) const;
1069
1070 /// Check if the specified \a ScheduleKind is static chunked.
1071 /// \param ScheduleKind Schedule kind specified in the 'schedule' clause.
1072 /// \param Chunked True if chunk is specified in the clause.
1073 ///
1074 virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
1075 bool Chunked) const;
1076
1077 /// Check if the specified \a ScheduleKind is static non-chunked.
1078 /// \param ScheduleKind Schedule kind specified in the 'dist_schedule' clause.
1079 /// \param Chunked True if chunk is specified in the clause.
1080 ///
1081 virtual bool isStaticChunked(OpenMPDistScheduleClauseKind ScheduleKind,
1082 bool Chunked) const;
1083
1084 /// Check if the specified \a ScheduleKind is dynamic.
1085 /// This kind of worksharing directive is emitted without outer loop.
1086 /// \param ScheduleKind Schedule Kind specified in the 'schedule' clause.
1087 ///
1088 virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const;
1089
1090 /// struct with the values to be passed to the dispatch runtime function
1091 struct DispatchRTInput {
1092 /// Loop lower bound
1093 llvm::Value *LB = nullptr;
1094 /// Loop upper bound
1095 llvm::Value *UB = nullptr;
1096 /// Chunk size specified using 'schedule' clause (nullptr if chunk
1097 /// was not specified)
1098 llvm::Value *Chunk = nullptr;
1099 DispatchRTInput() = default;
1100 DispatchRTInput(llvm::Value *LB, llvm::Value *UB, llvm::Value *Chunk)
1101 : LB(LB), UB(UB), Chunk(Chunk) {}
1102 };
1103
1104 /// Call the appropriate runtime routine to initialize it before start
1105 /// of loop.
1106
1107 /// This is used for non static scheduled types and when the ordered
1108 /// clause is present on the loop construct.
1109 /// Depending on the loop schedule, it is necessary to call some runtime
1110 /// routine before start of the OpenMP loop to get the loop upper / lower
1111 /// bounds \a LB and \a UB and stride \a ST.
1112 ///
1113 /// \param CGF Reference to current CodeGenFunction.
1114 /// \param Loc Clang source location.
1115 /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
1116 /// \param IVSize Size of the iteration variable in bits.
1117 /// \param IVSigned Sign of the iteration variable.
1118 /// \param Ordered true if loop is ordered, false otherwise.
1119 /// \param DispatchValues struct containing llvm values for lower bound, upper
1120 /// bound, and chunk expression.
1121 /// For the default (nullptr) value, the chunk 1 will be used.
1122 ///
1123 virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc,
1124 const OpenMPScheduleTy &ScheduleKind,
1125 unsigned IVSize, bool IVSigned, bool Ordered,
1126 const DispatchRTInput &DispatchValues);
1127
1128 /// Struct with the values to be passed to the static runtime function
1129 struct StaticRTInput {
1130 /// Size of the iteration variable in bits.
1131 unsigned IVSize = 0;
1132 /// Sign of the iteration variable.
1133 bool IVSigned = false;
1134 /// true if loop is ordered, false otherwise.
1135 bool Ordered = false;
1136 /// Address of the output variable in which the flag of the last iteration
1137 /// is returned.
1138 Address IL = Address::invalid();
1139 /// Address of the output variable in which the lower iteration number is
1140 /// returned.
1141 Address LB = Address::invalid();
1142 /// Address of the output variable in which the upper iteration number is
1143 /// returned.
1144 Address UB = Address::invalid();
1145 /// Address of the output variable in which the stride value is returned
1146 /// necessary to generated the static_chunked scheduled loop.
1147 Address ST = Address::invalid();
1148 /// Value of the chunk for the static_chunked scheduled loop. For the
1149 /// default (nullptr) value, the chunk 1 will be used.
1150 llvm::Value *Chunk = nullptr;
1151 StaticRTInput(unsigned IVSize, bool IVSigned, bool Ordered, Address IL,
1152 Address LB, Address UB, Address ST,
1153 llvm::Value *Chunk = nullptr)
1154 : IVSize(IVSize), IVSigned(IVSigned), Ordered(Ordered), IL(IL), LB(LB),
1155 UB(UB), ST(ST), Chunk(Chunk) {}
1156 };
1157 /// Call the appropriate runtime routine to initialize it before start
1158 /// of loop.
1159 ///
1160 /// This is used only in case of static schedule, when the user did not
1161 /// specify a ordered clause on the loop construct.
1162 /// Depending on the loop schedule, it is necessary to call some runtime
1163 /// routine before start of the OpenMP loop to get the loop upper / lower
1164 /// bounds LB and UB and stride ST.
1165 ///
1166 /// \param CGF Reference to current CodeGenFunction.
1167 /// \param Loc Clang source location.
1168 /// \param DKind Kind of the directive.
1169 /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
1170 /// \param Values Input arguments for the construct.
1171 ///
1172 virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
1173 OpenMPDirectiveKind DKind,
1174 const OpenMPScheduleTy &ScheduleKind,
1175 const StaticRTInput &Values);
1176
1177 ///
1178 /// \param CGF Reference to current CodeGenFunction.
1179 /// \param Loc Clang source location.
1180 /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause.
1181 /// \param Values Input arguments for the construct.
1182 ///
1183 virtual void emitDistributeStaticInit(CodeGenFunction &CGF,
1184 SourceLocation Loc,
1185 OpenMPDistScheduleClauseKind SchedKind,
1186 const StaticRTInput &Values);
1187
1188 /// Call the appropriate runtime routine to notify that we finished
1189 /// iteration of the ordered loop with the dynamic scheduling.
1190 ///
1191 /// \param CGF Reference to current CodeGenFunction.
1192 /// \param Loc Clang source location.
1193 /// \param IVSize Size of the iteration variable in bits.
1194 /// \param IVSigned Sign of the iteration variable.
1195 ///
1196 virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF,
1197 SourceLocation Loc, unsigned IVSize,
1198 bool IVSigned);
1199
1200 /// Call the appropriate runtime routine to notify that we finished
1201 /// all the work with current loop.
1202 ///
1203 /// \param CGF Reference to current CodeGenFunction.
1204 /// \param Loc Clang source location.
1205 /// \param DKind Kind of the directive for which the static finish is emitted.
1206 ///
1207 virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc,
1208 OpenMPDirectiveKind DKind);
1209
1210 /// Call __kmpc_dispatch_next(
1211 /// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
1212 /// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
1213 /// kmp_int[32|64] *p_stride);
1214 /// \param IVSize Size of the iteration variable in bits.
1215 /// \param IVSigned Sign of the iteration variable.
1216 /// \param IL Address of the output variable in which the flag of the
1217 /// last iteration is returned.
1218 /// \param LB Address of the output variable in which the lower iteration
1219 /// number is returned.
1220 /// \param UB Address of the output variable in which the upper iteration
1221 /// number is returned.
1222 /// \param ST Address of the output variable in which the stride value is
1223 /// returned.
1224 virtual llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
1225 unsigned IVSize, bool IVSigned,
1226 Address IL, Address LB,
1227 Address UB, Address ST);
1228
1229 /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
1230 /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
1231 /// clause.
1232 /// \param NumThreads An integer value of threads.
1233 virtual void emitNumThreadsClause(CodeGenFunction &CGF,
1234 llvm::Value *NumThreads,
1235 SourceLocation Loc);
1236
1237 /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
1238 /// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
1239 virtual void emitProcBindClause(CodeGenFunction &CGF,
1240 llvm::omp::ProcBindKind ProcBind,
1241 SourceLocation Loc);
1242
1243 /// Returns address of the threadprivate variable for the current
1244 /// thread.
1245 /// \param VD Threadprivate variable.
1246 /// \param VDAddr Address of the global variable \a VD.
1247 /// \param Loc Location of the reference to threadprivate var.
1248 /// \return Address of the threadprivate variable for the current thread.
1249 virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF,
1250 const VarDecl *VD,
1251 Address VDAddr,
1252 SourceLocation Loc);
1253
1254 /// Returns the address of the variable marked as declare target with link
1255 /// clause OR as declare target with to clause and unified memory.
1256 virtual Address getAddrOfDeclareTargetVar(const VarDecl *VD);
1257
1258 /// Emit a code for initialization of threadprivate variable. It emits
1259 /// a call to runtime library which adds initial value to the newly created
1260 /// threadprivate variable (if it is not constant) and registers destructor
1261 /// for the variable (if any).
1262 /// \param VD Threadprivate variable.
1263 /// \param VDAddr Address of the global variable \a VD.
1264 /// \param Loc Location of threadprivate declaration.
1265 /// \param PerformInit true if initialization expression is not constant.
1266 virtual llvm::Function *
1267 emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr,
1268 SourceLocation Loc, bool PerformInit,
1269 CodeGenFunction *CGF = nullptr);
1270
1271 /// Emit a code for initialization of declare target variable.
1272 /// \param VD Declare target variable.
1273 /// \param Addr Address of the global variable \a VD.
1274 /// \param PerformInit true if initialization expression is not constant.
1275 virtual bool emitDeclareTargetVarDefinition(const VarDecl *VD,
1276 llvm::GlobalVariable *Addr,
1277 bool PerformInit);
1278
1279 /// Creates artificial threadprivate variable with name \p Name and type \p
1280 /// VarType.
1281 /// \param VarType Type of the artificial threadprivate variable.
1282 /// \param Name Name of the artificial threadprivate variable.
1283 virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
1284 QualType VarType,
1285 StringRef Name);
1286
1287 /// Emit flush of the variables specified in 'omp flush' directive.
1288 /// \param Vars List of variables to flush.
1289 virtual void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
1290 SourceLocation Loc, llvm::AtomicOrdering AO);
1291
1292 /// Emit task region for the task directive. The task region is
1293 /// emitted in several steps:
1294 /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
1295 /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1296 /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
1297 /// function:
1298 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
1299 /// TaskFunction(gtid, tt->part_id, tt->shareds);
1300 /// return 0;
1301 /// }
1302 /// 2. Copy a list of shared variables to field shareds of the resulting
1303 /// structure kmp_task_t returned by the previous call (if any).
1304 /// 3. Copy a pointer to destructions function to field destructions of the
1305 /// resulting structure kmp_task_t.
1306 /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid,
1307 /// kmp_task_t *new_task), where new_task is a resulting structure from
1308 /// previous items.
1309 /// \param D Current task directive.
1310 /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
1311 /// /*part_id*/, captured_struct */*__context*/);
1312 /// \param SharedsTy A type which contains references the shared variables.
1313 /// \param Shareds Context with the list of shared variables from the \p
1314 /// TaskFunction.
1315 /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
1316 /// otherwise.
1317 /// \param Data Additional data for task generation like tiednsee, final
1318 /// state, list of privates etc.
1319 virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
1320 const OMPExecutableDirective &D,
1321 llvm::Function *TaskFunction, QualType SharedsTy,
1322 Address Shareds, const Expr *IfCond,
1323 const OMPTaskDataTy &Data);
1324
1325 /// Emit task region for the taskloop directive. The taskloop region is
1326 /// emitted in several steps:
1327 /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
1328 /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1329 /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
1330 /// function:
1331 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
1332 /// TaskFunction(gtid, tt->part_id, tt->shareds);
1333 /// return 0;
1334 /// }
1335 /// 2. Copy a list of shared variables to field shareds of the resulting
1336 /// structure kmp_task_t returned by the previous call (if any).
1337 /// 3. Copy a pointer to destructions function to field destructions of the
1338 /// resulting structure kmp_task_t.
1339 /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t
1340 /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int
1341 /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task
1342 /// is a resulting structure from
1343 /// previous items.
1344 /// \param D Current task directive.
1345 /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
1346 /// /*part_id*/, captured_struct */*__context*/);
1347 /// \param SharedsTy A type which contains references the shared variables.
1348 /// \param Shareds Context with the list of shared variables from the \p
1349 /// TaskFunction.
1350 /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
1351 /// otherwise.
1352 /// \param Data Additional data for task generation like tiednsee, final
1353 /// state, list of privates etc.
1354 virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
1355 const OMPLoopDirective &D,
1356 llvm::Function *TaskFunction,
1357 QualType SharedsTy, Address Shareds,
1358 const Expr *IfCond, const OMPTaskDataTy &Data);
1359
1360 /// Emit code for the directive that does not require outlining.
1361 ///
1362 /// \param InnermostKind Kind of innermost directive (for simple directives it
1363 /// is a directive itself, for combined - its innermost directive).
1364 /// \param CodeGen Code generation sequence for the \a D directive.
1365 /// \param HasCancel true if region has inner cancel directive, false
1366 /// otherwise.
1367 virtual void emitInlinedDirective(CodeGenFunction &CGF,
1368 OpenMPDirectiveKind InnermostKind,
1369 const RegionCodeGenTy &CodeGen,
1370 bool HasCancel = false);
1371
1372 /// Emits reduction function.
1373 /// \param ArgsType Array type containing pointers to reduction variables.
1374 /// \param Privates List of private copies for original reduction arguments.
1375 /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
1376 /// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
1377 /// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
1378 /// or 'operator binop(LHS, RHS)'.
1379 llvm::Function *emitReductionFunction(SourceLocation Loc,
1380 llvm::Type *ArgsType,
1381 ArrayRef<const Expr *> Privates,
1382 ArrayRef<const Expr *> LHSExprs,
1383 ArrayRef<const Expr *> RHSExprs,
1384 ArrayRef<const Expr *> ReductionOps);
1385
1386 /// Emits single reduction combiner
1387 void emitSingleReductionCombiner(CodeGenFunction &CGF,
1388 const Expr *ReductionOp,
1389 const Expr *PrivateRef,
1390 const DeclRefExpr *LHS,
1391 const DeclRefExpr *RHS);
1392
1393 struct ReductionOptionsTy {
1394 bool WithNowait;
1395 bool SimpleReduction;
1396 OpenMPDirectiveKind ReductionKind;
1397 };
1398 /// Emit a code for reduction clause. Next code should be emitted for
1399 /// reduction:
1400 /// \code
1401 ///
1402 /// static kmp_critical_name lock = { 0 };
1403 ///
1404 /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
1405 /// ...
1406 /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
1407 /// ...
1408 /// }
1409 ///
1410 /// ...
1411 /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
1412 /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
1413 /// RedList, reduce_func, &<lock>)) {
1414 /// case 1:
1415 /// ...
1416 /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
1417 /// ...
1418 /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
1419 /// break;
1420 /// case 2:
1421 /// ...
1422 /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
1423 /// ...
1424 /// break;
1425 /// default:;
1426 /// }
1427 /// \endcode
1428 ///
1429 /// \param Privates List of private copies for original reduction arguments.
1430 /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
1431 /// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
1432 /// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
1433 /// or 'operator binop(LHS, RHS)'.
1434 /// \param Options List of options for reduction codegen:
1435 /// WithNowait true if parent directive has also nowait clause, false
1436 /// otherwise.
1437 /// SimpleReduction Emit reduction operation only. Used for omp simd
1438 /// directive on the host.
1439 /// ReductionKind The kind of reduction to perform.
1440 virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
1441 ArrayRef<const Expr *> Privates,
1442 ArrayRef<const Expr *> LHSExprs,
1443 ArrayRef<const Expr *> RHSExprs,
1444 ArrayRef<const Expr *> ReductionOps,
1445 ReductionOptionsTy Options);
1446
1447 /// Emit a code for initialization of task reduction clause. Next code
1448 /// should be emitted for reduction:
1449 /// \code
1450 ///
1451 /// _taskred_item_t red_data[n];
1452 /// ...
1453 /// red_data[i].shar = &shareds[i];
1454 /// red_data[i].orig = &origs[i];
1455 /// red_data[i].size = sizeof(origs[i]);
1456 /// red_data[i].f_init = (void*)RedInit<i>;
1457 /// red_data[i].f_fini = (void*)RedDest<i>;
1458 /// red_data[i].f_comb = (void*)RedOp<i>;
1459 /// red_data[i].flags = <Flag_i>;
1460 /// ...
1461 /// void* tg1 = __kmpc_taskred_init(gtid, n, red_data);
1462 /// \endcode
1463 /// For reduction clause with task modifier it emits the next call:
1464 /// \code
1465 ///
1466 /// _taskred_item_t red_data[n];
1467 /// ...
1468 /// red_data[i].shar = &shareds[i];
1469 /// red_data[i].orig = &origs[i];
1470 /// red_data[i].size = sizeof(origs[i]);
1471 /// red_data[i].f_init = (void*)RedInit<i>;
1472 /// red_data[i].f_fini = (void*)RedDest<i>;
1473 /// red_data[i].f_comb = (void*)RedOp<i>;
1474 /// red_data[i].flags = <Flag_i>;
1475 /// ...
1476 /// void* tg1 = __kmpc_taskred_modifier_init(loc, gtid, is_worksharing, n,
1477 /// red_data);
1478 /// \endcode
1479 /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations.
1480 /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations.
1481 /// \param Data Additional data for task generation like tiedness, final
1482 /// state, list of privates, reductions etc.
1483 virtual llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF,
1484 SourceLocation Loc,
1485 ArrayRef<const Expr *> LHSExprs,
1486 ArrayRef<const Expr *> RHSExprs,
1487 const OMPTaskDataTy &Data);
1488
1489 /// Emits the following code for reduction clause with task modifier:
1490 /// \code
1491 /// __kmpc_task_reduction_modifier_fini(loc, gtid, is_worksharing);
1492 /// \endcode
1493 virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc,
1494 bool IsWorksharingReduction);
1495
1496 /// Required to resolve existing problems in the runtime. Emits threadprivate
1497 /// variables to store the size of the VLAs/array sections for
1498 /// initializer/combiner/finalizer functions.
1499 /// \param RCG Allows to reuse an existing data for the reductions.
1500 /// \param N Reduction item for which fixups must be emitted.
1501 virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc,
1502 ReductionCodeGen &RCG, unsigned N);
1503
1504 /// Get the address of `void *` type of the privatue copy of the reduction
1505 /// item specified by the \p SharedLVal.
1506 /// \param ReductionsPtr Pointer to the reduction data returned by the
1507 /// emitTaskReductionInit function.
1508 /// \param SharedLVal Address of the original reduction item.
1509 virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc,
1510 llvm::Value *ReductionsPtr,
1511 LValue SharedLVal);
1512
1513 /// Emit code for 'taskwait' directive.
1514 virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc);
1515
1516 /// Emit code for 'cancellation point' construct.
1517 /// \param CancelRegion Region kind for which the cancellation point must be
1518 /// emitted.
1519 ///
1520 virtual void emitCancellationPointCall(CodeGenFunction &CGF,
1521 SourceLocation Loc,
1522 OpenMPDirectiveKind CancelRegion);
1523
1524 /// Emit code for 'cancel' construct.
1525 /// \param IfCond Condition in the associated 'if' clause, if it was
1526 /// specified, nullptr otherwise.
1527 /// \param CancelRegion Region kind for which the cancel must be emitted.
1528 ///
1529 virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
1530 const Expr *IfCond,
1531 OpenMPDirectiveKind CancelRegion);
1532
1533 /// Emit outilined function for 'target' directive.
1534 /// \param D Directive to emit.
1535 /// \param ParentName Name of the function that encloses the target region.
1536 /// \param OutlinedFn Outlined function value to be defined by this call.
1537 /// \param OutlinedFnID Outlined function ID value to be defined by this call.
1538 /// \param IsOffloadEntry True if the outlined function is an offload entry.
1539 /// \param CodeGen Code generation sequence for the \a D directive.
1540 /// An outlined function may not be an entry if, e.g. the if clause always
1541 /// evaluates to false.
1542 virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D,
1543 StringRef ParentName,
1544 llvm::Function *&OutlinedFn,
1545 llvm::Constant *&OutlinedFnID,
1546 bool IsOffloadEntry,
1547 const RegionCodeGenTy &CodeGen);
1548
1549 /// Emit the target offloading code associated with \a D. The emitted
1550 /// code attempts offloading the execution to the device, an the event of
1551 /// a failure it executes the host version outlined in \a OutlinedFn.
1552 /// \param D Directive to emit.
1553 /// \param OutlinedFn Host version of the code to be offloaded.
1554 /// \param OutlinedFnID ID of host version of the code to be offloaded.
1555 /// \param IfCond Expression evaluated in if clause associated with the target
1556 /// directive, or null if no if clause is used.
1557 /// \param Device Expression evaluated in device clause associated with the
1558 /// target directive, or null if no device clause is used and device modifier.
1559 /// \param SizeEmitter Callback to emit number of iterations for loop-based
1560 /// directives.
1561 virtual void emitTargetCall(
1562 CodeGenFunction &CGF, const OMPExecutableDirective &D,
1563 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
1564 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device,
1565 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
1566 const OMPLoopDirective &D)>
1567 SizeEmitter);
1568
1569 /// Emit the target regions enclosed in \a GD function definition or
1570 /// the function itself in case it is a valid device function. Returns true if
1571 /// \a GD was dealt with successfully.
1572 /// \param GD Function to scan.
1573 virtual bool emitTargetFunctions(GlobalDecl GD);
1574
1575 /// Emit the global variable if it is a valid device global variable.
1576 /// Returns true if \a GD was dealt with successfully.
1577 /// \param GD Variable declaration to emit.
1578 virtual bool emitTargetGlobalVariable(GlobalDecl GD);
1579
1580 /// Checks if the provided global decl \a GD is a declare target variable and
1581 /// registers it when emitting code for the host.
1582 virtual void registerTargetGlobalVariable(const VarDecl *VD,
1583 llvm::Constant *Addr);
1584
1585 /// Registers provided target firstprivate variable as global on the
1586 /// target.
1587 llvm::Constant *registerTargetFirstprivateCopy(CodeGenFunction &CGF,
1588 const VarDecl *VD);
1589
1590 /// Emit the global \a GD if it is meaningful for the target. Returns
1591 /// if it was emitted successfully.
1592 /// \param GD Global to scan.
1593 virtual bool emitTargetGlobal(GlobalDecl GD);
1594
1595 /// Creates and returns a registration function for when at least one
1596 /// requires directives was used in the current module.
1597 llvm::Function *emitRequiresDirectiveRegFun();
1598
1599 /// Creates all the offload entries in the current compilation unit
1600 /// along with the associated metadata.
1601 void createOffloadEntriesAndInfoMetadata();
1602
1603 /// Emits code for teams call of the \a OutlinedFn with
1604 /// variables captured in a record which address is stored in \a
1605 /// CapturedStruct.
1606 /// \param OutlinedFn Outlined function to be run by team masters. Type of
1607 /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
1608 /// \param CapturedVars A pointer to the record with the references to
1609 /// variables used in \a OutlinedFn function.
1610 ///
1611 virtual void emitTeamsCall(CodeGenFunction &CGF,
1612 const OMPExecutableDirective &D,
1613 SourceLocation Loc, llvm::Function *OutlinedFn,
1614 ArrayRef<llvm::Value *> CapturedVars);
1615
1616 /// Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32
1617 /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code
1618 /// for num_teams clause.
1619 /// \param NumTeams An integer expression of teams.
1620 /// \param ThreadLimit An integer expression of threads.
1621 virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams,
1622 const Expr *ThreadLimit, SourceLocation Loc);
1623
1624 /// Struct that keeps all the relevant information that should be kept
1625 /// throughout a 'target data' region.
1626 class TargetDataInfo {
1627 /// Set to true if device pointer information have to be obtained.
1628 bool RequiresDevicePointerInfo = false;
1629 /// Set to true if Clang emits separate runtime calls for the beginning and
1630 /// end of the region. These calls might have separate map type arrays.
1631 bool SeparateBeginEndCalls = false;
1632
1633 public:
1634 /// The array of base pointer passed to the runtime library.
1635 llvm::Value *BasePointersArray = nullptr;
1636 /// The array of section pointers passed to the runtime library.
1637 llvm::Value *PointersArray = nullptr;
1638 /// The array of sizes passed to the runtime library.
1639 llvm::Value *SizesArray = nullptr;
1640 /// The array of map types passed to the runtime library for the beginning
1641 /// of the region or for the entire region if there are no separate map
1642 /// types for the region end.
1643 llvm::Value *MapTypesArray = nullptr;
1644 /// The array of map types passed to the runtime library for the end of the
1645 /// region, or nullptr if there are no separate map types for the region
1646 /// end.
1647 llvm::Value *MapTypesArrayEnd = nullptr;
1648 /// The array of user-defined mappers passed to the runtime library.
1649 llvm::Value *MappersArray = nullptr;
1650 /// Indicate whether any user-defined mapper exists.
1651 bool HasMapper = false;
1652 /// The total number of pointers passed to the runtime library.
1653 unsigned NumberOfPtrs = 0u;
1654 /// Map between the a declaration of a capture and the corresponding base
1655 /// pointer address where the runtime returns the device pointers.
1656 llvm::DenseMap<const ValueDecl *, Address> CaptureDeviceAddrMap;
1657
1658 explicit TargetDataInfo() {}
1659 explicit TargetDataInfo(bool RequiresDevicePointerInfo,
1660 bool SeparateBeginEndCalls)
1661 : RequiresDevicePointerInfo(RequiresDevicePointerInfo),
1662 SeparateBeginEndCalls(SeparateBeginEndCalls) {}
1663 /// Clear information about the data arrays.
1664 void clearArrayInfo() {
1665 BasePointersArray = nullptr;
1666 PointersArray = nullptr;
1667 SizesArray = nullptr;
1668 MapTypesArray = nullptr;
1669 MapTypesArrayEnd = nullptr;
1670 MappersArray = nullptr;
1671 HasMapper = false;
1672 NumberOfPtrs = 0u;
1673 }
1674 /// Return true if the current target data information has valid arrays.
1675 bool isValid() {
1676 return BasePointersArray && PointersArray && SizesArray &&
1677 MapTypesArray && (!HasMapper || MappersArray) && NumberOfPtrs;
1678 }
1679 bool requiresDevicePointerInfo() { return RequiresDevicePointerInfo; }
1680 bool separateBeginEndCalls() { return SeparateBeginEndCalls; }
1681 };
1682
1683 /// Emit the target data mapping code associated with \a D.
1684 /// \param D Directive to emit.
1685 /// \param IfCond Expression evaluated in if clause associated with the
1686 /// target directive, or null if no device clause is used.
1687 /// \param Device Expression evaluated in device clause associated with the
1688 /// target directive, or null if no device clause is used.
1689 /// \param Info A record used to store information that needs to be preserved
1690 /// until the region is closed.
1691 virtual void emitTargetDataCalls(CodeGenFunction &CGF,
1692 const OMPExecutableDirective &D,
1693 const Expr *IfCond, const Expr *Device,
1694 const RegionCodeGenTy &CodeGen,
1695 TargetDataInfo &Info);
1696
1697 /// Emit the data mapping/movement code associated with the directive
1698 /// \a D that should be of the form 'target [{enter|exit} data | update]'.
1699 /// \param D Directive to emit.
1700 /// \param IfCond Expression evaluated in if clause associated with the target
1701 /// directive, or null if no if clause is used.
1702 /// \param Device Expression evaluated in device clause associated with the
1703 /// target directive, or null if no device clause is used.
1704 virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF,
1705 const OMPExecutableDirective &D,
1706 const Expr *IfCond,
1707 const Expr *Device);
1708
1709 /// Marks function \a Fn with properly mangled versions of vector functions.
1710 /// \param FD Function marked as 'declare simd'.
1711 /// \param Fn LLVM function that must be marked with 'declare simd'
1712 /// attributes.
1713 virtual void emitDeclareSimdFunction(const FunctionDecl *FD,
1714 llvm::Function *Fn);
1715
1716 /// Emit initialization for doacross loop nesting support.
1717 /// \param D Loop-based construct used in doacross nesting construct.
1718 virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D,
1719 ArrayRef<Expr *> NumIterations);
1720
1721 /// Emit code for doacross ordered directive with 'depend' clause.
1722 /// \param C 'depend' clause with 'sink|source' dependency kind.
1723 virtual void emitDoacrossOrdered(CodeGenFunction &CGF,
1724 const OMPDependClause *C);
1725
1726 /// Translates the native parameter of outlined function if this is required
1727 /// for target.
1728 /// \param FD Field decl from captured record for the parameter.
1729 /// \param NativeParam Parameter itself.
1730 virtual const VarDecl *translateParameter(const FieldDecl *FD,
1731 const VarDecl *NativeParam) const {
1732 return NativeParam;
1733 }
1734
1735 /// Gets the address of the native argument basing on the address of the
1736 /// target-specific parameter.
1737 /// \param NativeParam Parameter itself.
1738 /// \param TargetParam Corresponding target-specific parameter.
1739 virtual Address getParameterAddress(CodeGenFunction &CGF,
1740 const VarDecl *NativeParam,
1741 const VarDecl *TargetParam) const;
1742
1743 /// Choose default schedule type and chunk value for the
1744 /// dist_schedule clause.
1745 virtual void getDefaultDistScheduleAndChunk(CodeGenFunction &CGF,
1746 const OMPLoopDirective &S, OpenMPDistScheduleClauseKind &ScheduleKind,
1747 llvm::Value *&Chunk) const {}
1748
1749 /// Choose default schedule type and chunk value for the
1750 /// schedule clause.
1751 virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF,
1752 const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind,
1753 const Expr *&ChunkExpr) const;
1754
1755 /// Emits call of the outlined function with the provided arguments,
1756 /// translating these arguments to correct target-specific arguments.
1757 virtual void
1758 emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc,
1759 llvm::FunctionCallee OutlinedFn,
1760 ArrayRef<llvm::Value *> Args = llvm::None) const;
1761
1762 /// Emits OpenMP-specific function prolog.
1763 /// Required for device constructs.
1764 virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D);
1765
1766 /// Gets the OpenMP-specific address of the local variable.
1767 virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF,
1768 const VarDecl *VD);
1769
1770 /// Marks the declaration as already emitted for the device code and returns
1771 /// true, if it was marked already, and false, otherwise.
1772 bool markAsGlobalTarget(GlobalDecl GD);
1773
1774 /// Emit deferred declare target variables marked for deferred emission.
1775 void emitDeferredTargetDecls() const;
1776
1777 /// Adjust some parameters for the target-based directives, like addresses of
1778 /// the variables captured by reference in lambdas.
1779 virtual void
1780 adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF,
1781 const OMPExecutableDirective &D) const;
1782
1783 /// Perform check on requires decl to ensure that target architecture
1784 /// supports unified addressing
1785 virtual void processRequiresDirective(const OMPRequiresDecl *D);
1786
1787 /// Gets default memory ordering as specified in requires directive.
1788 llvm::AtomicOrdering getDefaultMemoryOrdering() const;
1789
1790 /// Checks if the variable has associated OMPAllocateDeclAttr attribute with
1791 /// the predefined allocator and translates it into the corresponding address
1792 /// space.
1793 virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS);
1794
1795 /// Return whether the unified_shared_memory has been specified.
1796 bool hasRequiresUnifiedSharedMemory() const;
1797
1798 /// Checks if the \p VD variable is marked as nontemporal declaration in
1799 /// current context.
1800 bool isNontemporalDecl(const ValueDecl *VD) const;
1801
1802 /// Create specialized alloca to handle lastprivate conditionals.
1803 Address emitLastprivateConditionalInit(CodeGenFunction &CGF,
1804 const VarDecl *VD);
1805
1806 /// Checks if the provided \p LVal is lastprivate conditional and emits the
1807 /// code to update the value of the original variable.
1808 /// \code
1809 /// lastprivate(conditional: a)
1810 /// ...
1811 /// <type> a;
1812 /// lp_a = ...;
1813 /// #pragma omp critical(a)
1814 /// if (last_iv_a <= iv) {
1815 /// last_iv_a = iv;
1816 /// global_a = lp_a;
1817 /// }
1818 /// \endcode
1819 virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF,
1820 const Expr *LHS);
1821
1822 /// Checks if the lastprivate conditional was updated in inner region and
1823 /// writes the value.
1824 /// \code
1825 /// lastprivate(conditional: a)
1826 /// ...
1827 /// <type> a;bool Fired = false;
1828 /// #pragma omp ... shared(a)
1829 /// {
1830 /// lp_a = ...;
1831 /// Fired = true;
1832 /// }
1833 /// if (Fired) {
1834 /// #pragma omp critical(a)
1835 /// if (last_iv_a <= iv) {
1836 /// last_iv_a = iv;
1837 /// global_a = lp_a;
1838 /// }
1839 /// Fired = false;
1840 /// }
1841 /// \endcode
1842 virtual void checkAndEmitSharedLastprivateConditional(
1843 CodeGenFunction &CGF, const OMPExecutableDirective &D,
1844 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls);
1845
1846 /// Gets the address of the global copy used for lastprivate conditional
1847 /// update, if any.
1848 /// \param PrivLVal LValue for the private copy.
1849 /// \param VD Original lastprivate declaration.
1850 virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF,
1851 LValue PrivLVal,
1852 const VarDecl *VD,
1853 SourceLocation Loc);
1854
1855 /// Emits list of dependecies based on the provided data (array of
1856 /// dependence/expression pairs).
1857 /// \returns Pointer to the first element of the array casted to VoidPtr type.
1858 std::pair<llvm::Value *, Address>
1859 emitDependClause(CodeGenFunction &CGF,
1860 ArrayRef<OMPTaskDataTy::DependData> Dependencies,
1861 SourceLocation Loc);
1862
1863 /// Emits list of dependecies based on the provided data (array of
1864 /// dependence/expression pairs) for depobj construct. In this case, the
1865 /// variable is allocated in dynamically. \returns Pointer to the first
1866 /// element of the array casted to VoidPtr type.
1867 Address emitDepobjDependClause(CodeGenFunction &CGF,
1868 const OMPTaskDataTy::DependData &Dependencies,
1869 SourceLocation Loc);
1870
1871 /// Emits the code to destroy the dependency object provided in depobj
1872 /// directive.
1873 void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal,
1874 SourceLocation Loc);
1875
1876 /// Updates the dependency kind in the specified depobj object.
1877 /// \param DepobjLVal LValue for the main depobj object.
1878 /// \param NewDepKind New dependency kind.
1879 void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal,
1880 OpenMPDependClauseKind NewDepKind, SourceLocation Loc);
1881
1882 /// Initializes user defined allocators specified in the uses_allocators
1883 /// clauses.
1884 void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator,
1885 const Expr *AllocatorTraits);
1886
1887 /// Destroys user defined allocators specified in the uses_allocators clause.
1888 void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator);
1889
1890 /// Returns true if the variable is a local variable in untied task.
1891 bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const;
1892};
1893
1894/// Class supports emissionof SIMD-only code.
1895class CGOpenMPSIMDRuntime final : public CGOpenMPRuntime {
1896public:
1897 explicit CGOpenMPSIMDRuntime(CodeGenModule &CGM) : CGOpenMPRuntime(CGM) {}
1898 ~CGOpenMPSIMDRuntime() override {}
1899
1900 /// Emits outlined function for the specified OpenMP parallel directive
1901 /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
1902 /// kmp_int32 BoundID, struct context_vars*).
1903 /// \param D OpenMP directive.
1904 /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
1905 /// \param InnermostKind Kind of innermost directive (for simple directives it
1906 /// is a directive itself, for combined - its innermost directive).
1907 /// \param CodeGen Code generation sequence for the \a D directive.
1908 llvm::Function *
1909 emitParallelOutlinedFunction(const OMPExecutableDirective &D,
1910 const VarDecl *ThreadIDVar,
1911 OpenMPDirectiveKind InnermostKind,
1912 const RegionCodeGenTy &CodeGen) override;
1913
1914 /// Emits outlined function for the specified OpenMP teams directive
1915 /// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
1916 /// kmp_int32 BoundID, struct context_vars*).
1917 /// \param D OpenMP directive.
1918 /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
1919 /// \param InnermostKind Kind of innermost directive (for simple directives it
1920 /// is a directive itself, for combined - its innermost directive).
1921 /// \param CodeGen Code generation sequence for the \a D directive.
1922 llvm::Function *
1923 emitTeamsOutlinedFunction(const OMPExecutableDirective &D,
1924 const VarDecl *ThreadIDVar,
1925 OpenMPDirectiveKind InnermostKind,
1926 const RegionCodeGenTy &CodeGen) override;
1927
1928 /// Emits outlined function for the OpenMP task directive \a D. This
1929 /// outlined function has type void(*)(kmp_int32 ThreadID, struct task_t*
1930 /// TaskT).
1931 /// \param D OpenMP directive.
1932 /// \param ThreadIDVar Variable for thread id in the current OpenMP region.
1933 /// \param PartIDVar Variable for partition id in the current OpenMP untied
1934 /// task region.
1935 /// \param TaskTVar Variable for task_t argument.
1936 /// \param InnermostKind Kind of innermost directive (for simple directives it
1937 /// is a directive itself, for combined - its innermost directive).
1938 /// \param CodeGen Code generation sequence for the \a D directive.
1939 /// \param Tied true if task is generated for tied task, false otherwise.
1940 /// \param NumberOfParts Number of parts in untied task. Ignored for tied
1941 /// tasks.
1942 ///
1943 llvm::Function *emitTaskOutlinedFunction(
1944 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1945 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1946 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1947 bool Tied, unsigned &NumberOfParts) override;
1948
1949 /// Emits code for parallel or serial call of the \a OutlinedFn with
1950 /// variables captured in a record which address is stored in \a
1951 /// CapturedStruct.
1952 /// \param OutlinedFn Outlined function to be run in parallel threads. Type of
1953 /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
1954 /// \param CapturedVars A pointer to the record with the references to
1955 /// variables used in \a OutlinedFn function.
1956 /// \param IfCond Condition in the associated 'if' clause, if it was
1957 /// specified, nullptr otherwise.
1958 ///
1959 void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1960 llvm::Function *OutlinedFn,
1961 ArrayRef<llvm::Value *> CapturedVars,
1962 const Expr *IfCond) override;
1963
1964 /// Emits a critical region.
1965 /// \param CriticalName Name of the critical region.
1966 /// \param CriticalOpGen Generator for the statement associated with the given
1967 /// critical region.
1968 /// \param Hint Value of the 'hint' clause (optional).
1969 void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
1970 const RegionCodeGenTy &CriticalOpGen,
1971 SourceLocation Loc,
1972 const Expr *Hint = nullptr) override;
1973
1974 /// Emits a master region.
1975 /// \param MasterOpGen Generator for the statement associated with the given
1976 /// master region.
1977 void emitMasterRegion(CodeGenFunction &CGF,
1978 const RegionCodeGenTy &MasterOpGen,
1979 SourceLocation Loc) override;
1980
1981 /// Emits code for a taskyield directive.
1982 void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override;
1983
1984 /// Emit a taskgroup region.
1985 /// \param TaskgroupOpGen Generator for the statement associated with the
1986 /// given taskgroup region.
1987 void emitTaskgroupRegion(CodeGenFunction &CGF,
1988 const RegionCodeGenTy &TaskgroupOpGen,
1989 SourceLocation Loc) override;
1990
1991 /// Emits a single region.
1992 /// \param SingleOpGen Generator for the statement associated with the given
1993 /// single region.
1994 void emitSingleRegion(CodeGenFunction &CGF,
1995 const RegionCodeGenTy &SingleOpGen, SourceLocation Loc,
1996 ArrayRef<const Expr *> CopyprivateVars,
1997 ArrayRef<const Expr *> DestExprs,
1998 ArrayRef<const Expr *> SrcExprs,
1999 ArrayRef<const Expr *> AssignmentOps) override;
2000
2001 /// Emit an ordered region.
2002 /// \param OrderedOpGen Generator for the statement associated with the given
2003 /// ordered region.
2004 void emitOrderedRegion(CodeGenFunction &CGF,
2005 const RegionCodeGenTy &OrderedOpGen,
2006 SourceLocation Loc, bool IsThreads) override;
2007
2008 /// Emit an implicit/explicit barrier for OpenMP threads.
2009 /// \param Kind Directive for which this implicit barrier call must be
2010 /// generated. Must be OMPD_barrier for explicit barrier generation.
2011 /// \param EmitChecks true if need to emit checks for cancellation barriers.
2012 /// \param ForceSimpleCall true simple barrier call must be emitted, false if
2013 /// runtime class decides which one to emit (simple or with cancellation
2014 /// checks).
2015 ///
2016 void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
2017 OpenMPDirectiveKind Kind, bool EmitChecks = true,
2018 bool ForceSimpleCall = false) override;
2019
2020 /// This is used for non static scheduled types and when the ordered
2021 /// clause is present on the loop construct.
2022 /// Depending on the loop schedule, it is necessary to call some runtime
2023 /// routine before start of the OpenMP loop to get the loop upper / lower
2024 /// bounds \a LB and \a UB and stride \a ST.
2025 ///
2026 /// \param CGF Reference to current CodeGenFunction.
2027 /// \param Loc Clang source location.
2028 /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
2029 /// \param IVSize Size of the iteration variable in bits.
2030 /// \param IVSigned Sign of the iteration variable.
2031 /// \param Ordered true if loop is ordered, false otherwise.
2032 /// \param DispatchValues struct containing llvm values for lower bound, upper
2033 /// bound, and chunk expression.
2034 /// For the default (nullptr) value, the chunk 1 will be used.
2035 ///
2036 void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc,
2037 const OpenMPScheduleTy &ScheduleKind,
2038 unsigned IVSize, bool IVSigned, bool Ordered,
2039 const DispatchRTInput &DispatchValues) override;
2040
2041 /// Call the appropriate runtime routine to initialize it before start
2042 /// of loop.
2043 ///
2044 /// This is used only in case of static schedule, when the user did not
2045 /// specify a ordered clause on the loop construct.
2046 /// Depending on the loop schedule, it is necessary to call some runtime
2047 /// routine before start of the OpenMP loop to get the loop upper / lower
2048 /// bounds LB and UB and stride ST.
2049 ///
2050 /// \param CGF Reference to current CodeGenFunction.
2051 /// \param Loc Clang source location.
2052 /// \param DKind Kind of the directive.
2053 /// \param ScheduleKind Schedule kind, specified by the 'schedule' clause.
2054 /// \param Values Input arguments for the construct.
2055 ///
2056 void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
2057 OpenMPDirectiveKind DKind,
2058 const OpenMPScheduleTy &ScheduleKind,
2059 const StaticRTInput &Values) override;
2060
2061 ///
2062 /// \param CGF Reference to current CodeGenFunction.
2063 /// \param Loc Clang source location.
2064 /// \param SchedKind Schedule kind, specified by the 'dist_schedule' clause.
2065 /// \param Values Input arguments for the construct.
2066 ///
2067 void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
2068 OpenMPDistScheduleClauseKind SchedKind,
2069 const StaticRTInput &Values) override;
2070
2071 /// Call the appropriate runtime routine to notify that we finished
2072 /// iteration of the ordered loop with the dynamic scheduling.
2073 ///
2074 /// \param CGF Reference to current CodeGenFunction.
2075 /// \param Loc Clang source location.
2076 /// \param IVSize Size of the iteration variable in bits.
2077 /// \param IVSigned Sign of the iteration variable.
2078 ///
2079 void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc,
2080 unsigned IVSize, bool IVSigned) override;
2081
2082 /// Call the appropriate runtime routine to notify that we finished
2083 /// all the work with current loop.
2084 ///
2085 /// \param CGF Reference to current CodeGenFunction.
2086 /// \param Loc Clang source location.
2087 /// \param DKind Kind of the directive for which the static finish is emitted.
2088 ///
2089 void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc,
2090 OpenMPDirectiveKind DKind) override;
2091
2092 /// Call __kmpc_dispatch_next(
2093 /// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2094 /// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2095 /// kmp_int[32|64] *p_stride);
2096 /// \param IVSize Size of the iteration variable in bits.
2097 /// \param IVSigned Sign of the iteration variable.
2098 /// \param IL Address of the output variable in which the flag of the
2099 /// last iteration is returned.
2100 /// \param LB Address of the output variable in which the lower iteration
2101 /// number is returned.
2102 /// \param UB Address of the output variable in which the upper iteration
2103 /// number is returned.
2104 /// \param ST Address of the output variable in which the stride value is
2105 /// returned.
2106 llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
2107 unsigned IVSize, bool IVSigned, Address IL,
2108 Address LB, Address UB, Address ST) override;
2109
2110 /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
2111 /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
2112 /// clause.
2113 /// \param NumThreads An integer value of threads.
2114 void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads,
2115 SourceLocation Loc) override;
2116
2117 /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
2118 /// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
2119 void emitProcBindClause(CodeGenFunction &CGF,
2120 llvm::omp::ProcBindKind ProcBind,
2121 SourceLocation Loc) override;
2122
2123 /// Returns address of the threadprivate variable for the current
2124 /// thread.
2125 /// \param VD Threadprivate variable.
2126 /// \param VDAddr Address of the global variable \a VD.
2127 /// \param Loc Location of the reference to threadprivate var.
2128 /// \return Address of the threadprivate variable for the current thread.
2129 Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD,
2130 Address VDAddr, SourceLocation Loc) override;
2131
2132 /// Emit a code for initialization of threadprivate variable. It emits
2133 /// a call to runtime library which adds initial value to the newly created
2134 /// threadprivate variable (if it is not constant) and registers destructor
2135 /// for the variable (if any).
2136 /// \param VD Threadprivate variable.
2137 /// \param VDAddr Address of the global variable \a VD.
2138 /// \param Loc Location of threadprivate declaration.
2139 /// \param PerformInit true if initialization expression is not constant.
2140 llvm::Function *
2141 emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr,
2142 SourceLocation Loc, bool PerformInit,
2143 CodeGenFunction *CGF = nullptr) override;
2144
2145 /// Creates artificial threadprivate variable with name \p Name and type \p
2146 /// VarType.
2147 /// \param VarType Type of the artificial threadprivate variable.
2148 /// \param Name Name of the artificial threadprivate variable.
2149 Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2150 QualType VarType,
2151 StringRef Name) override;
2152
2153 /// Emit flush of the variables specified in 'omp flush' directive.
2154 /// \param Vars List of variables to flush.
2155 void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
2156 SourceLocation Loc, llvm::AtomicOrdering AO) override;
2157
2158 /// Emit task region for the task directive. The task region is
2159 /// emitted in several steps:
2160 /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
2161 /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2162 /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
2163 /// function:
2164 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
2165 /// TaskFunction(gtid, tt->part_id, tt->shareds);
2166 /// return 0;
2167 /// }
2168 /// 2. Copy a list of shared variables to field shareds of the resulting
2169 /// structure kmp_task_t returned by the previous call (if any).
2170 /// 3. Copy a pointer to destructions function to field destructions of the
2171 /// resulting structure kmp_task_t.
2172 /// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid,
2173 /// kmp_task_t *new_task), where new_task is a resulting structure from
2174 /// previous items.
2175 /// \param D Current task directive.
2176 /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
2177 /// /*part_id*/, captured_struct */*__context*/);
2178 /// \param SharedsTy A type which contains references the shared variables.
2179 /// \param Shareds Context with the list of shared variables from the \p
2180 /// TaskFunction.
2181 /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
2182 /// otherwise.
2183 /// \param Data Additional data for task generation like tiednsee, final
2184 /// state, list of privates etc.
2185 void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
2186 const OMPExecutableDirective &D,
2187 llvm::Function *TaskFunction, QualType SharedsTy,
2188 Address Shareds, const Expr *IfCond,
2189 const OMPTaskDataTy &Data) override;
2190
2191 /// Emit task region for the taskloop directive. The taskloop region is
2192 /// emitted in several steps:
2193 /// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
2194 /// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2195 /// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
2196 /// function:
2197 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
2198 /// TaskFunction(gtid, tt->part_id, tt->shareds);
2199 /// return 0;
2200 /// }
2201 /// 2. Copy a list of shared variables to field shareds of the resulting
2202 /// structure kmp_task_t returned by the previous call (if any).
2203 /// 3. Copy a pointer to destructions function to field destructions of the
2204 /// resulting structure kmp_task_t.
2205 /// 4. Emit a call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t
2206 /// *task, int if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int
2207 /// nogroup, int sched, kmp_uint64 grainsize, void *task_dup ), where new_task
2208 /// is a resulting structure from
2209 /// previous items.
2210 /// \param D Current task directive.
2211 /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
2212 /// /*part_id*/, captured_struct */*__context*/);
2213 /// \param SharedsTy A type which contains references the shared variables.
2214 /// \param Shareds Context with the list of shared variables from the \p
2215 /// TaskFunction.
2216 /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
2217 /// otherwise.
2218 /// \param Data Additional data for task generation like tiednsee, final
2219 /// state, list of privates etc.
2220 void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
2221 const OMPLoopDirective &D, llvm::Function *TaskFunction,
2222 QualType SharedsTy, Address Shareds, const Expr *IfCond,
2223 const OMPTaskDataTy &Data) override;
2224
2225 /// Emit a code for reduction clause. Next code should be emitted for
2226 /// reduction:
2227 /// \code
2228 ///
2229 /// static kmp_critical_name lock = { 0 };
2230 ///
2231 /// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
2232 /// ...
2233 /// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
2234 /// ...
2235 /// }
2236 ///
2237 /// ...
2238 /// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
2239 /// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2240 /// RedList, reduce_func, &<lock>)) {
2241 /// case 1:
2242 /// ...
2243 /// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2244 /// ...
2245 /// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2246 /// break;
2247 /// case 2:
2248 /// ...
2249 /// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2250 /// ...
2251 /// break;
2252 /// default:;
2253 /// }
2254 /// \endcode
2255 ///
2256 /// \param Privates List of private copies for original reduction arguments.
2257 /// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
2258 /// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
2259 /// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
2260 /// or 'operator binop(LHS, RHS)'.
2261 /// \param Options List of options for reduction codegen:
2262 /// WithNowait true if parent directive has also nowait clause, false
2263 /// otherwise.
2264 /// SimpleReduction Emit reduction operation only. Used for omp simd
2265 /// directive on the host.
2266 /// ReductionKind The kind of reduction to perform.
2267 void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
2268 ArrayRef<const Expr *> Privates,
2269 ArrayRef<const Expr *> LHSExprs,
2270 ArrayRef<const Expr *> RHSExprs,
2271 ArrayRef<const Expr *> ReductionOps,
2272 ReductionOptionsTy Options) override;
2273
2274 /// Emit a code for initialization of task reduction clause. Next code
2275 /// should be emitted for reduction:
2276 /// \code
2277 ///
2278 /// _taskred_item_t red_data[n];
2279 /// ...
2280 /// red_data[i].shar = &shareds[i];
2281 /// red_data[i].orig = &origs[i];
2282 /// red_data[i].size = sizeof(origs[i]);
2283 /// red_data[i].f_init = (void*)RedInit<i>;
2284 /// red_data[i].f_fini = (void*)RedDest<i>;
2285 /// red_data[i].f_comb = (void*)RedOp<i>;
2286 /// red_data[i].flags = <Flag_i>;
2287 /// ...
2288 /// void* tg1 = __kmpc_taskred_init(gtid, n, red_data);
2289 /// \endcode
2290 /// For reduction clause with task modifier it emits the next call:
2291 /// \code
2292 ///
2293 /// _taskred_item_t red_data[n];
2294 /// ...
2295 /// red_data[i].shar = &shareds[i];
2296 /// red_data[i].orig = &origs[i];
2297 /// red_data[i].size = sizeof(origs[i]);
2298 /// red_data[i].f_init = (void*)RedInit<i>;
2299 /// red_data[i].f_fini = (void*)RedDest<i>;
2300 /// red_data[i].f_comb = (void*)RedOp<i>;
2301 /// red_data[i].flags = <Flag_i>;
2302 /// ...
2303 /// void* tg1 = __kmpc_taskred_modifier_init(loc, gtid, is_worksharing, n,
2304 /// red_data);
2305 /// \endcode
2306 /// \param LHSExprs List of LHS in \a Data.ReductionOps reduction operations.
2307 /// \param RHSExprs List of RHS in \a Data.ReductionOps reduction operations.
2308 /// \param Data Additional data for task generation like tiedness, final
2309 /// state, list of privates, reductions etc.
2310 llvm::Value *emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc,
2311 ArrayRef<const Expr *> LHSExprs,
2312 ArrayRef<const Expr *> RHSExprs,
2313 const OMPTaskDataTy &Data) override;
2314
2315 /// Emits the following code for reduction clause with task modifier:
2316 /// \code
2317 /// __kmpc_task_reduction_modifier_fini(loc, gtid, is_worksharing);
2318 /// \endcode
2319 void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc,
2320 bool IsWorksharingReduction) override;
2321
2322 /// Required to resolve existing problems in the runtime. Emits threadprivate
2323 /// variables to store the size of the VLAs/array sections for
2324 /// initializer/combiner/finalizer functions + emits threadprivate variable to
2325 /// store the pointer to the original reduction item for the custom
2326 /// initializer defined by declare reduction construct.
2327 /// \param RCG Allows to reuse an existing data for the reductions.
2328 /// \param N Reduction item for which fixups must be emitted.
2329 void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc,
2330 ReductionCodeGen &RCG, unsigned N) override;
2331
2332 /// Get the address of `void *` type of the privatue copy of the reduction
2333 /// item specified by the \p SharedLVal.
2334 /// \param ReductionsPtr Pointer to the reduction data returned by the
2335 /// emitTaskReductionInit function.
2336 /// \param SharedLVal Address of the original reduction item.
2337 Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc,
2338 llvm::Value *ReductionsPtr,
2339 LValue SharedLVal) override;
2340
2341 /// Emit code for 'taskwait' directive.
2342 void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc) override;
2343
2344 /// Emit code for 'cancellation point' construct.
2345 /// \param CancelRegion Region kind for which the cancellation point must be
2346 /// emitted.
2347 ///
2348 void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc,
2349 OpenMPDirectiveKind CancelRegion) override;
2350
2351 /// Emit code for 'cancel' construct.
2352 /// \param IfCond Condition in the associated 'if' clause, if it was
2353 /// specified, nullptr otherwise.
2354 /// \param CancelRegion Region kind for which the cancel must be emitted.
2355 ///
2356 void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
2357 const Expr *IfCond,
2358 OpenMPDirectiveKind CancelRegion) override;
2359
2360 /// Emit outilined function for 'target' directive.
2361 /// \param D Directive to emit.
2362 /// \param ParentName Name of the function that encloses the target region.
2363 /// \param OutlinedFn Outlined function value to be defined by this call.
2364 /// \param OutlinedFnID Outlined function ID value to be defined by this call.
2365 /// \param IsOffloadEntry True if the outlined function is an offload entry.
2366 /// \param CodeGen Code generation sequence for the \a D directive.
2367 /// An outlined function may not be an entry if, e.g. the if clause always
2368 /// evaluates to false.
2369 void emitTargetOutlinedFunction(const OMPExecutableDirective &D,
2370 StringRef ParentName,
2371 llvm::Function *&OutlinedFn,
2372 llvm::Constant *&OutlinedFnID,
2373 bool IsOffloadEntry,
2374 const RegionCodeGenTy &CodeGen) override;
2375
2376 /// Emit the target offloading code associated with \a D. The emitted
2377 /// code attempts offloading the execution to the device, an the event of
2378 /// a failure it executes the host version outlined in \a OutlinedFn.
2379 /// \param D Directive to emit.
2380 /// \param OutlinedFn Host version of the code to be offloaded.
2381 /// \param OutlinedFnID ID of host version of the code to be offloaded.
2382 /// \param IfCond Expression evaluated in if clause associated with the target
2383 /// directive, or null if no if clause is used.
2384 /// \param Device Expression evaluated in device clause associated with the
2385 /// target directive, or null if no device clause is used and device modifier.
2386 void emitTargetCall(
2387 CodeGenFunction &CGF, const OMPExecutableDirective &D,
2388 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
2389 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device,
2390 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
2391 const OMPLoopDirective &D)>
2392 SizeEmitter) override;
2393
2394 /// Emit the target regions enclosed in \a GD function definition or
2395 /// the function itself in case it is a valid device function. Returns true if
2396 /// \a GD was dealt with successfully.
2397 /// \param GD Function to scan.
2398 bool emitTargetFunctions(GlobalDecl GD) override;
2399
2400 /// Emit the global variable if it is a valid device global variable.
2401 /// Returns true if \a GD was dealt with successfully.
2402 /// \param GD Variable declaration to emit.
2403 bool emitTargetGlobalVariable(GlobalDecl GD) override;
2404
2405 /// Emit the global \a GD if it is meaningful for the target. Returns
2406 /// if it was emitted successfully.
2407 /// \param GD Global to scan.
2408 bool emitTargetGlobal(GlobalDecl GD) override;
2409
2410 /// Emits code for teams call of the \a OutlinedFn with
2411 /// variables captured in a record which address is stored in \a
2412 /// CapturedStruct.
2413 /// \param OutlinedFn Outlined function to be run by team masters. Type of
2414 /// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
2415 /// \param CapturedVars A pointer to the record with the references to
2416 /// variables used in \a OutlinedFn function.
2417 ///
2418 void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D,
2419 SourceLocation Loc, llvm::Function *OutlinedFn,
2420 ArrayRef<llvm::Value *> CapturedVars) override;
2421
2422 /// Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32
2423 /// global_tid, kmp_int32 num_teams, kmp_int32 thread_limit) to generate code
2424 /// for num_teams clause.
2425 /// \param NumTeams An integer expression of teams.
2426 /// \param ThreadLimit An integer expression of threads.
2427 void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams,
2428 const Expr *ThreadLimit, SourceLocation Loc) override;
2429
2430 /// Emit the target data mapping code associated with \a D.
2431 /// \param D Directive to emit.
2432 /// \param IfCond Expression evaluated in if clause associated with the
2433 /// target directive, or null if no device clause is used.
2434 /// \param Device Expression evaluated in device clause associated with the
2435 /// target directive, or null if no device clause is used.
2436 /// \param Info A record used to store information that needs to be preserved
2437 /// until the region is closed.
2438 void emitTargetDataCalls(CodeGenFunction &CGF,
2439 const OMPExecutableDirective &D, const Expr *IfCond,
2440 const Expr *Device, const RegionCodeGenTy &CodeGen,
2441 TargetDataInfo &Info) override;
2442
2443 /// Emit the data mapping/movement code associated with the directive
2444 /// \a D that should be of the form 'target [{enter|exit} data | update]'.
2445 /// \param D Directive to emit.
2446 /// \param IfCond Expression evaluated in if clause associated with the target
2447 /// directive, or null if no if clause is used.
2448 /// \param Device Expression evaluated in device clause associated with the
2449 /// target directive, or null if no device clause is used.
2450 void emitTargetDataStandAloneCall(CodeGenFunction &CGF,
2451 const OMPExecutableDirective &D,
2452 const Expr *IfCond,
2453 const Expr *Device) override;
2454
2455 /// Emit initialization for doacross loop nesting support.
2456 /// \param D Loop-based construct used in doacross nesting construct.
2457 void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D,
2458 ArrayRef<Expr *> NumIterations) override;
2459
2460 /// Emit code for doacross ordered directive with 'depend' clause.
2461 /// \param C 'depend' clause with 'sink|source' dependency kind.
2462 void emitDoacrossOrdered(CodeGenFunction &CGF,
2463 const OMPDependClause *C) override;
2464
2465 /// Translates the native parameter of outlined function if this is required
2466 /// for target.
2467 /// \param FD Field decl from captured record for the parameter.
2468 /// \param NativeParam Parameter itself.
2469 const VarDecl *translateParameter(const FieldDecl *FD,
2470 const VarDecl *NativeParam) const override;
2471
2472 /// Gets the address of the native argument basing on the address of the
2473 /// target-specific parameter.
2474 /// \param NativeParam Parameter itself.
2475 /// \param TargetParam Corresponding target-specific parameter.
2476 Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam,
2477 const VarDecl *TargetParam) const override;
2478
2479 /// Gets the OpenMP-specific address of the local variable.
2480 Address getAddressOfLocalVariable(CodeGenFunction &CGF,
2481 const VarDecl *VD) override {
2482 return Address::invalid();
2483 }
2484};
2485
2486} // namespace CodeGen
2487} // namespace clang
2488
2489#endif