Bug Summary

File:clang/lib/CodeGen/CGOpenMPRuntime.cpp
Warning:line 2938, column 20
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -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 -mthread-model posix -mframe-pointer=none -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-11/lib/clang/11.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-11~++20200309111110+2c36c23f347/build-llvm/tools/clang/lib/CodeGen -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/include -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/build-llvm/include -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/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-11/lib/clang/11.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-11~++20200309111110+2c36c23f347/build-llvm/tools/clang/lib/CodeGen -fdebug-prefix-map=/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -o /tmp/scan-build-2020-03-09-184146-41876-1 -x c++ /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp

/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/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/OpenMPKinds.h"
25#include "clang/Basic/SourceManager.h"
26#include "clang/CodeGen/ConstantInitBuilder.h"
27#include "llvm/ADT/ArrayRef.h"
28#include "llvm/ADT/SetOperations.h"
29#include "llvm/ADT/StringExtras.h"
30#include "llvm/Bitcode/BitcodeReader.h"
31#include "llvm/Frontend/OpenMP/OMPIRBuilder.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
41using namespace clang;
42using namespace CodeGen;
43using namespace llvm::omp;
44
45namespace {
46/// Base class for handling code generation inside OpenMP regions.
47class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
48public:
49 /// Kinds of OpenMP regions used in codegen.
50 enum CGOpenMPRegionKind {
51 /// Region with outlined function for standalone 'parallel'
52 /// directive.
53 ParallelOutlinedRegion,
54 /// Region with outlined function for standalone 'task' directive.
55 TaskOutlinedRegion,
56 /// Region for constructs that do not require function outlining,
57 /// like 'for', 'sections', 'atomic' etc. directives.
58 InlinedRegion,
59 /// Region with outlined function for standalone 'target' directive.
60 TargetRegion,
61 };
62
63 CGOpenMPRegionInfo(const CapturedStmt &CS,
64 const CGOpenMPRegionKind RegionKind,
65 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
66 bool HasCancel)
67 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
68 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
69
70 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
71 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
72 bool HasCancel)
73 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
74 Kind(Kind), HasCancel(HasCancel) {}
75
76 /// Get a variable or parameter for storing global thread id
77 /// inside OpenMP construct.
78 virtual const VarDecl *getThreadIDVariable() const = 0;
79
80 /// Emit the captured statement body.
81 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
82
83 /// Get an LValue for the current ThreadID variable.
84 /// \return LValue for thread id variable. This LValue always has type int32*.
85 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
86
87 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
88
89 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
90
91 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
92
93 bool hasCancel() const { return HasCancel; }
94
95 static bool classof(const CGCapturedStmtInfo *Info) {
96 return Info->getKind() == CR_OpenMP;
97 }
98
99 ~CGOpenMPRegionInfo() override = default;
100
101protected:
102 CGOpenMPRegionKind RegionKind;
103 RegionCodeGenTy CodeGen;
104 OpenMPDirectiveKind Kind;
105 bool HasCancel;
106};
107
108/// API for captured statement code generation in OpenMP constructs.
109class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
110public:
111 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
112 const RegionCodeGenTy &CodeGen,
113 OpenMPDirectiveKind Kind, bool HasCancel,
114 StringRef HelperName)
115 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
116 HasCancel),
117 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
118 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 118, __PRETTY_FUNCTION__))
;
119 }
120
121 /// Get a variable or parameter for storing global thread id
122 /// inside OpenMP construct.
123 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
124
125 /// Get the name of the capture helper.
126 StringRef getHelperName() const override { return HelperName; }
127
128 static bool classof(const CGCapturedStmtInfo *Info) {
129 return CGOpenMPRegionInfo::classof(Info) &&
130 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
131 ParallelOutlinedRegion;
132 }
133
134private:
135 /// A variable or parameter storing global thread id for OpenMP
136 /// constructs.
137 const VarDecl *ThreadIDVar;
138 StringRef HelperName;
139};
140
141/// API for captured statement code generation in OpenMP constructs.
142class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
143public:
144 class UntiedTaskActionTy final : public PrePostActionTy {
145 bool Untied;
146 const VarDecl *PartIDVar;
147 const RegionCodeGenTy UntiedCodeGen;
148 llvm::SwitchInst *UntiedSwitch = nullptr;
149
150 public:
151 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
152 const RegionCodeGenTy &UntiedCodeGen)
153 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
154 void Enter(CodeGenFunction &CGF) override {
155 if (Untied) {
156 // Emit task switching point.
157 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
158 CGF.GetAddrOfLocalVar(PartIDVar),
159 PartIDVar->getType()->castAs<PointerType>());
160 llvm::Value *Res =
161 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation());
162 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done.");
163 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
164 CGF.EmitBlock(DoneBB);
165 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
166 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
167 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
168 CGF.Builder.GetInsertBlock());
169 emitUntiedSwitch(CGF);
170 }
171 }
172 void emitUntiedSwitch(CodeGenFunction &CGF) const {
173 if (Untied) {
174 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
175 CGF.GetAddrOfLocalVar(PartIDVar),
176 PartIDVar->getType()->castAs<PointerType>());
177 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
178 PartIdLVal);
179 UntiedCodeGen(CGF);
180 CodeGenFunction::JumpDest CurPoint =
181 CGF.getJumpDestInCurrentScope(".untied.next.");
182 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
183 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
184 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
185 CGF.Builder.GetInsertBlock());
186 CGF.EmitBranchThroughCleanup(CurPoint);
187 CGF.EmitBlock(CurPoint.getBlock());
188 }
189 }
190 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
191 };
192 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
193 const VarDecl *ThreadIDVar,
194 const RegionCodeGenTy &CodeGen,
195 OpenMPDirectiveKind Kind, bool HasCancel,
196 const UntiedTaskActionTy &Action)
197 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
198 ThreadIDVar(ThreadIDVar), Action(Action) {
199 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 199, __PRETTY_FUNCTION__))
;
200 }
201
202 /// Get a variable or parameter for storing global thread id
203 /// inside OpenMP construct.
204 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
205
206 /// Get an LValue for the current ThreadID variable.
207 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
208
209 /// Get the name of the capture helper.
210 StringRef getHelperName() const override { return ".omp_outlined."; }
211
212 void emitUntiedSwitch(CodeGenFunction &CGF) override {
213 Action.emitUntiedSwitch(CGF);
214 }
215
216 static bool classof(const CGCapturedStmtInfo *Info) {
217 return CGOpenMPRegionInfo::classof(Info) &&
218 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
219 TaskOutlinedRegion;
220 }
221
222private:
223 /// A variable or parameter storing global thread id for OpenMP
224 /// constructs.
225 const VarDecl *ThreadIDVar;
226 /// Action for emitting code for untied tasks.
227 const UntiedTaskActionTy &Action;
228};
229
230/// API for inlined captured statement code generation in OpenMP
231/// constructs.
232class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
233public:
234 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
235 const RegionCodeGenTy &CodeGen,
236 OpenMPDirectiveKind Kind, bool HasCancel)
237 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
238 OldCSI(OldCSI),
239 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
240
241 // Retrieve the value of the context parameter.
242 llvm::Value *getContextValue() const override {
243 if (OuterRegionInfo)
244 return OuterRegionInfo->getContextValue();
245 llvm_unreachable("No context value for inlined OpenMP region")::llvm::llvm_unreachable_internal("No context value for inlined OpenMP region"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 245)
;
246 }
247
248 void setContextValue(llvm::Value *V) override {
249 if (OuterRegionInfo) {
250 OuterRegionInfo->setContextValue(V);
251 return;
252 }
253 llvm_unreachable("No context value for inlined OpenMP region")::llvm::llvm_unreachable_internal("No context value for inlined OpenMP region"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 253)
;
254 }
255
256 /// Lookup the captured field decl for a variable.
257 const FieldDecl *lookup(const VarDecl *VD) const override {
258 if (OuterRegionInfo)
259 return OuterRegionInfo->lookup(VD);
260 // If there is no outer outlined region,no need to lookup in a list of
261 // captured variables, we can use the original one.
262 return nullptr;
263 }
264
265 FieldDecl *getThisFieldDecl() const override {
266 if (OuterRegionInfo)
267 return OuterRegionInfo->getThisFieldDecl();
268 return nullptr;
269 }
270
271 /// Get a variable or parameter for storing global thread id
272 /// inside OpenMP construct.
273 const VarDecl *getThreadIDVariable() const override {
274 if (OuterRegionInfo)
275 return OuterRegionInfo->getThreadIDVariable();
276 return nullptr;
277 }
278
279 /// Get an LValue for the current ThreadID variable.
280 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override {
281 if (OuterRegionInfo)
282 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
283 llvm_unreachable("No LValue for inlined OpenMP construct")::llvm::llvm_unreachable_internal("No LValue for inlined OpenMP construct"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 283)
;
284 }
285
286 /// Get the name of the capture helper.
287 StringRef getHelperName() const override {
288 if (auto *OuterRegionInfo = getOldCSI())
289 return OuterRegionInfo->getHelperName();
290 llvm_unreachable("No helper name for inlined OpenMP construct")::llvm::llvm_unreachable_internal("No helper name for inlined OpenMP construct"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 290)
;
291 }
292
293 void emitUntiedSwitch(CodeGenFunction &CGF) override {
294 if (OuterRegionInfo)
295 OuterRegionInfo->emitUntiedSwitch(CGF);
296 }
297
298 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
299
300 static bool classof(const CGCapturedStmtInfo *Info) {
301 return CGOpenMPRegionInfo::classof(Info) &&
302 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
303 }
304
305 ~CGOpenMPInlinedRegionInfo() override = default;
306
307private:
308 /// CodeGen info about outer OpenMP region.
309 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
310 CGOpenMPRegionInfo *OuterRegionInfo;
311};
312
313/// API for captured statement code generation in OpenMP target
314/// constructs. For this captures, implicit parameters are used instead of the
315/// captured fields. The name of the target region has to be unique in a given
316/// application so it is provided by the client, because only the client has
317/// the information to generate that.
318class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
319public:
320 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
321 const RegionCodeGenTy &CodeGen, StringRef HelperName)
322 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
323 /*HasCancel=*/false),
324 HelperName(HelperName) {}
325
326 /// This is unused for target regions because each starts executing
327 /// with a single thread.
328 const VarDecl *getThreadIDVariable() const override { return nullptr; }
329
330 /// Get the name of the capture helper.
331 StringRef getHelperName() const override { return HelperName; }
332
333 static bool classof(const CGCapturedStmtInfo *Info) {
334 return CGOpenMPRegionInfo::classof(Info) &&
335 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
336 }
337
338private:
339 StringRef HelperName;
340};
341
342static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
343 llvm_unreachable("No codegen for expressions")::llvm::llvm_unreachable_internal("No codegen for expressions"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 343)
;
344}
345/// API for generation of expressions captured in a innermost OpenMP
346/// region.
347class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
348public:
349 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
350 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
351 OMPD_unknown,
352 /*HasCancel=*/false),
353 PrivScope(CGF) {
354 // Make sure the globals captured in the provided statement are local by
355 // using the privatization logic. We assume the same variable is not
356 // captured more than once.
357 for (const auto &C : CS.captures()) {
358 if (!C.capturesVariable() && !C.capturesVariableByCopy())
359 continue;
360
361 const VarDecl *VD = C.getCapturedVar();
362 if (VD->isLocalVarDeclOrParm())
363 continue;
364
365 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
366 /*RefersToEnclosingVariableOrCapture=*/false,
367 VD->getType().getNonReferenceType(), VK_LValue,
368 C.getLocation());
369 PrivScope.addPrivate(
370 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); });
371 }
372 (void)PrivScope.Privatize();
373 }
374
375 /// Lookup the captured field decl for a variable.
376 const FieldDecl *lookup(const VarDecl *VD) const override {
377 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
378 return FD;
379 return nullptr;
380 }
381
382 /// Emit the captured statement body.
383 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
384 llvm_unreachable("No body for expressions")::llvm::llvm_unreachable_internal("No body for expressions", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 384)
;
385 }
386
387 /// Get a variable or parameter for storing global thread id
388 /// inside OpenMP construct.
389 const VarDecl *getThreadIDVariable() const override {
390 llvm_unreachable("No thread id for expressions")::llvm::llvm_unreachable_internal("No thread id for expressions"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 390)
;
391 }
392
393 /// Get the name of the capture helper.
394 StringRef getHelperName() const override {
395 llvm_unreachable("No helper name for expressions")::llvm::llvm_unreachable_internal("No helper name for expressions"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 395)
;
396 }
397
398 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
399
400private:
401 /// Private scope to capture global variables.
402 CodeGenFunction::OMPPrivateScope PrivScope;
403};
404
405/// RAII for emitting code of OpenMP constructs.
406class InlinedOpenMPRegionRAII {
407 CodeGenFunction &CGF;
408 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
409 FieldDecl *LambdaThisCaptureField = nullptr;
410 const CodeGen::CGBlockInfo *BlockInfo = nullptr;
411
412public:
413 /// Constructs region for combined constructs.
414 /// \param CodeGen Code generation sequence for combined directives. Includes
415 /// a list of functions used for code generation of implicitly inlined
416 /// regions.
417 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
418 OpenMPDirectiveKind Kind, bool HasCancel)
419 : CGF(CGF) {
420 // Start emission for the construct.
421 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
422 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
423 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
424 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
425 CGF.LambdaThisCaptureField = nullptr;
426 BlockInfo = CGF.BlockInfo;
427 CGF.BlockInfo = nullptr;
428 }
429
430 ~InlinedOpenMPRegionRAII() {
431 // Restore original CapturedStmtInfo only if we're done with code emission.
432 auto *OldCSI =
433 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
434 delete CGF.CapturedStmtInfo;
435 CGF.CapturedStmtInfo = OldCSI;
436 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
437 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
438 CGF.BlockInfo = BlockInfo;
439 }
440};
441
442/// Values for bit flags used in the ident_t to describe the fields.
443/// All enumeric elements are named and described in accordance with the code
444/// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
445enum OpenMPLocationFlags : unsigned {
446 /// Use trampoline for internal microtask.
447 OMP_IDENT_IMD = 0x01,
448 /// Use c-style ident structure.
449 OMP_IDENT_KMPC = 0x02,
450 /// Atomic reduction option for kmpc_reduce.
451 OMP_ATOMIC_REDUCE = 0x10,
452 /// Explicit 'barrier' directive.
453 OMP_IDENT_BARRIER_EXPL = 0x20,
454 /// Implicit barrier in code.
455 OMP_IDENT_BARRIER_IMPL = 0x40,
456 /// Implicit barrier in 'for' directive.
457 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
458 /// Implicit barrier in 'sections' directive.
459 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
460 /// Implicit barrier in 'single' directive.
461 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
462 /// Call of __kmp_for_static_init for static loop.
463 OMP_IDENT_WORK_LOOP = 0x200,
464 /// Call of __kmp_for_static_init for sections.
465 OMP_IDENT_WORK_SECTIONS = 0x400,
466 /// Call of __kmp_for_static_init for distribute.
467 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
468 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_IDENT_WORK_DISTRIBUTE
469};
470
471namespace {
472LLVM_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^=
;
473/// Values for bit flags for marking which requires clauses have been used.
474enum OpenMPOffloadingRequiresDirFlags : int64_t {
475 /// flag undefined.
476 OMP_REQ_UNDEFINED = 0x000,
477 /// no requires clause present.
478 OMP_REQ_NONE = 0x001,
479 /// reverse_offload clause.
480 OMP_REQ_REVERSE_OFFLOAD = 0x002,
481 /// unified_address clause.
482 OMP_REQ_UNIFIED_ADDRESS = 0x004,
483 /// unified_shared_memory clause.
484 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
485 /// dynamic_allocators clause.
486 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
487 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_REQ_DYNAMIC_ALLOCATORS
488};
489
490enum OpenMPOffloadingReservedDeviceIDs {
491 /// Device ID if the device was not defined, runtime should get it
492 /// from environment variables in the spec.
493 OMP_DEVICEID_UNDEF = -1,
494};
495} // anonymous namespace
496
497/// Describes ident structure that describes a source location.
498/// All descriptions are taken from
499/// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
500/// Original structure:
501/// typedef struct ident {
502/// kmp_int32 reserved_1; /**< might be used in Fortran;
503/// see above */
504/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
505/// KMP_IDENT_KMPC identifies this union
506/// member */
507/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
508/// see above */
509///#if USE_ITT_BUILD
510/// /* but currently used for storing
511/// region-specific ITT */
512/// /* contextual information. */
513///#endif /* USE_ITT_BUILD */
514/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
515/// C++ */
516/// char const *psource; /**< String describing the source location.
517/// The string is composed of semi-colon separated
518// fields which describe the source file,
519/// the function and a pair of line numbers that
520/// delimit the construct.
521/// */
522/// } ident_t;
523enum IdentFieldIndex {
524 /// might be used in Fortran
525 IdentField_Reserved_1,
526 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
527 IdentField_Flags,
528 /// Not really used in Fortran any more
529 IdentField_Reserved_2,
530 /// Source[4] in Fortran, do not use for C++
531 IdentField_Reserved_3,
532 /// String describing the source location. The string is composed of
533 /// semi-colon separated fields which describe the source file, the function
534 /// and a pair of line numbers that delimit the construct.
535 IdentField_PSource
536};
537
538/// Schedule types for 'omp for' loops (these enumerators are taken from
539/// the enum sched_type in kmp.h).
540enum OpenMPSchedType {
541 /// Lower bound for default (unordered) versions.
542 OMP_sch_lower = 32,
543 OMP_sch_static_chunked = 33,
544 OMP_sch_static = 34,
545 OMP_sch_dynamic_chunked = 35,
546 OMP_sch_guided_chunked = 36,
547 OMP_sch_runtime = 37,
548 OMP_sch_auto = 38,
549 /// static with chunk adjustment (e.g., simd)
550 OMP_sch_static_balanced_chunked = 45,
551 /// Lower bound for 'ordered' versions.
552 OMP_ord_lower = 64,
553 OMP_ord_static_chunked = 65,
554 OMP_ord_static = 66,
555 OMP_ord_dynamic_chunked = 67,
556 OMP_ord_guided_chunked = 68,
557 OMP_ord_runtime = 69,
558 OMP_ord_auto = 70,
559 OMP_sch_default = OMP_sch_static,
560 /// dist_schedule types
561 OMP_dist_sch_static_chunked = 91,
562 OMP_dist_sch_static = 92,
563 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
564 /// Set if the monotonic schedule modifier was present.
565 OMP_sch_modifier_monotonic = (1 << 29),
566 /// Set if the nonmonotonic schedule modifier was present.
567 OMP_sch_modifier_nonmonotonic = (1 << 30),
568};
569
570enum OpenMPRTLFunction {
571 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
572 /// kmpc_micro microtask, ...);
573 OMPRTL__kmpc_fork_call,
574 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc,
575 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
576 OMPRTL__kmpc_threadprivate_cached,
577 /// Call to void __kmpc_threadprivate_register( ident_t *,
578 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
579 OMPRTL__kmpc_threadprivate_register,
580 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
581 OMPRTL__kmpc_global_thread_num,
582 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
583 // kmp_critical_name *crit);
584 OMPRTL__kmpc_critical,
585 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
586 // global_tid, kmp_critical_name *crit, uintptr_t hint);
587 OMPRTL__kmpc_critical_with_hint,
588 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
589 // kmp_critical_name *crit);
590 OMPRTL__kmpc_end_critical,
591 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
592 // global_tid);
593 OMPRTL__kmpc_cancel_barrier,
594 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
595 OMPRTL__kmpc_barrier,
596 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
597 OMPRTL__kmpc_for_static_fini,
598 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
599 // global_tid);
600 OMPRTL__kmpc_serialized_parallel,
601 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
602 // global_tid);
603 OMPRTL__kmpc_end_serialized_parallel,
604 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
605 // kmp_int32 num_threads);
606 OMPRTL__kmpc_push_num_threads,
607 // Call to void __kmpc_flush(ident_t *loc);
608 OMPRTL__kmpc_flush,
609 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
610 OMPRTL__kmpc_master,
611 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
612 OMPRTL__kmpc_end_master,
613 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
614 // int end_part);
615 OMPRTL__kmpc_omp_taskyield,
616 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
617 OMPRTL__kmpc_single,
618 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
619 OMPRTL__kmpc_end_single,
620 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
621 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
622 // kmp_routine_entry_t *task_entry);
623 OMPRTL__kmpc_omp_task_alloc,
624 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *,
625 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t,
626 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry,
627 // kmp_int64 device_id);
628 OMPRTL__kmpc_omp_target_task_alloc,
629 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
630 // new_task);
631 OMPRTL__kmpc_omp_task,
632 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
633 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
634 // kmp_int32 didit);
635 OMPRTL__kmpc_copyprivate,
636 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
637 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
638 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
639 OMPRTL__kmpc_reduce,
640 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
641 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
642 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
643 // *lck);
644 OMPRTL__kmpc_reduce_nowait,
645 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
646 // kmp_critical_name *lck);
647 OMPRTL__kmpc_end_reduce,
648 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
649 // kmp_critical_name *lck);
650 OMPRTL__kmpc_end_reduce_nowait,
651 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
652 // kmp_task_t * new_task);
653 OMPRTL__kmpc_omp_task_begin_if0,
654 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
655 // kmp_task_t * new_task);
656 OMPRTL__kmpc_omp_task_complete_if0,
657 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
658 OMPRTL__kmpc_ordered,
659 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
660 OMPRTL__kmpc_end_ordered,
661 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
662 // global_tid);
663 OMPRTL__kmpc_omp_taskwait,
664 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
665 OMPRTL__kmpc_taskgroup,
666 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
667 OMPRTL__kmpc_end_taskgroup,
668 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
669 // int proc_bind);
670 OMPRTL__kmpc_push_proc_bind,
671 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
672 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
673 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
674 OMPRTL__kmpc_omp_task_with_deps,
675 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
676 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
677 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
678 OMPRTL__kmpc_omp_wait_deps,
679 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
680 // global_tid, kmp_int32 cncl_kind);
681 OMPRTL__kmpc_cancellationpoint,
682 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
683 // kmp_int32 cncl_kind);
684 OMPRTL__kmpc_cancel,
685 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
686 // kmp_int32 num_teams, kmp_int32 thread_limit);
687 OMPRTL__kmpc_push_num_teams,
688 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
689 // microtask, ...);
690 OMPRTL__kmpc_fork_teams,
691 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
692 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
693 // sched, kmp_uint64 grainsize, void *task_dup);
694 OMPRTL__kmpc_taskloop,
695 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
696 // num_dims, struct kmp_dim *dims);
697 OMPRTL__kmpc_doacross_init,
698 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
699 OMPRTL__kmpc_doacross_fini,
700 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
701 // *vec);
702 OMPRTL__kmpc_doacross_post,
703 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
704 // *vec);
705 OMPRTL__kmpc_doacross_wait,
706 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void
707 // *data);
708 OMPRTL__kmpc_task_reduction_init,
709 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
710 // *d);
711 OMPRTL__kmpc_task_reduction_get_th_data,
712 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al);
713 OMPRTL__kmpc_alloc,
714 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al);
715 OMPRTL__kmpc_free,
716
717 //
718 // Offloading related calls
719 //
720 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
721 // size);
722 OMPRTL__kmpc_push_target_tripcount,
723 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
724 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
725 // *arg_types);
726 OMPRTL__tgt_target,
727 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
728 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
729 // *arg_types);
730 OMPRTL__tgt_target_nowait,
731 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
732 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
733 // *arg_types, int32_t num_teams, int32_t thread_limit);
734 OMPRTL__tgt_target_teams,
735 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void
736 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
737 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
738 OMPRTL__tgt_target_teams_nowait,
739 // Call to void __tgt_register_requires(int64_t flags);
740 OMPRTL__tgt_register_requires,
741 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
742 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
743 OMPRTL__tgt_target_data_begin,
744 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
745 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
746 // *arg_types);
747 OMPRTL__tgt_target_data_begin_nowait,
748 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
749 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
750 OMPRTL__tgt_target_data_end,
751 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t
752 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
753 // *arg_types);
754 OMPRTL__tgt_target_data_end_nowait,
755 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
756 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
757 OMPRTL__tgt_target_data_update,
758 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t
759 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
760 // *arg_types);
761 OMPRTL__tgt_target_data_update_nowait,
762 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
763 OMPRTL__tgt_mapper_num_components,
764 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void
765 // *base, void *begin, int64_t size, int64_t type);
766 OMPRTL__tgt_push_mapper_component,
767};
768
769/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
770/// region.
771class CleanupTy final : public EHScopeStack::Cleanup {
772 PrePostActionTy *Action;
773
774public:
775 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
776 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
777 if (!CGF.HaveInsertPoint())
778 return;
779 Action->Exit(CGF);
780 }
781};
782
783} // anonymous namespace
784
785void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
786 CodeGenFunction::RunCleanupsScope Scope(CGF);
787 if (PrePostAction) {
788 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
789 Callback(CodeGen, CGF, *PrePostAction);
790 } else {
791 PrePostActionTy Action;
792 Callback(CodeGen, CGF, Action);
793 }
794}
795
796/// Check if the combiner is a call to UDR combiner and if it is so return the
797/// UDR decl used for reduction.
798static const OMPDeclareReductionDecl *
799getReductionInit(const Expr *ReductionOp) {
800 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
801 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
802 if (const auto *DRE =
803 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
804 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
805 return DRD;
806 return nullptr;
807}
808
809static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
810 const OMPDeclareReductionDecl *DRD,
811 const Expr *InitOp,
812 Address Private, Address Original,
813 QualType Ty) {
814 if (DRD->getInitializer()) {
815 std::pair<llvm::Function *, llvm::Function *> Reduction =
816 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
817 const auto *CE = cast<CallExpr>(InitOp);
818 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
819 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
820 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
821 const auto *LHSDRE =
822 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
823 const auto *RHSDRE =
824 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
825 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
826 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
827 [=]() { return Private; });
828 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
829 [=]() { return Original; });
830 (void)PrivateScope.Privatize();
831 RValue Func = RValue::get(Reduction.second);
832 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
833 CGF.EmitIgnoredExpr(InitOp);
834 } else {
835 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
836 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
837 auto *GV = new llvm::GlobalVariable(
838 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
839 llvm::GlobalValue::PrivateLinkage, Init, Name);
840 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
841 RValue InitRVal;
842 switch (CGF.getEvaluationKind(Ty)) {
843 case TEK_Scalar:
844 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
845 break;
846 case TEK_Complex:
847 InitRVal =
848 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
849 break;
850 case TEK_Aggregate:
851 InitRVal = RValue::getAggregate(LV.getAddress(CGF));
852 break;
853 }
854 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
855 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
856 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
857 /*IsInitializer=*/false);
858 }
859}
860
861/// Emit initialization of arrays of complex types.
862/// \param DestAddr Address of the array.
863/// \param Type Type of array.
864/// \param Init Initial expression of array.
865/// \param SrcAddr Address of the original array.
866static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
867 QualType Type, bool EmitDeclareReductionInit,
868 const Expr *Init,
869 const OMPDeclareReductionDecl *DRD,
870 Address SrcAddr = Address::invalid()) {
871 // Perform element-by-element initialization.
872 QualType ElementTy;
873
874 // Drill down to the base element type on both arrays.
875 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
876 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
877 DestAddr =
878 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
879 if (DRD)
880 SrcAddr =
881 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
882
883 llvm::Value *SrcBegin = nullptr;
884 if (DRD)
885 SrcBegin = SrcAddr.getPointer();
886 llvm::Value *DestBegin = DestAddr.getPointer();
887 // Cast from pointer to array type to pointer to single element.
888 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
889 // The basic structure here is a while-do loop.
890 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
891 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
892 llvm::Value *IsEmpty =
893 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
894 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
895
896 // Enter the loop body, making that address the current address.
897 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
898 CGF.EmitBlock(BodyBB);
899
900 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
901
902 llvm::PHINode *SrcElementPHI = nullptr;
903 Address SrcElementCurrent = Address::invalid();
904 if (DRD) {
905 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
906 "omp.arraycpy.srcElementPast");
907 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
908 SrcElementCurrent =
909 Address(SrcElementPHI,
910 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
911 }
912 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
913 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
914 DestElementPHI->addIncoming(DestBegin, EntryBB);
915 Address DestElementCurrent =
916 Address(DestElementPHI,
917 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
918
919 // Emit copy.
920 {
921 CodeGenFunction::RunCleanupsScope InitScope(CGF);
922 if (EmitDeclareReductionInit) {
923 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
924 SrcElementCurrent, ElementTy);
925 } else
926 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
927 /*IsInitializer=*/false);
928 }
929
930 if (DRD) {
931 // Shift the address forward by one element.
932 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
933 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
934 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
935 }
936
937 // Shift the address forward by one element.
938 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
939 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
940 // Check whether we've reached the end.
941 llvm::Value *Done =
942 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
943 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
944 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
945
946 // Done.
947 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
948}
949
950LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
951 return CGF.EmitOMPSharedLValue(E);
952}
953
954LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
955 const Expr *E) {
956 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
957 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
958 return LValue();
959}
960
961void ReductionCodeGen::emitAggregateInitialization(
962 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
963 const OMPDeclareReductionDecl *DRD) {
964 // Emit VarDecl with copy init for arrays.
965 // Get the address of the original variable captured in current
966 // captured region.
967 const auto *PrivateVD =
968 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
969 bool EmitDeclareReductionInit =
970 DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
971 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),
972 EmitDeclareReductionInit,
973 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
974 : PrivateVD->getInit(),
975 DRD, SharedLVal.getAddress(CGF));
976}
977
978ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
979 ArrayRef<const Expr *> Privates,
980 ArrayRef<const Expr *> ReductionOps) {
981 ClausesData.reserve(Shareds.size());
982 SharedAddresses.reserve(Shareds.size());
983 Sizes.reserve(Shareds.size());
984 BaseDecls.reserve(Shareds.size());
985 auto IPriv = Privates.begin();
986 auto IRed = ReductionOps.begin();
987 for (const Expr *Ref : Shareds) {
988 ClausesData.emplace_back(Ref, *IPriv, *IRed);
989 std::advance(IPriv, 1);
990 std::advance(IRed, 1);
991 }
992}
993
994void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) {
995 assert(SharedAddresses.size() == N &&((SharedAddresses.size() == N && "Number of generated lvalues must be exactly N."
) ? static_cast<void> (0) : __assert_fail ("SharedAddresses.size() == N && \"Number of generated lvalues must be exactly N.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 996, __PRETTY_FUNCTION__))
996 "Number of generated lvalues must be exactly N.")((SharedAddresses.size() == N && "Number of generated lvalues must be exactly N."
) ? static_cast<void> (0) : __assert_fail ("SharedAddresses.size() == N && \"Number of generated lvalues must be exactly N.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 996, __PRETTY_FUNCTION__))
;
997 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
998 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
999 SharedAddresses.emplace_back(First, Second);
1000}
1001
1002void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
1003 const auto *PrivateVD =
1004 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1005 QualType PrivateType = PrivateVD->getType();
1006 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
1007 if (!PrivateType->isVariablyModifiedType()) {
1008 Sizes.emplace_back(
1009 CGF.getTypeSize(
1010 SharedAddresses[N].first.getType().getNonReferenceType()),
1011 nullptr);
1012 return;
1013 }
1014 llvm::Value *Size;
1015 llvm::Value *SizeInChars;
1016 auto *ElemType = cast<llvm::PointerType>(
1017 SharedAddresses[N].first.getPointer(CGF)->getType())
1018 ->getElementType();
1019 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
1020 if (AsArraySection) {
1021 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF),
1022 SharedAddresses[N].first.getPointer(CGF));
1023 Size = CGF.Builder.CreateNUWAdd(
1024 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
1025 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf);
1026 } else {
1027 SizeInChars = CGF.getTypeSize(
1028 SharedAddresses[N].first.getType().getNonReferenceType());
1029 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
1030 }
1031 Sizes.emplace_back(SizeInChars, Size);
1032 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1033 CGF,
1034 cast<OpaqueValueExpr>(
1035 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1036 RValue::get(Size));
1037 CGF.EmitVariablyModifiedType(PrivateType);
1038}
1039
1040void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
1041 llvm::Value *Size) {
1042 const auto *PrivateVD =
1043 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1044 QualType PrivateType = PrivateVD->getType();
1045 if (!PrivateType->isVariablyModifiedType()) {
1046 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1048, __PRETTY_FUNCTION__))
1047 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1048, __PRETTY_FUNCTION__))
1048 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1048, __PRETTY_FUNCTION__))
;
1049 return;
1050 }
1051 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1052 CGF,
1053 cast<OpaqueValueExpr>(
1054 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1055 RValue::get(Size));
1056 CGF.EmitVariablyModifiedType(PrivateType);
1057}
1058
1059void ReductionCodeGen::emitInitialization(
1060 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
1061 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
1062 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1062, __PRETTY_FUNCTION__))
;
1063 const auto *PrivateVD =
1064 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1065 const OMPDeclareReductionDecl *DRD =
1066 getReductionInit(ClausesData[N].ReductionOp);
1067 QualType PrivateType = PrivateVD->getType();
1068 PrivateAddr = CGF.Builder.CreateElementBitCast(
1069 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1070 QualType SharedType = SharedAddresses[N].first.getType();
1071 SharedLVal = CGF.MakeAddrLValue(
1072 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF),
1073 CGF.ConvertTypeForMem(SharedType)),
1074 SharedType, SharedAddresses[N].first.getBaseInfo(),
1075 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType));
1076 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
1077 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD);
1078 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
1079 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
1080 PrivateAddr, SharedLVal.getAddress(CGF),
1081 SharedLVal.getType());
1082 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
1083 !CGF.isTrivialInitializer(PrivateVD->getInit())) {
1084 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,
1085 PrivateVD->getType().getQualifiers(),
1086 /*IsInitializer=*/false);
1087 }
1088}
1089
1090bool ReductionCodeGen::needCleanups(unsigned N) {
1091 const auto *PrivateVD =
1092 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1093 QualType PrivateType = PrivateVD->getType();
1094 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1095 return DTorKind != QualType::DK_none;
1096}
1097
1098void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
1099 Address PrivateAddr) {
1100 const auto *PrivateVD =
1101 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1102 QualType PrivateType = PrivateVD->getType();
1103 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1104 if (needCleanups(N)) {
1105 PrivateAddr = CGF.Builder.CreateElementBitCast(
1106 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1107 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);
1108 }
1109}
1110
1111static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1112 LValue BaseLV) {
1113 BaseTy = BaseTy.getNonReferenceType();
1114 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1115 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
1116 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
1117 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy);
1118 } else {
1119 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy);
1120 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
1121 }
1122 BaseTy = BaseTy->getPointeeType();
1123 }
1124 return CGF.MakeAddrLValue(
1125 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF),
1126 CGF.ConvertTypeForMem(ElTy)),
1127 BaseLV.getType(), BaseLV.getBaseInfo(),
1128 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
1129}
1130
1131static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1132 llvm::Type *BaseLVType, CharUnits BaseLVAlignment,
1133 llvm::Value *Addr) {
1134 Address Tmp = Address::invalid();
1135 Address TopTmp = Address::invalid();
1136 Address MostTopTmp = Address::invalid();
1137 BaseTy = BaseTy.getNonReferenceType();
1138 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1139 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
1140 Tmp = CGF.CreateMemTemp(BaseTy);
1141 if (TopTmp.isValid())
1142 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
1143 else
1144 MostTopTmp = Tmp;
1145 TopTmp = Tmp;
1146 BaseTy = BaseTy->getPointeeType();
1147 }
1148 llvm::Type *Ty = BaseLVType;
1149 if (Tmp.isValid())
1150 Ty = Tmp.getElementType();
1151 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);
1152 if (Tmp.isValid()) {
1153 CGF.Builder.CreateStore(Addr, Tmp);
1154 return MostTopTmp;
1155 }
1156 return Address(Addr, BaseLVAlignment);
1157}
1158
1159static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
1160 const VarDecl *OrigVD = nullptr;
1161 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
1162 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
1163 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
1164 Base = TempOASE->getBase()->IgnoreParenImpCasts();
1165 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
1166 Base = TempASE->getBase()->IgnoreParenImpCasts();
1167 DE = cast<DeclRefExpr>(Base);
1168 OrigVD = cast<VarDecl>(DE->getDecl());
1169 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
1170 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
1171 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
1172 Base = TempASE->getBase()->IgnoreParenImpCasts();
1173 DE = cast<DeclRefExpr>(Base);
1174 OrigVD = cast<VarDecl>(DE->getDecl());
1175 }
1176 return OrigVD;
1177}
1178
1179Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
1180 Address PrivateAddr) {
1181 const DeclRefExpr *DE;
1182 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
1183 BaseDecls.emplace_back(OrigVD);
1184 LValue OriginalBaseLValue = CGF.EmitLValue(DE);
1185 LValue BaseLValue =
1186 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
1187 OriginalBaseLValue);
1188 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
1189 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF));
1190 llvm::Value *PrivatePointer =
1191 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1192 PrivateAddr.getPointer(),
1193 SharedAddresses[N].first.getAddress(CGF).getType());
1194 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
1195 return castToBase(CGF, OrigVD->getType(),
1196 SharedAddresses[N].first.getType(),
1197 OriginalBaseLValue.getAddress(CGF).getType(),
1198 OriginalBaseLValue.getAlignment(), Ptr);
1199 }
1200 BaseDecls.emplace_back(
1201 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
1202 return PrivateAddr;
1203}
1204
1205bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
1206 const OMPDeclareReductionDecl *DRD =
1207 getReductionInit(ClausesData[N].ReductionOp);
1208 return DRD && DRD->getInitializer();
1209}
1210
1211LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
1212 return CGF.EmitLoadOfPointerLValue(
1213 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1214 getThreadIDVariable()->getType()->castAs<PointerType>());
1215}
1216
1217void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
1218 if (!CGF.HaveInsertPoint())
1219 return;
1220 // 1.2.2 OpenMP Language Terminology
1221 // Structured block - An executable statement with a single entry at the
1222 // top and a single exit at the bottom.
1223 // The point of exit cannot be a branch out of the structured block.
1224 // longjmp() and throw() must not violate the entry/exit criteria.
1225 CGF.EHStack.pushTerminate();
1226 CodeGen(CGF);
1227 CGF.EHStack.popTerminate();
1228}
1229
1230LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1231 CodeGenFunction &CGF) {
1232 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1233 getThreadIDVariable()->getType(),
1234 AlignmentSource::Decl);
1235}
1236
1237static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1238 QualType FieldTy) {
1239 auto *Field = FieldDecl::Create(
1240 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1241 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1242 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1243 Field->setAccess(AS_public);
1244 DC->addDecl(Field);
1245 return Field;
1246}
1247
1248CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
1249 StringRef Separator)
1250 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
1251 OffloadEntriesInfoManager(CGM) {
1252 ASTContext &C = CGM.getContext();
1253 RecordDecl *RD = C.buildImplicitRecord("ident_t");
1254 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1255 RD->startDefinition();
1256 // reserved_1
1257 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1258 // flags
1259 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1260 // reserved_2
1261 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1262 // reserved_3
1263 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1264 // psource
1265 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1266 RD->completeDefinition();
1267 IdentQTy = C.getRecordType(RD);
1268 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD);
1269 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
1270
1271 loadOffloadInfoMetadata();
1272}
1273
1274bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD,
1275 const GlobalDecl &OldGD,
1276 llvm::GlobalValue *OrigAddr,
1277 bool IsForDefinition) {
1278 // Emit at least a definition for the aliasee if the the address of the
1279 // original function is requested.
1280 if (IsForDefinition || OrigAddr)
1281 (void)CGM.GetAddrOfGlobal(NewGD);
1282 StringRef NewMangledName = CGM.getMangledName(NewGD);
1283 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName);
1284 if (Addr && !Addr->isDeclaration()) {
1285 const auto *D = cast<FunctionDecl>(OldGD.getDecl());
1286 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(NewGD);
1287 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI);
1288
1289 // Create a reference to the named value. This ensures that it is emitted
1290 // if a deferred decl.
1291 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD);
1292
1293 // Create the new alias itself, but don't set a name yet.
1294 auto *GA =
1295 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule());
1296
1297 if (OrigAddr) {
1298 assert(OrigAddr->isDeclaration() && "Expected declaration")((OrigAddr->isDeclaration() && "Expected declaration"
) ? static_cast<void> (0) : __assert_fail ("OrigAddr->isDeclaration() && \"Expected declaration\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1298, __PRETTY_FUNCTION__))
;
1299
1300 GA->takeName(OrigAddr);
1301 OrigAddr->replaceAllUsesWith(
1302 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType()));
1303 OrigAddr->eraseFromParent();
1304 } else {
1305 GA->setName(CGM.getMangledName(OldGD));
1306 }
1307
1308 // Set attributes which are particular to an alias; this is a
1309 // specialization of the attributes which may be set on a global function.
1310 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() ||
1311 D->isWeakImported())
1312 GA->setLinkage(llvm::Function::WeakAnyLinkage);
1313
1314 CGM.SetCommonAttributes(OldGD, GA);
1315 return true;
1316 }
1317 return false;
1318}
1319
1320void CGOpenMPRuntime::clear() {
1321 InternalVars.clear();
1322 // Clean non-target variable declarations possibly used only in debug info.
1323 for (const auto &Data : EmittedNonTargetVariables) {
1324 if (!Data.getValue().pointsToAliveValue())
1325 continue;
1326 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1327 if (!GV)
1328 continue;
1329 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1330 continue;
1331 GV->eraseFromParent();
1332 }
1333 // Emit aliases for the deferred aliasees.
1334 for (const auto &Pair : DeferredVariantFunction) {
1335 StringRef MangledName = CGM.getMangledName(Pair.second.second);
1336 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName);
1337 // If not able to emit alias, just emit original declaration.
1338 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr,
1339 /*IsForDefinition=*/false);
1340 }
1341}
1342
1343std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1344 SmallString<128> Buffer;
1345 llvm::raw_svector_ostream OS(Buffer);
1346 StringRef Sep = FirstSeparator;
1347 for (StringRef Part : Parts) {
1348 OS << Sep << Part;
1349 Sep = Separator;
1350 }
1351 return std::string(OS.str());
1352}
1353
1354static llvm::Function *
1355emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1356 const Expr *CombinerInitializer, const VarDecl *In,
1357 const VarDecl *Out, bool IsCombiner) {
1358 // void .omp_combiner.(Ty *in, Ty *out);
1359 ASTContext &C = CGM.getContext();
1360 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1361 FunctionArgList Args;
1362 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
1363 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
1364 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
1365 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
1366 Args.push_back(&OmpOutParm);
1367 Args.push_back(&OmpInParm);
1368 const CGFunctionInfo &FnInfo =
1369 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
1370 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
1371 std::string Name = CGM.getOpenMPRuntime().getName(
1372 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1373 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1374 Name, &CGM.getModule());
1375 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
1376 if (CGM.getLangOpts().Optimize) {
1377 Fn->removeFnAttr(llvm::Attribute::NoInline);
1378 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1379 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1380 }
1381 CodeGenFunction CGF(CGM);
1382 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1383 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
1384 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1385 Out->getLocation());
1386 CodeGenFunction::OMPPrivateScope Scope(CGF);
1387 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
1388 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
1389 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
1390 .getAddress(CGF);
1391 });
1392 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
1393 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
1394 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
1395 .getAddress(CGF);
1396 });
1397 (void)Scope.Privatize();
1398 if (!IsCombiner && Out->hasInit() &&
1399 !CGF.isTrivialInitializer(Out->getInit())) {
1400 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1401 Out->getType().getQualifiers(),
1402 /*IsInitializer=*/true);
1403 }
1404 if (CombinerInitializer)
1405 CGF.EmitIgnoredExpr(CombinerInitializer);
1406 Scope.ForceCleanup();
1407 CGF.FinishFunction();
1408 return Fn;
1409}
1410
1411void CGOpenMPRuntime::emitUserDefinedReduction(
1412 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1413 if (UDRMap.count(D) > 0)
1414 return;
1415 llvm::Function *Combiner = emitCombinerOrInitializer(
1416 CGM, D->getType(), D->getCombiner(),
1417 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1418 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
1419 /*IsCombiner=*/true);
1420 llvm::Function *Initializer = nullptr;
1421 if (const Expr *Init = D->getInitializer()) {
1422 Initializer = emitCombinerOrInitializer(
1423 CGM, D->getType(),
1424 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1425 : nullptr,
1426 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1427 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
1428 /*IsCombiner=*/false);
1429 }
1430 UDRMap.try_emplace(D, Combiner, Initializer);
1431 if (CGF) {
1432 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1433 Decls.second.push_back(D);
1434 }
1435}
1436
1437std::pair<llvm::Function *, llvm::Function *>
1438CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1439 auto I = UDRMap.find(D);
1440 if (I != UDRMap.end())
1441 return I->second;
1442 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1443 return UDRMap.lookup(D);
1444}
1445
1446namespace {
1447// Temporary RAII solution to perform a push/pop stack event on the OpenMP IR
1448// Builder if one is present.
1449struct PushAndPopStackRAII {
1450 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF,
1451 bool HasCancel)
1452 : OMPBuilder(OMPBuilder) {
1453 if (!OMPBuilder)
1454 return;
1455
1456 // The following callback is the crucial part of clangs cleanup process.
1457 //
1458 // NOTE:
1459 // Once the OpenMPIRBuilder is used to create parallel regions (and
1460 // similar), the cancellation destination (Dest below) is determined via
1461 // IP. That means if we have variables to finalize we split the block at IP,
1462 // use the new block (=BB) as destination to build a JumpDest (via
1463 // getJumpDestInCurrentScope(BB)) which then is fed to
1464 // EmitBranchThroughCleanup. Furthermore, there will not be the need
1465 // to push & pop an FinalizationInfo object.
1466 // The FiniCB will still be needed but at the point where the
1467 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct.
1468 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1469 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1470, __PRETTY_FUNCTION__))
1470 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1470, __PRETTY_FUNCTION__))
;
1471 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1472 CGF.Builder.restoreIP(IP);
1473 CodeGenFunction::JumpDest Dest =
1474 CGF.getOMPCancelDestination(OMPD_parallel);
1475 CGF.EmitBranchThroughCleanup(Dest);
1476 };
1477
1478 // TODO: Remove this once we emit parallel regions through the
1479 // OpenMPIRBuilder as it can do this setup internally.
1480 llvm::OpenMPIRBuilder::FinalizationInfo FI(
1481 {FiniCB, OMPD_parallel, HasCancel});
1482 OMPBuilder->pushFinalizationCB(std::move(FI));
1483 }
1484 ~PushAndPopStackRAII() {
1485 if (OMPBuilder)
1486 OMPBuilder->popFinalizationCB();
1487 }
1488 llvm::OpenMPIRBuilder *OMPBuilder;
1489};
1490} // namespace
1491
1492static llvm::Function *emitParallelOrTeamsOutlinedFunction(
1493 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1494 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1495 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
1496 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1497, __PRETTY_FUNCTION__))
1497 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1497, __PRETTY_FUNCTION__))
;
1498 CodeGenFunction CGF(CGM, true);
1499 bool HasCancel = false;
1500 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1501 HasCancel = OPD->hasCancel();
1502 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1503 HasCancel = OPSD->hasCancel();
1504 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1505 HasCancel = OPFD->hasCancel();
1506 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1507 HasCancel = OPFD->hasCancel();
1508 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1509 HasCancel = OPFD->hasCancel();
1510 else if (const auto *OPFD =
1511 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1512 HasCancel = OPFD->hasCancel();
1513 else if (const auto *OPFD =
1514 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1515 HasCancel = OPFD->hasCancel();
1516
1517 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new
1518 // parallel region to make cancellation barriers work properly.
1519 llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder();
1520 PushAndPopStackRAII PSR(OMPBuilder, CGF, HasCancel);
1521 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
1522 HasCancel, OutlinedHelperName);
1523 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
1524 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc());
1525}
1526
1527llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
1528 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1529 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1530 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1531 return emitParallelOrTeamsOutlinedFunction(
1532 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1533}
1534
1535llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
1536 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1537 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1538 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1539 return emitParallelOrTeamsOutlinedFunction(
1540 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1541}
1542
1543llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
1544 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1545 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1546 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1547 bool Tied, unsigned &NumberOfParts) {
1548 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1549 PrePostActionTy &) {
1550 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1551 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
1552 llvm::Value *TaskArgs[] = {
1553 UpLoc, ThreadID,
1554 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1555 TaskTVar->getType()->castAs<PointerType>())
1556 .getPointer(CGF)};
1557 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
1558 };
1559 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1560 UntiedCodeGen);
1561 CodeGen.setAction(Action);
1562 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1563, __PRETTY_FUNCTION__))
1563 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1563, __PRETTY_FUNCTION__))
;
1564 const OpenMPDirectiveKind Region =
1565 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1566 : OMPD_task;
1567 const CapturedStmt *CS = D.getCapturedStmt(Region);
1568 bool HasCancel = false;
1569 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1570 HasCancel = TD->hasCancel();
1571 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1572 HasCancel = TD->hasCancel();
1573 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1574 HasCancel = TD->hasCancel();
1575 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1576 HasCancel = TD->hasCancel();
1577
1578 CodeGenFunction CGF(CGM, true);
1579 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1580 InnermostKind, HasCancel, Action);
1581 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
1582 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1583 if (!Tied)
1584 NumberOfParts = Action.getNumberOfParts();
1585 return Res;
1586}
1587
1588static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1589 const RecordDecl *RD, const CGRecordLayout &RL,
1590 ArrayRef<llvm::Constant *> Data) {
1591 llvm::StructType *StructTy = RL.getLLVMType();
1592 unsigned PrevIdx = 0;
1593 ConstantInitBuilder CIBuilder(CGM);
1594 auto DI = Data.begin();
1595 for (const FieldDecl *FD : RD->fields()) {
1596 unsigned Idx = RL.getLLVMFieldNo(FD);
1597 // Fill the alignment.
1598 for (unsigned I = PrevIdx; I < Idx; ++I)
1599 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1600 PrevIdx = Idx + 1;
1601 Fields.add(*DI);
1602 ++DI;
1603 }
1604}
1605
1606template <class... As>
1607static llvm::GlobalVariable *
1608createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1609 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1610 As &&... Args) {
1611 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1612 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1613 ConstantInitBuilder CIBuilder(CGM);
1614 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1615 buildStructValue(Fields, CGM, RD, RL, Data);
1616 return Fields.finishAndCreateGlobal(
1617 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1618 std::forward<As>(Args)...);
1619}
1620
1621template <typename T>
1622static void
1623createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1624 ArrayRef<llvm::Constant *> Data,
1625 T &Parent) {
1626 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1627 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1628 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1629 buildStructValue(Fields, CGM, RD, RL, Data);
1630 Fields.finishAndAddTo(Parent);
1631}
1632
1633Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
1634 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
1635 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1636 FlagsTy FlagsKey(Flags, Reserved2Flags);
1637 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey);
1638 if (!Entry) {
1639 if (!DefaultOpenMPPSource) {
1640 // Initialize default location for psource field of ident_t structure of
1641 // all ident_t objects. Format is ";file;function;line;column;;".
1642 // Taken from
1643 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp
1644 DefaultOpenMPPSource =
1645 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
1646 DefaultOpenMPPSource =
1647 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
1648 }
1649
1650 llvm::Constant *Data[] = {
1651 llvm::ConstantInt::getNullValue(CGM.Int32Ty),
1652 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
1653 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags),
1654 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource};
1655 llvm::GlobalValue *DefaultOpenMPLocation =
1656 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "",
1657 llvm::GlobalValue::PrivateLinkage);
1658 DefaultOpenMPLocation->setUnnamedAddr(
1659 llvm::GlobalValue::UnnamedAddr::Global);
1660
1661 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation;
1662 }
1663 return Address(Entry, Align);
1664}
1665
1666void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1667 bool AtCurrentPoint) {
1668 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1669 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1669, __PRETTY_FUNCTION__))
;
1670
1671 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1672 if (AtCurrentPoint) {
1673 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1674 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1675 } else {
1676 Elem.second.ServiceInsertPt =
1677 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1678 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1679 }
1680}
1681
1682void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1683 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1684 if (Elem.second.ServiceInsertPt) {
1685 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1686 Elem.second.ServiceInsertPt = nullptr;
1687 Ptr->eraseFromParent();
1688 }
1689}
1690
1691llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1692 SourceLocation Loc,
1693 unsigned Flags) {
1694 Flags |= OMP_IDENT_KMPC;
1695 // If no debug info is generated - return global default location.
1696 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
1697 Loc.isInvalid())
1698 return getOrCreateDefaultLocation(Flags).getPointer();
1699
1700 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1700, __PRETTY_FUNCTION__))
;
1701
1702 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
1703 Address LocValue = Address::invalid();
1704 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1705 if (I != OpenMPLocThreadIDMap.end())
1706 LocValue = Address(I->second.DebugLoc, Align);
1707
1708 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
1709 // GetOpenMPThreadID was called before this routine.
1710 if (!LocValue.isValid()) {
1711 // Generate "ident_t .kmpc_loc.addr;"
1712 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr");
1713 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1714 Elem.second.DebugLoc = AI.getPointer();
1715 LocValue = AI;
1716
1717 if (!Elem.second.ServiceInsertPt)
1718 setLocThreadIdInsertPt(CGF);
1719 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1720 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
1721 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
1722 CGF.getTypeSize(IdentQTy));
1723 }
1724
1725 // char **psource = &.kmpc_loc_<flags>.addr.psource;
1726 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy);
1727 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin();
1728 LValue PSource =
1729 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource));
1730
1731 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
1732 if (OMPDebugLoc == nullptr) {
1733 SmallString<128> Buffer2;
1734 llvm::raw_svector_ostream OS2(Buffer2);
1735 // Build debug location
1736 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1737 OS2 << ";" << PLoc.getFilename() << ";";
1738 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
1739 OS2 << FD->getQualifiedNameAsString();
1740 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1741 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
1742 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
1743 }
1744 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
1745 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource);
1746
1747 // Our callers always pass this to a runtime function, so for
1748 // convenience, go ahead and return a naked pointer.
1749 return LocValue.getPointer();
1750}
1751
1752llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1753 SourceLocation Loc) {
1754 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1754, __PRETTY_FUNCTION__))
;
1755
1756 llvm::Value *ThreadID = nullptr;
1757 // Check whether we've already cached a load of the thread id in this
1758 // function.
1759 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1760 if (I != OpenMPLocThreadIDMap.end()) {
1761 ThreadID = I->second.ThreadID;
1762 if (ThreadID != nullptr)
1763 return ThreadID;
1764 }
1765 // If exceptions are enabled, do not use parameter to avoid possible crash.
1766 if (auto *OMPRegionInfo =
1767 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1768 if (OMPRegionInfo->getThreadIDVariable()) {
1769 // Check if this an outlined function with thread id passed as argument.
1770 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1771 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent();
1772 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1773 !CGF.getLangOpts().CXXExceptions ||
1774 CGF.Builder.GetInsertBlock() == TopBlock ||
1775 !isa<llvm::Instruction>(LVal.getPointer(CGF)) ||
1776 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1777 TopBlock ||
1778 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1779 CGF.Builder.GetInsertBlock()) {
1780 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
1781 // If value loaded in entry block, cache it and use it everywhere in
1782 // function.
1783 if (CGF.Builder.GetInsertBlock() == TopBlock) {
1784 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1785 Elem.second.ThreadID = ThreadID;
1786 }
1787 return ThreadID;
1788 }
1789 }
1790 }
1791
1792 // This is not an outlined function region - need to call __kmpc_int32
1793 // kmpc_global_thread_num(ident_t *loc).
1794 // Generate thread id value and cache this value for use across the
1795 // function.
1796 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1797 if (!Elem.second.ServiceInsertPt)
1798 setLocThreadIdInsertPt(CGF);
1799 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1800 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
1801 llvm::CallInst *Call = CGF.Builder.CreateCall(
1802 createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1803 emitUpdateLocation(CGF, Loc));
1804 Call->setCallingConv(CGF.getRuntimeCC());
1805 Elem.second.ThreadID = Call;
1806 return Call;
1807}
1808
1809void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
1810 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1810, __PRETTY_FUNCTION__))
;
1811 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1812 clearLocThreadIdInsertPt(CGF);
1813 OpenMPLocThreadIDMap.erase(CGF.CurFn);
1814 }
1815 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
1816 for(const auto *D : FunctionUDRMap[CGF.CurFn])
1817 UDRMap.erase(D);
1818 FunctionUDRMap.erase(CGF.CurFn);
1819 }
1820 auto I = FunctionUDMMap.find(CGF.CurFn);
1821 if (I != FunctionUDMMap.end()) {
1822 for(const auto *D : I->second)
1823 UDMMap.erase(D);
1824 FunctionUDMMap.erase(I);
1825 }
1826 LastprivateConditionalToTypes.erase(CGF.CurFn);
1827}
1828
1829llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
1830 return IdentTy->getPointerTo();
1831}
1832
1833llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
1834 if (!Kmpc_MicroTy) {
1835 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1836 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1837 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1838 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1839 }
1840 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1841}
1842
1843llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
1844 llvm::FunctionCallee RTLFn = nullptr;
1845 switch (static_cast<OpenMPRTLFunction>(Function)) {
1846 case OMPRTL__kmpc_fork_call: {
1847 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1848 // microtask, ...);
1849 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1850 getKmpc_MicroPointerTy()};
1851 auto *FnTy =
1852 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
1853 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
1854 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
1855 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
1856 llvm::LLVMContext &Ctx = F->getContext();
1857 llvm::MDBuilder MDB(Ctx);
1858 // Annotate the callback behavior of the __kmpc_fork_call:
1859 // - The callback callee is argument number 2 (microtask).
1860 // - The first two arguments of the callback callee are unknown (-1).
1861 // - All variadic arguments to the __kmpc_fork_call are passed to the
1862 // callback callee.
1863 F->addMetadata(
1864 llvm::LLVMContext::MD_callback,
1865 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
1866 2, {-1, -1},
1867 /* VarArgsArePassed */ true)}));
1868 }
1869 }
1870 break;
1871 }
1872 case OMPRTL__kmpc_global_thread_num: {
1873 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
1874 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
1875 auto *FnTy =
1876 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1877 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1878 break;
1879 }
1880 case OMPRTL__kmpc_threadprivate_cached: {
1881 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1882 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1883 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1884 CGM.VoidPtrTy, CGM.SizeTy,
1885 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
1886 auto *FnTy =
1887 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1888 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1889 break;
1890 }
1891 case OMPRTL__kmpc_critical: {
1892 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1893 // kmp_critical_name *crit);
1894 llvm::Type *TypeParams[] = {
1895 getIdentTyPointerTy(), CGM.Int32Ty,
1896 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1897 auto *FnTy =
1898 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1899 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1900 break;
1901 }
1902 case OMPRTL__kmpc_critical_with_hint: {
1903 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1904 // kmp_critical_name *crit, uintptr_t hint);
1905 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1906 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1907 CGM.IntPtrTy};
1908 auto *FnTy =
1909 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1910 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1911 break;
1912 }
1913 case OMPRTL__kmpc_threadprivate_register: {
1914 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1915 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1916 // typedef void *(*kmpc_ctor)(void *);
1917 auto *KmpcCtorTy =
1918 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1919 /*isVarArg*/ false)->getPointerTo();
1920 // typedef void *(*kmpc_cctor)(void *, void *);
1921 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1922 auto *KmpcCopyCtorTy =
1923 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
1924 /*isVarArg*/ false)
1925 ->getPointerTo();
1926 // typedef void (*kmpc_dtor)(void *);
1927 auto *KmpcDtorTy =
1928 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1929 ->getPointerTo();
1930 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1931 KmpcCopyCtorTy, KmpcDtorTy};
1932 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
1933 /*isVarArg*/ false);
1934 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1935 break;
1936 }
1937 case OMPRTL__kmpc_end_critical: {
1938 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1939 // kmp_critical_name *crit);
1940 llvm::Type *TypeParams[] = {
1941 getIdentTyPointerTy(), CGM.Int32Ty,
1942 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1943 auto *FnTy =
1944 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1945 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1946 break;
1947 }
1948 case OMPRTL__kmpc_cancel_barrier: {
1949 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1950 // global_tid);
1951 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1952 auto *FnTy =
1953 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1954 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
1955 break;
1956 }
1957 case OMPRTL__kmpc_barrier: {
1958 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
1959 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1960 auto *FnTy =
1961 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1962 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1963 break;
1964 }
1965 case OMPRTL__kmpc_for_static_fini: {
1966 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1967 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1968 auto *FnTy =
1969 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1970 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1971 break;
1972 }
1973 case OMPRTL__kmpc_push_num_threads: {
1974 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1975 // kmp_int32 num_threads)
1976 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1977 CGM.Int32Ty};
1978 auto *FnTy =
1979 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1980 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1981 break;
1982 }
1983 case OMPRTL__kmpc_serialized_parallel: {
1984 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1985 // global_tid);
1986 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1987 auto *FnTy =
1988 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1989 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1990 break;
1991 }
1992 case OMPRTL__kmpc_end_serialized_parallel: {
1993 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1994 // global_tid);
1995 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1996 auto *FnTy =
1997 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1998 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1999 break;
2000 }
2001 case OMPRTL__kmpc_flush: {
2002 // Build void __kmpc_flush(ident_t *loc);
2003 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
2004 auto *FnTy =
2005 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2006 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
2007 break;
2008 }
2009 case OMPRTL__kmpc_master: {
2010 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
2011 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
2012 auto *FnTy =
2013 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2014 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
2015 break;
2016 }
2017 case OMPRTL__kmpc_end_master: {
2018 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
2019 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
2020 auto *FnTy =
2021 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2022 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
2023 break;
2024 }
2025 case OMPRTL__kmpc_omp_taskyield: {
2026 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
2027 // int end_part);
2028 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
2029 auto *FnTy =
2030 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2031 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
2032 break;
2033 }
2034 case OMPRTL__kmpc_single: {
2035 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
2036 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
2037 auto *FnTy =
2038 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2039 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
2040 break;
2041 }
2042 case OMPRTL__kmpc_end_single: {
2043 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
2044 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
2045 auto *FnTy =
2046 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2047 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
2048 break;
2049 }
2050 case OMPRTL__kmpc_omp_task_alloc: {
2051 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
2052 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2053 // kmp_routine_entry_t *task_entry);
2054 assert(KmpRoutineEntryPtrTy != nullptr &&((KmpRoutineEntryPtrTy != nullptr && "Type kmp_routine_entry_t must be created."
) ? static_cast<void> (0) : __assert_fail ("KmpRoutineEntryPtrTy != nullptr && \"Type kmp_routine_entry_t must be created.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2055, __PRETTY_FUNCTION__))
2055 "Type kmp_routine_entry_t must be created.")((KmpRoutineEntryPtrTy != nullptr && "Type kmp_routine_entry_t must be created."
) ? static_cast<void> (0) : __assert_fail ("KmpRoutineEntryPtrTy != nullptr && \"Type kmp_routine_entry_t must be created.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2055, __PRETTY_FUNCTION__))
;
2056 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2057 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
2058 // Return void * and then cast to particular kmp_task_t type.
2059 auto *FnTy =
2060 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2061 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
2062 break;
2063 }
2064 case OMPRTL__kmpc_omp_target_task_alloc: {
2065 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid,
2066 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2067 // kmp_routine_entry_t *task_entry, kmp_int64 device_id);
2068 assert(KmpRoutineEntryPtrTy != nullptr &&((KmpRoutineEntryPtrTy != nullptr && "Type kmp_routine_entry_t must be created."
) ? static_cast<void> (0) : __assert_fail ("KmpRoutineEntryPtrTy != nullptr && \"Type kmp_routine_entry_t must be created.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2069, __PRETTY_FUNCTION__))
2069 "Type kmp_routine_entry_t must be created.")((KmpRoutineEntryPtrTy != nullptr && "Type kmp_routine_entry_t must be created."
) ? static_cast<void> (0) : __assert_fail ("KmpRoutineEntryPtrTy != nullptr && \"Type kmp_routine_entry_t must be created.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2069, __PRETTY_FUNCTION__))
;
2070 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2071 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy,
2072 CGM.Int64Ty};
2073 // Return void * and then cast to particular kmp_task_t type.
2074 auto *FnTy =
2075 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2076 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc");
2077 break;
2078 }
2079 case OMPRTL__kmpc_omp_task: {
2080 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2081 // *new_task);
2082 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2083 CGM.VoidPtrTy};
2084 auto *FnTy =
2085 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2086 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
2087 break;
2088 }
2089 case OMPRTL__kmpc_copyprivate: {
2090 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
2091 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
2092 // kmp_int32 didit);
2093 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2094 auto *CpyFnTy =
2095 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
2096 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
2097 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
2098 CGM.Int32Ty};
2099 auto *FnTy =
2100 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2101 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
2102 break;
2103 }
2104 case OMPRTL__kmpc_reduce: {
2105 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
2106 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
2107 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
2108 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2109 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2110 /*isVarArg=*/false);
2111 llvm::Type *TypeParams[] = {
2112 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2113 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2114 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
2115 auto *FnTy =
2116 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2117 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
2118 break;
2119 }
2120 case OMPRTL__kmpc_reduce_nowait: {
2121 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
2122 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
2123 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
2124 // *lck);
2125 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2126 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2127 /*isVarArg=*/false);
2128 llvm::Type *TypeParams[] = {
2129 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2130 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2131 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
2132 auto *FnTy =
2133 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2134 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
2135 break;
2136 }
2137 case OMPRTL__kmpc_end_reduce: {
2138 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
2139 // kmp_critical_name *lck);
2140 llvm::Type *TypeParams[] = {
2141 getIdentTyPointerTy(), CGM.Int32Ty,
2142 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
2143 auto *FnTy =
2144 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2145 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
2146 break;
2147 }
2148 case OMPRTL__kmpc_end_reduce_nowait: {
2149 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
2150 // kmp_critical_name *lck);
2151 llvm::Type *TypeParams[] = {
2152 getIdentTyPointerTy(), CGM.Int32Ty,
2153 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
2154 auto *FnTy =
2155 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2156 RTLFn =
2157 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
2158 break;
2159 }
2160 case OMPRTL__kmpc_omp_task_begin_if0: {
2161 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2162 // *new_task);
2163 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2164 CGM.VoidPtrTy};
2165 auto *FnTy =
2166 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2167 RTLFn =
2168 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
2169 break;
2170 }
2171 case OMPRTL__kmpc_omp_task_complete_if0: {
2172 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2173 // *new_task);
2174 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2175 CGM.VoidPtrTy};
2176 auto *FnTy =
2177 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2178 RTLFn = CGM.CreateRuntimeFunction(FnTy,
2179 /*Name=*/"__kmpc_omp_task_complete_if0");
2180 break;
2181 }
2182 case OMPRTL__kmpc_ordered: {
2183 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
2184 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
2185 auto *FnTy =
2186 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2187 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
2188 break;
2189 }
2190 case OMPRTL__kmpc_end_ordered: {
2191 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
2192 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
2193 auto *FnTy =
2194 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2195 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
2196 break;
2197 }
2198 case OMPRTL__kmpc_omp_taskwait: {
2199 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
2200 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
2201 auto *FnTy =
2202 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2203 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
2204 break;
2205 }
2206 case OMPRTL__kmpc_taskgroup: {
2207 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
2208 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
2209 auto *FnTy =
2210 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2211 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
2212 break;
2213 }
2214 case OMPRTL__kmpc_end_taskgroup: {
2215 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
2216 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
2217 auto *FnTy =
2218 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2219 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
2220 break;
2221 }
2222 case OMPRTL__kmpc_push_proc_bind: {
2223 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2224 // int proc_bind)
2225 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
2226 auto *FnTy =
2227 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2228 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
2229 break;
2230 }
2231 case OMPRTL__kmpc_omp_task_with_deps: {
2232 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2233 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2234 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
2235 llvm::Type *TypeParams[] = {
2236 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
2237 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
2238 auto *FnTy =
2239 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2240 RTLFn =
2241 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
2242 break;
2243 }
2244 case OMPRTL__kmpc_omp_wait_deps: {
2245 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2246 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
2247 // kmp_depend_info_t *noalias_dep_list);
2248 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2249 CGM.Int32Ty, CGM.VoidPtrTy,
2250 CGM.Int32Ty, CGM.VoidPtrTy};
2251 auto *FnTy =
2252 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2253 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
2254 break;
2255 }
2256 case OMPRTL__kmpc_cancellationpoint: {
2257 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2258 // global_tid, kmp_int32 cncl_kind)
2259 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
2260 auto *FnTy =
2261 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2262 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
2263 break;
2264 }
2265 case OMPRTL__kmpc_cancel: {
2266 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2267 // kmp_int32 cncl_kind)
2268 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
2269 auto *FnTy =
2270 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2271 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
2272 break;
2273 }
2274 case OMPRTL__kmpc_push_num_teams: {
2275 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
2276 // kmp_int32 num_teams, kmp_int32 num_threads)
2277 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2278 CGM.Int32Ty};
2279 auto *FnTy =
2280 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2281 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
2282 break;
2283 }
2284 case OMPRTL__kmpc_fork_teams: {
2285 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
2286 // microtask, ...);
2287 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2288 getKmpc_MicroPointerTy()};
2289 auto *FnTy =
2290 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
2291 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
2292 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
2293 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
2294 llvm::LLVMContext &Ctx = F->getContext();
2295 llvm::MDBuilder MDB(Ctx);
2296 // Annotate the callback behavior of the __kmpc_fork_teams:
2297 // - The callback callee is argument number 2 (microtask).
2298 // - The first two arguments of the callback callee are unknown (-1).
2299 // - All variadic arguments to the __kmpc_fork_teams are passed to the
2300 // callback callee.
2301 F->addMetadata(
2302 llvm::LLVMContext::MD_callback,
2303 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
2304 2, {-1, -1},
2305 /* VarArgsArePassed */ true)}));
2306 }
2307 }
2308 break;
2309 }
2310 case OMPRTL__kmpc_taskloop: {
2311 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
2312 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
2313 // sched, kmp_uint64 grainsize, void *task_dup);
2314 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2315 CGM.IntTy,
2316 CGM.VoidPtrTy,
2317 CGM.IntTy,
2318 CGM.Int64Ty->getPointerTo(),
2319 CGM.Int64Ty->getPointerTo(),
2320 CGM.Int64Ty,
2321 CGM.IntTy,
2322 CGM.IntTy,
2323 CGM.Int64Ty,
2324 CGM.VoidPtrTy};
2325 auto *FnTy =
2326 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2327 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
2328 break;
2329 }
2330 case OMPRTL__kmpc_doacross_init: {
2331 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
2332 // num_dims, struct kmp_dim *dims);
2333 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2334 CGM.Int32Ty,
2335 CGM.Int32Ty,
2336 CGM.VoidPtrTy};
2337 auto *FnTy =
2338 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2339 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
2340 break;
2341 }
2342 case OMPRTL__kmpc_doacross_fini: {
2343 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
2344 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
2345 auto *FnTy =
2346 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2347 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
2348 break;
2349 }
2350 case OMPRTL__kmpc_doacross_post: {
2351 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
2352 // *vec);
2353 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2354 CGM.Int64Ty->getPointerTo()};
2355 auto *FnTy =
2356 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2357 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
2358 break;
2359 }
2360 case OMPRTL__kmpc_doacross_wait: {
2361 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
2362 // *vec);
2363 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2364 CGM.Int64Ty->getPointerTo()};
2365 auto *FnTy =
2366 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2367 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
2368 break;
2369 }
2370 case OMPRTL__kmpc_task_reduction_init: {
2371 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
2372 // *data);
2373 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
2374 auto *FnTy =
2375 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2376 RTLFn =
2377 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
2378 break;
2379 }
2380 case OMPRTL__kmpc_task_reduction_get_th_data: {
2381 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
2382 // *d);
2383 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
2384 auto *FnTy =
2385 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2386 RTLFn = CGM.CreateRuntimeFunction(
2387 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
2388 break;
2389 }
2390 case OMPRTL__kmpc_alloc: {
2391 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t
2392 // al); omp_allocator_handle_t type is void *.
2393 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy};
2394 auto *FnTy =
2395 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2396 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc");
2397 break;
2398 }
2399 case OMPRTL__kmpc_free: {
2400 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t
2401 // al); omp_allocator_handle_t type is void *.
2402 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
2403 auto *FnTy =
2404 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2405 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free");
2406 break;
2407 }
2408 case OMPRTL__kmpc_push_target_tripcount: {
2409 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
2410 // size);
2411 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
2412 llvm::FunctionType *FnTy =
2413 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2414 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
2415 break;
2416 }
2417 case OMPRTL__tgt_target: {
2418 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
2419 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
2420 // *arg_types);
2421 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2422 CGM.VoidPtrTy,
2423 CGM.Int32Ty,
2424 CGM.VoidPtrPtrTy,
2425 CGM.VoidPtrPtrTy,
2426 CGM.Int64Ty->getPointerTo(),
2427 CGM.Int64Ty->getPointerTo()};
2428 auto *FnTy =
2429 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2430 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
2431 break;
2432 }
2433 case OMPRTL__tgt_target_nowait: {
2434 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
2435 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
2436 // int64_t *arg_types);
2437 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2438 CGM.VoidPtrTy,
2439 CGM.Int32Ty,
2440 CGM.VoidPtrPtrTy,
2441 CGM.VoidPtrPtrTy,
2442 CGM.Int64Ty->getPointerTo(),
2443 CGM.Int64Ty->getPointerTo()};
2444 auto *FnTy =
2445 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2446 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
2447 break;
2448 }
2449 case OMPRTL__tgt_target_teams: {
2450 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
2451 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
2452 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2453 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2454 CGM.VoidPtrTy,
2455 CGM.Int32Ty,
2456 CGM.VoidPtrPtrTy,
2457 CGM.VoidPtrPtrTy,
2458 CGM.Int64Ty->getPointerTo(),
2459 CGM.Int64Ty->getPointerTo(),
2460 CGM.Int32Ty,
2461 CGM.Int32Ty};
2462 auto *FnTy =
2463 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2464 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
2465 break;
2466 }
2467 case OMPRTL__tgt_target_teams_nowait: {
2468 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
2469 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
2470 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2471 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2472 CGM.VoidPtrTy,
2473 CGM.Int32Ty,
2474 CGM.VoidPtrPtrTy,
2475 CGM.VoidPtrPtrTy,
2476 CGM.Int64Ty->getPointerTo(),
2477 CGM.Int64Ty->getPointerTo(),
2478 CGM.Int32Ty,
2479 CGM.Int32Ty};
2480 auto *FnTy =
2481 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2482 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
2483 break;
2484 }
2485 case OMPRTL__tgt_register_requires: {
2486 // Build void __tgt_register_requires(int64_t flags);
2487 llvm::Type *TypeParams[] = {CGM.Int64Ty};
2488 auto *FnTy =
2489 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2490 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires");
2491 break;
2492 }
2493 case OMPRTL__tgt_target_data_begin: {
2494 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
2495 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
2496 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2497 CGM.Int32Ty,
2498 CGM.VoidPtrPtrTy,
2499 CGM.VoidPtrPtrTy,
2500 CGM.Int64Ty->getPointerTo(),
2501 CGM.Int64Ty->getPointerTo()};
2502 auto *FnTy =
2503 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2504 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
2505 break;
2506 }
2507 case OMPRTL__tgt_target_data_begin_nowait: {
2508 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
2509 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
2510 // *arg_types);
2511 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2512 CGM.Int32Ty,
2513 CGM.VoidPtrPtrTy,
2514 CGM.VoidPtrPtrTy,
2515 CGM.Int64Ty->getPointerTo(),
2516 CGM.Int64Ty->getPointerTo()};
2517 auto *FnTy =
2518 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2519 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
2520 break;
2521 }
2522 case OMPRTL__tgt_target_data_end: {
2523 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
2524 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
2525 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2526 CGM.Int32Ty,
2527 CGM.VoidPtrPtrTy,
2528 CGM.VoidPtrPtrTy,
2529 CGM.Int64Ty->getPointerTo(),
2530 CGM.Int64Ty->getPointerTo()};
2531 auto *FnTy =
2532 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2533 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
2534 break;
2535 }
2536 case OMPRTL__tgt_target_data_end_nowait: {
2537 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
2538 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
2539 // *arg_types);
2540 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2541 CGM.Int32Ty,
2542 CGM.VoidPtrPtrTy,
2543 CGM.VoidPtrPtrTy,
2544 CGM.Int64Ty->getPointerTo(),
2545 CGM.Int64Ty->getPointerTo()};
2546 auto *FnTy =
2547 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2548 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
2549 break;
2550 }
2551 case OMPRTL__tgt_target_data_update: {
2552 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
2553 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
2554 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2555 CGM.Int32Ty,
2556 CGM.VoidPtrPtrTy,
2557 CGM.VoidPtrPtrTy,
2558 CGM.Int64Ty->getPointerTo(),
2559 CGM.Int64Ty->getPointerTo()};
2560 auto *FnTy =
2561 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2562 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
2563 break;
2564 }
2565 case OMPRTL__tgt_target_data_update_nowait: {
2566 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
2567 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
2568 // *arg_types);
2569 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2570 CGM.Int32Ty,
2571 CGM.VoidPtrPtrTy,
2572 CGM.VoidPtrPtrTy,
2573 CGM.Int64Ty->getPointerTo(),
2574 CGM.Int64Ty->getPointerTo()};
2575 auto *FnTy =
2576 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2577 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
2578 break;
2579 }
2580 case OMPRTL__tgt_mapper_num_components: {
2581 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
2582 llvm::Type *TypeParams[] = {CGM.VoidPtrTy};
2583 auto *FnTy =
2584 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false);
2585 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components");
2586 break;
2587 }
2588 case OMPRTL__tgt_push_mapper_component: {
2589 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void
2590 // *base, void *begin, int64_t size, int64_t type);
2591 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy,
2592 CGM.Int64Ty, CGM.Int64Ty};
2593 auto *FnTy =
2594 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2595 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component");
2596 break;
2597 }
2598 }
2599 assert(RTLFn && "Unable to find OpenMP runtime function")((RTLFn && "Unable to find OpenMP runtime function") ?
static_cast<void> (0) : __assert_fail ("RTLFn && \"Unable to find OpenMP runtime function\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2599, __PRETTY_FUNCTION__))
;
2600 return RTLFn;
2601}
2602
2603llvm::FunctionCallee
2604CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
2605 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2606, __PRETTY_FUNCTION__))
2606 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2606, __PRETTY_FUNCTION__))
;
2607 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
2608 : "__kmpc_for_static_init_4u")
2609 : (IVSigned ? "__kmpc_for_static_init_8"
2610 : "__kmpc_for_static_init_8u");
2611 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2612 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
2613 llvm::Type *TypeParams[] = {
2614 getIdentTyPointerTy(), // loc
2615 CGM.Int32Ty, // tid
2616 CGM.Int32Ty, // schedtype
2617 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2618 PtrTy, // p_lower
2619 PtrTy, // p_upper
2620 PtrTy, // p_stride
2621 ITy, // incr
2622 ITy // chunk
2623 };
2624 auto *FnTy =
2625 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2626 return CGM.CreateRuntimeFunction(FnTy, Name);
2627}
2628
2629llvm::FunctionCallee
2630CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
2631 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2632, __PRETTY_FUNCTION__))
2632 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2632, __PRETTY_FUNCTION__))
;
2633 StringRef Name =
2634 IVSize == 32
2635 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
2636 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
2637 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2638 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
2639 CGM.Int32Ty, // tid
2640 CGM.Int32Ty, // schedtype
2641 ITy, // lower
2642 ITy, // upper
2643 ITy, // stride
2644 ITy // chunk
2645 };
2646 auto *FnTy =
2647 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2648 return CGM.CreateRuntimeFunction(FnTy, Name);
2649}
2650
2651llvm::FunctionCallee
2652CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
2653 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2654, __PRETTY_FUNCTION__))
2654 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2654, __PRETTY_FUNCTION__))
;
2655 StringRef Name =
2656 IVSize == 32
2657 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
2658 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
2659 llvm::Type *TypeParams[] = {
2660 getIdentTyPointerTy(), // loc
2661 CGM.Int32Ty, // tid
2662 };
2663 auto *FnTy =
2664 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2665 return CGM.CreateRuntimeFunction(FnTy, Name);
2666}
2667
2668llvm::FunctionCallee
2669CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
2670 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2671, __PRETTY_FUNCTION__))
2671 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2671, __PRETTY_FUNCTION__))
;
2672 StringRef Name =
2673 IVSize == 32
2674 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
2675 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
2676 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2677 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
2678 llvm::Type *TypeParams[] = {
2679 getIdentTyPointerTy(), // loc
2680 CGM.Int32Ty, // tid
2681 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2682 PtrTy, // p_lower
2683 PtrTy, // p_upper
2684 PtrTy // p_stride
2685 };
2686 auto *FnTy =
2687 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2688 return CGM.CreateRuntimeFunction(FnTy, Name);
2689}
2690
2691/// Obtain information that uniquely identifies a target entry. This
2692/// consists of the file and device IDs as well as line number associated with
2693/// the relevant entry source location.
2694static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
2695 unsigned &DeviceID, unsigned &FileID,
2696 unsigned &LineNum) {
2697 SourceManager &SM = C.getSourceManager();
2698
2699 // The loc should be always valid and have a file ID (the user cannot use
2700 // #pragma directives in macros)
2701
2702 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2702, __PRETTY_FUNCTION__))
;
2703
2704 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
2705 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2705, __PRETTY_FUNCTION__))
;
2706
2707 llvm::sys::fs::UniqueID ID;
2708 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
2709 SM.getDiagnostics().Report(diag::err_cannot_open_file)
2710 << PLoc.getFilename() << EC.message();
2711
2712 DeviceID = ID.getDevice();
2713 FileID = ID.getFile();
2714 LineNum = PLoc.getLine();
2715}
2716
2717Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
2718 if (CGM.getLangOpts().OpenMPSimd)
2719 return Address::invalid();
2720 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
2721 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
2722 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
2723 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2724 HasRequiresUnifiedSharedMemory))) {
2725 SmallString<64> PtrName;
2726 {
2727 llvm::raw_svector_ostream OS(PtrName);
2728 OS << CGM.getMangledName(GlobalDecl(VD));
2729 if (!VD->isExternallyVisible()) {
2730 unsigned DeviceID, FileID, Line;
2731 getTargetEntryUniqueInfo(CGM.getContext(),
2732 VD->getCanonicalDecl()->getBeginLoc(),
2733 DeviceID, FileID, Line);
2734 OS << llvm::format("_%x", FileID);
2735 }
2736 OS << "_decl_tgt_ref_ptr";
2737 }
2738 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
2739 if (!Ptr) {
2740 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
2741 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
2742 PtrName);
2743
2744 auto *GV = cast<llvm::GlobalVariable>(Ptr);
2745 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
2746
2747 if (!CGM.getLangOpts().OpenMPIsDevice)
2748 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
2749 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
2750 }
2751 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
2752 }
2753 return Address::invalid();
2754}
2755
2756llvm::Constant *
2757CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
2758 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2759, __PRETTY_FUNCTION__))
2759 !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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2759, __PRETTY_FUNCTION__))
;
2760 // Lookup the entry, lazily creating it if necessary.
2761 std::string Suffix = getName({"cache", ""});
2762 return getOrCreateInternalVariable(
2763 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
2764}
2765
2766Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
2767 const VarDecl *VD,
2768 Address VDAddr,
2769 SourceLocation Loc) {
2770 if (CGM.getLangOpts().OpenMPUseTLS &&
2771 CGM.getContext().getTargetInfo().isTLSSupported())
2772 return VDAddr;
2773
2774 llvm::Type *VarTy = VDAddr.getElementType();
2775 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2776 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
2777 CGM.Int8PtrTy),
2778 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
2779 getOrCreateThreadPrivateCache(VD)};
2780 return Address(CGF.EmitRuntimeCall(
2781 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2782 VDAddr.getAlignment());
2783}
2784
2785void CGOpenMPRuntime::emitThreadPrivateVarInit(
2786 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
2787 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
2788 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
2789 // library.
2790 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
2791 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
2792 OMPLoc);
2793 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
2794 // to register constructor/destructor for variable.
2795 llvm::Value *Args[] = {
2796 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
2797 Ctor, CopyCtor, Dtor};
2798 CGF.EmitRuntimeCall(
2799 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
2800}
2801
2802llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
2803 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
2804 bool PerformInit, CodeGenFunction *CGF) {
2805 if (CGM.getLangOpts().OpenMPUseTLS &&
2806 CGM.getContext().getTargetInfo().isTLSSupported())
2807 return nullptr;
2808
2809 VD = VD->getDefinition(CGM.getContext());
2810 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
2811 QualType ASTTy = VD->getType();
2812
2813 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
2814 const Expr *Init = VD->getAnyInitializer();
2815 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2816 // Generate function that re-emits the declaration's initializer into the
2817 // threadprivate copy of the variable VD
2818 CodeGenFunction CtorCGF(CGM);
2819 FunctionArgList Args;
2820 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2821 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
2822 ImplicitParamDecl::Other);
2823 Args.push_back(&Dst);
2824
2825 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
2826 CGM.getContext().VoidPtrTy, Args);
2827 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2828 std::string Name = getName({"__kmpc_global_ctor_", ""});
2829 llvm::Function *Fn =
2830 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
2831 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
2832 Args, Loc, Loc);
2833 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
2834 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
2835 CGM.getContext().VoidPtrTy, Dst.getLocation());
2836 Address Arg = Address(ArgVal, VDAddr.getAlignment());
2837 Arg = CtorCGF.Builder.CreateElementBitCast(
2838 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
2839 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
2840 /*IsInitializer=*/true);
2841 ArgVal = CtorCGF.EmitLoadOfScalar(
2842 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
2843 CGM.getContext().VoidPtrTy, Dst.getLocation());
2844 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
2845 CtorCGF.FinishFunction();
2846 Ctor = Fn;
2847 }
2848 if (VD->getType().isDestructedType() != QualType::DK_none) {
2849 // Generate function that emits destructor call for the threadprivate copy
2850 // of the variable VD
2851 CodeGenFunction DtorCGF(CGM);
2852 FunctionArgList Args;
2853 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2854 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
2855 ImplicitParamDecl::Other);
2856 Args.push_back(&Dst);
2857
2858 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
2859 CGM.getContext().VoidTy, Args);
2860 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2861 std::string Name = getName({"__kmpc_global_dtor_", ""});
2862 llvm::Function *Fn =
2863 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
2864 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
2865 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
2866 Loc, Loc);
2867 // Create a scope with an artificial location for the body of this function.
2868 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
2869 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
2870 DtorCGF.GetAddrOfLocalVar(&Dst),
2871 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
2872 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
2873 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2874 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2875 DtorCGF.FinishFunction();
2876 Dtor = Fn;
2877 }
2878 // Do not emit init function if it is not required.
2879 if (!Ctor && !Dtor)
2880 return nullptr;
2881
2882 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2883 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
2884 /*isVarArg=*/false)
2885 ->getPointerTo();
2886 // Copying constructor for the threadprivate variable.
2887 // Must be NULL - reserved by runtime, but currently it requires that this
2888 // parameter is always NULL. Otherwise it fires assertion.
2889 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
2890 if (Ctor == nullptr) {
2891 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
2892 /*isVarArg=*/false)
2893 ->getPointerTo();
2894 Ctor = llvm::Constant::getNullValue(CtorTy);
2895 }
2896 if (Dtor == nullptr) {
2897 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
2898 /*isVarArg=*/false)
2899 ->getPointerTo();
2900 Dtor = llvm::Constant::getNullValue(DtorTy);
2901 }
2902 if (!CGF) {
2903 auto *InitFunctionTy =
2904 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
2905 std::string Name = getName({"__omp_threadprivate_init_", ""});
2906 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
2907 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
2908 CodeGenFunction InitCGF(CGM);
2909 FunctionArgList ArgList;
2910 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
2911 CGM.getTypes().arrangeNullaryFunction(), ArgList,
2912 Loc, Loc);
2913 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
2914 InitCGF.FinishFunction();
2915 return InitFunction;
2916 }
2917 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
2918 }
2919 return nullptr;
2920}
2921
2922bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
2923 llvm::GlobalVariable *Addr,
2924 bool PerformInit) {
2925 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
1
Assuming the condition is false
2926 !CGM.getLangOpts().OpenMPIsDevice)
2927 return false;
2928 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
2929 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
2930 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
2
Calling 'Optional::operator bool'
10
Returning from 'Optional::operator bool'
11
Assuming the condition is false
2931 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
12
Assuming the condition is false
2932 HasRequiresUnifiedSharedMemory))
2933 return CGM.getLangOpts().OpenMPIsDevice;
2934 VD = VD->getDefinition(CGM.getContext());
13
Value assigned to 'VD'
2935 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
14
Assuming 'VD' is null
15
Taking false branch
2936 return CGM.getLangOpts().OpenMPIsDevice;
2937
2938 QualType ASTTy = VD->getType();
16
Called C++ object pointer is null
2939
2940 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
2941 // Produce the unique prefix to identify the new target regions. We use
2942 // the source location of the variable declaration which we know to not
2943 // conflict with any target region.
2944 unsigned DeviceID;
2945 unsigned FileID;
2946 unsigned Line;
2947 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2948 SmallString<128> Buffer, Out;
2949 {
2950 llvm::raw_svector_ostream OS(Buffer);
2951 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2952 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2953 }
2954
2955 const Expr *Init = VD->getAnyInitializer();
2956 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2957 llvm::Constant *Ctor;
2958 llvm::Constant *ID;
2959 if (CGM.getLangOpts().OpenMPIsDevice) {
2960 // Generate function that re-emits the declaration's initializer into
2961 // the threadprivate copy of the variable VD
2962 CodeGenFunction CtorCGF(CGM);
2963
2964 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2965 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2966 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2967 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2968 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2969 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2970 FunctionArgList(), Loc, Loc);
2971 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2972 CtorCGF.EmitAnyExprToMem(Init,
2973 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2974 Init->getType().getQualifiers(),
2975 /*IsInitializer=*/true);
2976 CtorCGF.FinishFunction();
2977 Ctor = Fn;
2978 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
2979 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
2980 } else {
2981 Ctor = new llvm::GlobalVariable(
2982 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2983 llvm::GlobalValue::PrivateLinkage,
2984 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2985 ID = Ctor;
2986 }
2987
2988 // Register the information for the entry associated with the constructor.
2989 Out.clear();
2990 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2991 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
2992 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
2993 }
2994 if (VD->getType().isDestructedType() != QualType::DK_none) {
2995 llvm::Constant *Dtor;
2996 llvm::Constant *ID;
2997 if (CGM.getLangOpts().OpenMPIsDevice) {
2998 // Generate function that emits destructor call for the threadprivate
2999 // copy of the variable VD
3000 CodeGenFunction DtorCGF(CGM);
3001
3002 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
3003 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
3004 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
3005 FTy, Twine(Buffer, "_dtor"), FI, Loc);
3006 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
3007 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
3008 FunctionArgList(), Loc, Loc);
3009 // Create a scope with an artificial location for the body of this
3010 // function.
3011 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
3012 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
3013 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
3014 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
3015 DtorCGF.FinishFunction();
3016 Dtor = Fn;
3017 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
3018 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
3019 } else {
3020 Dtor = new llvm::GlobalVariable(
3021 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
3022 llvm::GlobalValue::PrivateLinkage,
3023 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
3024 ID = Dtor;
3025 }
3026 // Register the information for the entry associated with the destructor.
3027 Out.clear();
3028 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
3029 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
3030 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
3031 }
3032 return CGM.getLangOpts().OpenMPIsDevice;
3033}
3034
3035Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
3036 QualType VarType,
3037 StringRef Name) {
3038 std::string Suffix = getName({"artificial", ""});
3039 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
3040 llvm::Value *GAddr =
3041 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
3042 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS &&
3043 CGM.getTarget().isTLSSupported()) {
3044 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true);
3045 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType));
3046 }
3047 std::string CacheSuffix = getName({"cache", ""});
3048 llvm::Value *Args[] = {
3049 emitUpdateLocation(CGF, SourceLocation()),
3050 getThreadID(CGF, SourceLocation()),
3051 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
3052 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
3053 /*isSigned=*/false),
3054 getOrCreateInternalVariable(
3055 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
3056 return Address(
3057 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3058 CGF.EmitRuntimeCall(
3059 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
3060 VarLVType->getPointerTo(/*AddrSpace=*/0)),
3061 CGM.getContext().getTypeAlignInChars(VarType));
3062}
3063
3064void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond,
3065 const RegionCodeGenTy &ThenGen,
3066 const RegionCodeGenTy &ElseGen) {
3067 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
3068
3069 // If the condition constant folds and can be elided, try to avoid emitting
3070 // the condition and the dead arm of the if/else.
3071 bool CondConstant;
3072 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
3073 if (CondConstant)
3074 ThenGen(CGF);
3075 else
3076 ElseGen(CGF);
3077 return;
3078 }
3079
3080 // Otherwise, the condition did not fold, or we couldn't elide it. Just
3081 // emit the conditional branch.
3082 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
3083 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
3084 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
3085 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
3086
3087 // Emit the 'then' code.
3088 CGF.EmitBlock(ThenBlock);
3089 ThenGen(CGF);
3090 CGF.EmitBranch(ContBlock);
3091 // Emit the 'else' code if present.
3092 // There is no need to emit line number for unconditional branch.
3093 (void)ApplyDebugLocation::CreateEmpty(CGF);
3094 CGF.EmitBlock(ElseBlock);
3095 ElseGen(CGF);
3096 // There is no need to emit line number for unconditional branch.
3097 (void)ApplyDebugLocation::CreateEmpty(CGF);
3098 CGF.EmitBranch(ContBlock);
3099 // Emit the continuation block for code after the if.
3100 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
3101}
3102
3103void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
3104 llvm::Function *OutlinedFn,
3105 ArrayRef<llvm::Value *> CapturedVars,
3106 const Expr *IfCond) {
3107 if (!CGF.HaveInsertPoint())
3108 return;
3109 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
3110 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
3111 PrePostActionTy &) {
3112 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
3113 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
3114 llvm::Value *Args[] = {
3115 RTLoc,
3116 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
3117 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
3118 llvm::SmallVector<llvm::Value *, 16> RealArgs;
3119 RealArgs.append(std::begin(Args), std::end(Args));
3120 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
3121
3122 llvm::FunctionCallee RTLFn =
3123 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
3124 CGF.EmitRuntimeCall(RTLFn, RealArgs);
3125 };
3126 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
3127 PrePostActionTy &) {
3128 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
3129 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
3130 // Build calls:
3131 // __kmpc_serialized_parallel(&Loc, GTid);
3132 llvm::Value *Args[] = {RTLoc, ThreadID};
3133 CGF.EmitRuntimeCall(
3134 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
3135
3136 // OutlinedFn(&GTid, &zero_bound, CapturedStruct);
3137 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
3138 Address ZeroAddrBound =
3139 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
3140 /*Name=*/".bound.zero.addr");
3141 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0));
3142 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
3143 // ThreadId for serialized parallels is 0.
3144 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
3145 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer());
3146 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
3147 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
3148
3149 // __kmpc_end_serialized_parallel(&Loc, GTid);
3150 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
3151 CGF.EmitRuntimeCall(
3152 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
3153 EndArgs);
3154 };
3155 if (IfCond) {
3156 emitIfClause(CGF, IfCond, ThenGen, ElseGen);
3157 } else {
3158 RegionCodeGenTy ThenRCG(ThenGen);
3159 ThenRCG(CGF);
3160 }
3161}
3162
3163// If we're inside an (outlined) parallel region, use the region info's
3164// thread-ID variable (it is passed in a first argument of the outlined function
3165// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
3166// regular serial code region, get thread ID by calling kmp_int32
3167// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
3168// return the address of that temp.
3169Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
3170 SourceLocation Loc) {
3171 if (auto *OMPRegionInfo =
3172 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3173 if (OMPRegionInfo->getThreadIDVariable())
3174 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF);
3175
3176 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3177 QualType Int32Ty =
3178 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
3179 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
3180 CGF.EmitStoreOfScalar(ThreadID,
3181 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
3182
3183 return ThreadIDTemp;
3184}
3185
3186llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
3187 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
3188 SmallString<256> Buffer;
3189 llvm::raw_svector_ostream Out(Buffer);
3190 Out << Name;
3191 StringRef RuntimeName = Out.str();
3192 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
3193 if (Elem.second) {
3194 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3195, __PRETTY_FUNCTION__))
3195 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3195, __PRETTY_FUNCTION__))
;
3196 return &*Elem.second;
3197 }
3198
3199 return Elem.second = new llvm::GlobalVariable(
3200 CGM.getModule(), Ty, /*IsConstant*/ false,
3201 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
3202 Elem.first(), /*InsertBefore=*/nullptr,
3203 llvm::GlobalValue::NotThreadLocal, AddressSpace);
3204}
3205
3206llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
3207 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
3208 std::string Name = getName({Prefix, "var"});
3209 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
3210}
3211
3212namespace {
3213/// Common pre(post)-action for different OpenMP constructs.
3214class CommonActionTy final : public PrePostActionTy {
3215 llvm::FunctionCallee EnterCallee;
3216 ArrayRef<llvm::Value *> EnterArgs;
3217 llvm::FunctionCallee ExitCallee;
3218 ArrayRef<llvm::Value *> ExitArgs;
3219 bool Conditional;
3220 llvm::BasicBlock *ContBlock = nullptr;
3221
3222public:
3223 CommonActionTy(llvm::FunctionCallee EnterCallee,
3224 ArrayRef<llvm::Value *> EnterArgs,
3225 llvm::FunctionCallee ExitCallee,
3226 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
3227 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3228 ExitArgs(ExitArgs), Conditional(Conditional) {}
3229 void Enter(CodeGenFunction &CGF) override {
3230 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3231 if (Conditional) {
3232 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3233 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3234 ContBlock = CGF.createBasicBlock("omp_if.end");
3235 // Generate the branch (If-stmt)
3236 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3237 CGF.EmitBlock(ThenBlock);
3238 }
3239 }
3240 void Done(CodeGenFunction &CGF) {
3241 // Emit the rest of blocks/branches
3242 CGF.EmitBranch(ContBlock);
3243 CGF.EmitBlock(ContBlock, true);
3244 }
3245 void Exit(CodeGenFunction &CGF) override {
3246 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
3247 }
3248};
3249} // anonymous namespace
3250
3251void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3252 StringRef CriticalName,
3253 const RegionCodeGenTy &CriticalOpGen,
3254 SourceLocation Loc, const Expr *Hint) {
3255 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
3256 // CriticalOpGen();
3257 // __kmpc_end_critical(ident_t *, gtid, Lock);
3258 // Prepare arguments and build a call to __kmpc_critical
3259 if (!CGF.HaveInsertPoint())
3260 return;
3261 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3262 getCriticalRegionLock(CriticalName)};
3263 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3264 std::end(Args));
3265 if (Hint) {
3266 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3267 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3268 }
3269 CommonActionTy Action(
3270 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3271 : OMPRTL__kmpc_critical),
3272 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3273 CriticalOpGen.setAction(Action);
3274 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
3275}
3276
3277void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
3278 const RegionCodeGenTy &MasterOpGen,
3279 SourceLocation Loc) {
3280 if (!CGF.HaveInsertPoint())
3281 return;
3282 // if(__kmpc_master(ident_t *, gtid)) {
3283 // MasterOpGen();
3284 // __kmpc_end_master(ident_t *, gtid);
3285 // }
3286 // Prepare arguments and build a call to __kmpc_master
3287 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3288 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3289 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3290 /*Conditional=*/true);
3291 MasterOpGen.setAction(Action);
3292 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3293 Action.Done(CGF);
3294}
3295
3296void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3297 SourceLocation Loc) {
3298 if (!CGF.HaveInsertPoint())
3299 return;
3300 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder();
3301 if (OMPBuilder) {
3302 OMPBuilder->CreateTaskyield(CGF.Builder);
3303 } else {
3304 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3305 llvm::Value *Args[] = {
3306 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3307 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
3308 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield),
3309 Args);
3310 }
3311
3312 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3313 Region->emitUntiedSwitch(CGF);
3314}
3315
3316void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3317 const RegionCodeGenTy &TaskgroupOpGen,
3318 SourceLocation Loc) {
3319 if (!CGF.HaveInsertPoint())
3320 return;
3321 // __kmpc_taskgroup(ident_t *, gtid);
3322 // TaskgroupOpGen();
3323 // __kmpc_end_taskgroup(ident_t *, gtid);
3324 // Prepare arguments and build a call to __kmpc_taskgroup
3325 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3326 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3327 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3328 Args);
3329 TaskgroupOpGen.setAction(Action);
3330 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
3331}
3332
3333/// Given an array of pointers to variables, project the address of a
3334/// given variable.
3335static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3336 unsigned Index, const VarDecl *Var) {
3337 // Pull out the pointer to the variable.
3338 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
3339 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3340
3341 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
3342 Addr = CGF.Builder.CreateElementBitCast(
3343 Addr, CGF.ConvertTypeForMem(Var->getType()));
3344 return Addr;
3345}
3346
3347static llvm::Value *emitCopyprivateCopyFunction(
3348 CodeGenModule &CGM, llvm::Type *ArgsType,
3349 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
3350 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3351 SourceLocation Loc) {
3352 ASTContext &C = CGM.getContext();
3353 // void copy_func(void *LHSArg, void *RHSArg);
3354 FunctionArgList Args;
3355 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3356 ImplicitParamDecl::Other);
3357 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3358 ImplicitParamDecl::Other);
3359 Args.push_back(&LHSArg);
3360 Args.push_back(&RHSArg);
3361 const auto &CGFI =
3362 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
3363 std::string Name =
3364 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3365 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3366 llvm::GlobalValue::InternalLinkage, Name,
3367 &CGM.getModule());
3368 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
3369 Fn->setDoesNotRecurse();
3370 CodeGenFunction CGF(CGM);
3371 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
3372 // Dest = (void*[n])(LHSArg);
3373 // Src = (void*[n])(RHSArg);
3374 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3375 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3376 ArgsType), CGF.getPointerAlign());
3377 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3378 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3379 ArgsType), CGF.getPointerAlign());
3380 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3381 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3382 // ...
3383 // *(Typen*)Dst[n] = *(Typen*)Src[n];
3384 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
3385 const auto *DestVar =
3386 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
3387 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3388
3389 const auto *SrcVar =
3390 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
3391 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3392
3393 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
3394 QualType Type = VD->getType();
3395 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
3396 }
3397 CGF.FinishFunction();
3398 return Fn;
3399}
3400
3401void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
3402 const RegionCodeGenTy &SingleOpGen,
3403 SourceLocation Loc,
3404 ArrayRef<const Expr *> CopyprivateVars,
3405 ArrayRef<const Expr *> SrcExprs,
3406 ArrayRef<const Expr *> DstExprs,
3407 ArrayRef<const Expr *> AssignmentOps) {
3408 if (!CGF.HaveInsertPoint())
3409 return;
3410 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3412, __PRETTY_FUNCTION__))
3411 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3412, __PRETTY_FUNCTION__))
3412 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3412, __PRETTY_FUNCTION__))
;
3413 ASTContext &C = CGM.getContext();
3414 // int32 did_it = 0;
3415 // if(__kmpc_single(ident_t *, gtid)) {
3416 // SingleOpGen();
3417 // __kmpc_end_single(ident_t *, gtid);
3418 // did_it = 1;
3419 // }
3420 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3421 // <copy_func>, did_it);
3422
3423 Address DidIt = Address::invalid();
3424 if (!CopyprivateVars.empty()) {
3425 // int32 did_it = 0;
3426 QualType KmpInt32Ty =
3427 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
3428 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
3429 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
3430 }
3431 // Prepare arguments and build a call to __kmpc_single
3432 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3433 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3434 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3435 /*Conditional=*/true);
3436 SingleOpGen.setAction(Action);
3437 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3438 if (DidIt.isValid()) {
3439 // did_it = 1;
3440 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3441 }
3442 Action.Done(CGF);
3443 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3444 // <copy_func>, did_it);
3445 if (DidIt.isValid()) {
3446 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
3447 QualType CopyprivateArrayTy = C.getConstantArrayType(
3448 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
3449 /*IndexTypeQuals=*/0);
3450 // Create a list of all private variables for copyprivate.
3451 Address CopyprivateList =
3452 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3453 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
3454 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
3455 CGF.Builder.CreateStore(
3456 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3457 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF),
3458 CGF.VoidPtrTy),
3459 Elem);
3460 }
3461 // Build function that copies private values from single region to all other
3462 // threads in the corresponding parallel region.
3463 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
3464 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
3465 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
3466 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
3467 Address CL =
3468 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3469 CGF.VoidPtrTy);
3470 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
3471 llvm::Value *Args[] = {
3472 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3473 getThreadID(CGF, Loc), // i32 <gtid>
3474 BufSize, // size_t <buf_size>
3475 CL.getPointer(), // void *<copyprivate list>
3476 CpyFn, // void (*) (void *, void *) <copy_func>
3477 DidItVal // i32 did_it
3478 };
3479 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3480 }
3481}
3482
3483void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3484 const RegionCodeGenTy &OrderedOpGen,
3485 SourceLocation Loc, bool IsThreads) {
3486 if (!CGF.HaveInsertPoint())
3487 return;
3488 // __kmpc_ordered(ident_t *, gtid);
3489 // OrderedOpGen();
3490 // __kmpc_end_ordered(ident_t *, gtid);
3491 // Prepare arguments and build a call to __kmpc_ordered
3492 if (IsThreads) {
3493 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3494 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3495 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3496 Args);
3497 OrderedOpGen.setAction(Action);
3498 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3499 return;
3500 }
3501 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3502}
3503
3504unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
3505 unsigned Flags;
3506 if (Kind == OMPD_for)
3507 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3508 else if (Kind == OMPD_sections)
3509 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3510 else if (Kind == OMPD_single)
3511 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3512 else if (Kind == OMPD_barrier)
3513 Flags = OMP_IDENT_BARRIER_EXPL;
3514 else
3515 Flags = OMP_IDENT_BARRIER_IMPL;
3516 return Flags;
3517}
3518
3519void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3520 CodeGenFunction &CGF, const OMPLoopDirective &S,
3521 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3522 // Check if the loop directive is actually a doacross loop directive. In this
3523 // case choose static, 1 schedule.
3524 if (llvm::any_of(
3525 S.getClausesOfKind<OMPOrderedClause>(),
3526 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3527 ScheduleKind = OMPC_SCHEDULE_static;
3528 // Chunk size is 1 in this case.
3529 llvm::APInt ChunkSize(32, 1);
3530 ChunkExpr = IntegerLiteral::Create(
3531 CGF.getContext(), ChunkSize,
3532 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3533 SourceLocation());
3534 }
3535}
3536
3537void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3538 OpenMPDirectiveKind Kind, bool EmitChecks,
3539 bool ForceSimpleCall) {
3540 // Check if we should use the OMPBuilder
3541 auto *OMPRegionInfo =
3542 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
3543 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder();
3544 if (OMPBuilder) {
3545 CGF.Builder.restoreIP(OMPBuilder->CreateBarrier(
3546 CGF.Builder, Kind, ForceSimpleCall, EmitChecks));
3547 return;
3548 }
3549
3550 if (!CGF.HaveInsertPoint())
3551 return;
3552 // Build call __kmpc_cancel_barrier(loc, thread_id);
3553 // Build call __kmpc_barrier(loc, thread_id);
3554 unsigned Flags = getDefaultFlagsForBarriers(Kind);
3555 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3556 // thread_id);
3557 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3558 getThreadID(CGF, Loc)};
3559 if (OMPRegionInfo) {
3560 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
3561 llvm::Value *Result = CGF.EmitRuntimeCall(
3562 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
3563 if (EmitChecks) {
3564 // if (__kmpc_cancel_barrier()) {
3565 // exit from construct;
3566 // }
3567 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3568 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3569 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
3570 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3571 CGF.EmitBlock(ExitBB);
3572 // exit from construct;
3573 CodeGenFunction::JumpDest CancelDestination =
3574 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
3575 CGF.EmitBranchThroughCleanup(CancelDestination);
3576 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3577 }
3578 return;
3579 }
3580 }
3581 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
3582}
3583
3584/// Map the OpenMP loop schedule to the runtime enumeration.
3585static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
3586 bool Chunked, bool Ordered) {
3587 switch (ScheduleKind) {
3588 case OMPC_SCHEDULE_static:
3589 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3590 : (Ordered ? OMP_ord_static : OMP_sch_static);
3591 case OMPC_SCHEDULE_dynamic:
3592 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
3593 case OMPC_SCHEDULE_guided:
3594 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
3595 case OMPC_SCHEDULE_runtime:
3596 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3597 case OMPC_SCHEDULE_auto:
3598 return Ordered ? OMP_ord_auto : OMP_sch_auto;
3599 case OMPC_SCHEDULE_unknown:
3600 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3600, __PRETTY_FUNCTION__))
;
3601 return Ordered ? OMP_ord_static : OMP_sch_static;
3602 }
3603 llvm_unreachable("Unexpected runtime schedule")::llvm::llvm_unreachable_internal("Unexpected runtime schedule"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3603)
;
3604}
3605
3606/// Map the OpenMP distribute schedule to the runtime enumeration.
3607static OpenMPSchedType
3608getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3609 // only static is allowed for dist_schedule
3610 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3611}
3612
3613bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3614 bool Chunked) const {
3615 OpenMPSchedType Schedule =
3616 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3617 return Schedule == OMP_sch_static;
3618}
3619
3620bool CGOpenMPRuntime::isStaticNonchunked(
3621 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3622 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3623 return Schedule == OMP_dist_sch_static;
3624}
3625
3626bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3627 bool Chunked) const {
3628 OpenMPSchedType Schedule =
3629 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3630 return Schedule == OMP_sch_static_chunked;
3631}
3632
3633bool CGOpenMPRuntime::isStaticChunked(
3634 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3635 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3636 return Schedule == OMP_dist_sch_static_chunked;
3637}
3638
3639bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
3640 OpenMPSchedType Schedule =
3641 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
3642 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3642, __PRETTY_FUNCTION__))
;
3643 return Schedule != OMP_sch_static;
3644}
3645
3646static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
3647 OpenMPScheduleClauseModifier M1,
3648 OpenMPScheduleClauseModifier M2) {
3649 int Modifier = 0;
3650 switch (M1) {
3651 case OMPC_SCHEDULE_MODIFIER_monotonic:
3652 Modifier = OMP_sch_modifier_monotonic;
3653 break;
3654 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
3655 Modifier = OMP_sch_modifier_nonmonotonic;
3656 break;
3657 case OMPC_SCHEDULE_MODIFIER_simd:
3658 if (Schedule == OMP_sch_static_chunked)
3659 Schedule = OMP_sch_static_balanced_chunked;
3660 break;
3661 case OMPC_SCHEDULE_MODIFIER_last:
3662 case OMPC_SCHEDULE_MODIFIER_unknown:
3663 break;
3664 }
3665 switch (M2) {
3666 case OMPC_SCHEDULE_MODIFIER_monotonic:
3667 Modifier = OMP_sch_modifier_monotonic;
3668 break;
3669 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
3670 Modifier = OMP_sch_modifier_nonmonotonic;
3671 break;
3672 case OMPC_SCHEDULE_MODIFIER_simd:
3673 if (Schedule == OMP_sch_static_chunked)
3674 Schedule = OMP_sch_static_balanced_chunked;
3675 break;
3676 case OMPC_SCHEDULE_MODIFIER_last:
3677 case OMPC_SCHEDULE_MODIFIER_unknown:
3678 break;
3679 }
3680 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
3681 // If the static schedule kind is specified or if the ordered clause is
3682 // specified, and if the nonmonotonic modifier is not specified, the effect is
3683 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
3684 // modifier is specified, the effect is as if the nonmonotonic modifier is
3685 // specified.
3686 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
3687 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
3688 Schedule == OMP_sch_static_balanced_chunked ||
3689 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
3690 Schedule == OMP_dist_sch_static_chunked ||
3691 Schedule == OMP_dist_sch_static))
3692 Modifier = OMP_sch_modifier_nonmonotonic;
3693 }
3694 return Schedule | Modifier;
3695}
3696
3697void CGOpenMPRuntime::emitForDispatchInit(
3698 CodeGenFunction &CGF, SourceLocation Loc,
3699 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3700 bool Ordered, const DispatchRTInput &DispatchValues) {
3701 if (!CGF.HaveInsertPoint())
3702 return;
3703 OpenMPSchedType Schedule = getRuntimeSchedule(
3704 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
3705 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3708, __PRETTY_FUNCTION__))
3706 (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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3708, __PRETTY_FUNCTION__))
3707 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3708, __PRETTY_FUNCTION__))
3708 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3708, __PRETTY_FUNCTION__))
;
3709 // Call __kmpc_dispatch_init(
3710 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3711 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3712 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
3713
3714 // If the Chunk was not specified in the clause - use default value 1.
3715 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3716 : CGF.Builder.getIntN(IVSize, 1);
3717 llvm::Value *Args[] = {
3718 emitUpdateLocation(CGF, Loc),
3719 getThreadID(CGF, Loc),
3720 CGF.Builder.getInt32(addMonoNonMonoModifier(
3721 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
3722 DispatchValues.LB, // Lower
3723 DispatchValues.UB, // Upper
3724 CGF.Builder.getIntN(IVSize, 1), // Stride
3725 Chunk // Chunk
3726 };
3727 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3728}
3729
3730static void emitForStaticInitCall(
3731 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
3732 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
3733 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
3734 const CGOpenMPRuntime::StaticRTInput &Values) {
3735 if (!CGF.HaveInsertPoint())
3736 return;
3737
3738 assert(!Values.Ordered)((!Values.Ordered) ? static_cast<void> (0) : __assert_fail
("!Values.Ordered", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3738, __PRETTY_FUNCTION__))
;
3739 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3743, __PRETTY_FUNCTION__))
3740 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3743, __PRETTY_FUNCTION__))
3741 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3743, __PRETTY_FUNCTION__))
3742 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3743, __PRETTY_FUNCTION__))
3743 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3743, __PRETTY_FUNCTION__))
;
3744
3745 // Call __kmpc_for_static_init(
3746 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3747 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3748 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3749 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3750 llvm::Value *Chunk = Values.Chunk;
3751 if (Chunk == nullptr) {
3752 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3754, __PRETTY_FUNCTION__))
3753 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3754, __PRETTY_FUNCTION__))
3754 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3754, __PRETTY_FUNCTION__))
;
3755 // If the Chunk was not specified in the clause - use default value 1.
3756 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3757 } else {
3758 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3762, __PRETTY_FUNCTION__))
3759 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3762, __PRETTY_FUNCTION__))
3760 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3762, __PRETTY_FUNCTION__))
3761 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3762, __PRETTY_FUNCTION__))
3762 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3762, __PRETTY_FUNCTION__))
;
3763 }
3764 llvm::Value *Args[] = {
3765 UpdateLocation,
3766 ThreadId,
3767 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
3768 M2)), // Schedule type
3769 Values.IL.getPointer(), // &isLastIter
3770 Values.LB.getPointer(), // &LB
3771 Values.UB.getPointer(), // &UB
3772 Values.ST.getPointer(), // &Stride
3773 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3774 Chunk // Chunk
3775 };
3776 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
3777}
3778
3779void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3780 SourceLocation Loc,
3781 OpenMPDirectiveKind DKind,
3782 const OpenMPScheduleTy &ScheduleKind,
3783 const StaticRTInput &Values) {
3784 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3785 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3786 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3787, __PRETTY_FUNCTION__))
3787 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3787, __PRETTY_FUNCTION__))
;
3788 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
3789 isOpenMPLoopDirective(DKind)
3790 ? OMP_IDENT_WORK_LOOP
3791 : OMP_IDENT_WORK_SECTIONS);
3792 llvm::Value *ThreadId = getThreadID(CGF, Loc);
3793 llvm::FunctionCallee StaticInitFunction =
3794 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
3795 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
3796 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3797 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
3798}
3799
3800void CGOpenMPRuntime::emitDistributeStaticInit(
3801 CodeGenFunction &CGF, SourceLocation Loc,
3802 OpenMPDistScheduleClauseKind SchedKind,
3803 const CGOpenMPRuntime::StaticRTInput &Values) {
3804 OpenMPSchedType ScheduleNum =
3805 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
3806 llvm::Value *UpdatedLocation =
3807 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
3808 llvm::Value *ThreadId = getThreadID(CGF, Loc);
3809 llvm::FunctionCallee StaticInitFunction =
3810 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
3811 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3812 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
3813 OMPC_SCHEDULE_MODIFIER_unknown, Values);
3814}
3815
3816void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
3817 SourceLocation Loc,
3818 OpenMPDirectiveKind DKind) {
3819 if (!CGF.HaveInsertPoint())
3820 return;
3821 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
3822 llvm::Value *Args[] = {
3823 emitUpdateLocation(CGF, Loc,
3824 isOpenMPDistributeDirective(DKind)
3825 ? OMP_IDENT_WORK_DISTRIBUTE
3826 : isOpenMPLoopDirective(DKind)
3827 ? OMP_IDENT_WORK_LOOP
3828 : OMP_IDENT_WORK_SECTIONS),
3829 getThreadID(CGF, Loc)};
3830 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
3831 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3832 Args);
3833}
3834
3835void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3836 SourceLocation Loc,
3837 unsigned IVSize,
3838 bool IVSigned) {
3839 if (!CGF.HaveInsertPoint())
3840 return;
3841 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
3842 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3843 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3844}
3845
3846llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3847 SourceLocation Loc, unsigned IVSize,
3848 bool IVSigned, Address IL,
3849 Address LB, Address UB,
3850 Address ST) {
3851 // Call __kmpc_dispatch_next(
3852 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3853 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3854 // kmp_int[32|64] *p_stride);
3855 llvm::Value *Args[] = {
3856 emitUpdateLocation(CGF, Loc),
3857 getThreadID(CGF, Loc),
3858 IL.getPointer(), // &isLastIter
3859 LB.getPointer(), // &Lower
3860 UB.getPointer(), // &Upper
3861 ST.getPointer() // &Stride
3862 };
3863 llvm::Value *Call =
3864 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3865 return CGF.EmitScalarConversion(
3866 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
3867 CGF.getContext().BoolTy, Loc);
3868}
3869
3870void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3871 llvm::Value *NumThreads,
3872 SourceLocation Loc) {
3873 if (!CGF.HaveInsertPoint())
3874 return;
3875 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3876 llvm::Value *Args[] = {
3877 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3878 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
3879 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3880 Args);
3881}
3882
3883void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3884 ProcBindKind ProcBind,
3885 SourceLocation Loc) {
3886 if (!CGF.HaveInsertPoint())
3887 return;
3888 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3888, __PRETTY_FUNCTION__))
;
3889 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3890 llvm::Value *Args[] = {
3891 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3892 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)};
3893 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3894}
3895
3896void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3897 SourceLocation Loc, llvm::AtomicOrdering AO) {
3898 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder();
3899 if (OMPBuilder) {
3900 OMPBuilder->CreateFlush(CGF.Builder);
3901 } else {
3902 if (!CGF.HaveInsertPoint())
3903 return;
3904 // Build call void __kmpc_flush(ident_t *loc)
3905 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3906 emitUpdateLocation(CGF, Loc));
3907 }
3908}
3909
3910namespace {
3911/// Indexes of fields for type kmp_task_t.
3912enum KmpTaskTFields {
3913 /// List of shared variables.
3914 KmpTaskTShareds,
3915 /// Task routine.
3916 KmpTaskTRoutine,
3917 /// Partition id for the untied tasks.
3918 KmpTaskTPartId,
3919 /// Function with call of destructors for private variables.
3920 Data1,
3921 /// Task priority.
3922 Data2,
3923 /// (Taskloops only) Lower bound.
3924 KmpTaskTLowerBound,
3925 /// (Taskloops only) Upper bound.
3926 KmpTaskTUpperBound,
3927 /// (Taskloops only) Stride.
3928 KmpTaskTStride,
3929 /// (Taskloops only) Is last iteration flag.
3930 KmpTaskTLastIter,
3931 /// (Taskloops only) Reduction data.
3932 KmpTaskTReductions,
3933};
3934} // anonymous namespace
3935
3936bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
3937 return OffloadEntriesTargetRegion.empty() &&
3938 OffloadEntriesDeviceGlobalVar.empty();
3939}
3940
3941/// Initialize target region entry.
3942void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3943 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3944 StringRef ParentName, unsigned LineNum,
3945 unsigned Order) {
3946 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3948, __PRETTY_FUNCTION__))
3947 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3948, __PRETTY_FUNCTION__))
3948 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3948, __PRETTY_FUNCTION__))
;
3949 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
3950 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
3951 OMPTargetRegionEntryTargetRegion);
3952 ++OffloadingEntriesNum;
3953}
3954
3955void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3956 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3957 StringRef ParentName, unsigned LineNum,
3958 llvm::Constant *Addr, llvm::Constant *ID,
3959 OMPTargetRegionEntryKind Flags) {
3960 // If we are emitting code for a target, the entry is already initialized,
3961 // only has to be registered.
3962 if (CGM.getLangOpts().OpenMPIsDevice) {
3963 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3964 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3965 DiagnosticsEngine::Error,
3966 "Unable to find target region on line '%0' in the device code.");
3967 CGM.getDiags().Report(DiagID) << LineNum;
3968 return;
3969 }
3970 auto &Entry =
3971 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
3972 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3972, __PRETTY_FUNCTION__))
;
3973 Entry.setAddress(Addr);
3974 Entry.setID(ID);
3975 Entry.setFlags(Flags);
3976 } else {
3977 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
3978 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
3979 ++OffloadingEntriesNum;
3980 }
3981}
3982
3983bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
3984 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3985 unsigned LineNum) const {
3986 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3987 if (PerDevice == OffloadEntriesTargetRegion.end())
3988 return false;
3989 auto PerFile = PerDevice->second.find(FileID);
3990 if (PerFile == PerDevice->second.end())
3991 return false;
3992 auto PerParentName = PerFile->second.find(ParentName);
3993 if (PerParentName == PerFile->second.end())
3994 return false;
3995 auto PerLine = PerParentName->second.find(LineNum);
3996 if (PerLine == PerParentName->second.end())
3997 return false;
3998 // Fail if this entry is already registered.
3999 if (PerLine->second.getAddress() || PerLine->second.getID())
4000 return false;
4001 return true;
4002}
4003
4004void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
4005 const OffloadTargetRegionEntryInfoActTy &Action) {
4006 // Scan all target region entries and perform the provided action.
4007 for (const auto &D : OffloadEntriesTargetRegion)
4008 for (const auto &F : D.second)
4009 for (const auto &P : F.second)
4010 for (const auto &L : P.second)
4011 Action(D.first, F.first, P.first(), L.first, L.second);
4012}
4013
4014void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4015 initializeDeviceGlobalVarEntryInfo(StringRef Name,
4016 OMPTargetGlobalVarEntryKind Flags,
4017 unsigned Order) {
4018 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4020, __PRETTY_FUNCTION__))
4019 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4020, __PRETTY_FUNCTION__))
4020 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4020, __PRETTY_FUNCTION__))
;
4021 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
4022 ++OffloadingEntriesNum;
4023}
4024
4025void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4026 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
4027 CharUnits VarSize,
4028 OMPTargetGlobalVarEntryKind Flags,
4029 llvm::GlobalValue::LinkageTypes Linkage) {
4030 if (CGM.getLangOpts().OpenMPIsDevice) {
4031 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
4032 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4033, __PRETTY_FUNCTION__))
4033 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4033, __PRETTY_FUNCTION__))
;
4034 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4035, __PRETTY_FUNCTION__))
4035 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4035, __PRETTY_FUNCTION__))
;
4036 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
4037 if (Entry.getVarSize().isZero()) {
4038 Entry.setVarSize(VarSize);
4039 Entry.setLinkage(Linkage);
4040 }
4041 return;
4042 }
4043 Entry.setVarSize(VarSize);
4044 Entry.setLinkage(Linkage);
4045 Entry.setAddress(Addr);
4046 } else {
4047 if (hasDeviceGlobalVarEntryInfo(VarName)) {
4048 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
4049 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4050, __PRETTY_FUNCTION__))
4050 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4050, __PRETTY_FUNCTION__))
;
4051 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4052, __PRETTY_FUNCTION__))
4052 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4052, __PRETTY_FUNCTION__))
;
4053 if (Entry.getVarSize().isZero()) {
4054 Entry.setVarSize(VarSize);
4055 Entry.setLinkage(Linkage);
4056 }
4057 return;
4058 }
4059 OffloadEntriesDeviceGlobalVar.try_emplace(
4060 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
4061 ++OffloadingEntriesNum;
4062 }
4063}
4064
4065void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4066 actOnDeviceGlobalVarEntriesInfo(
4067 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
4068 // Scan all target region entries and perform the provided action.
4069 for (const auto &E : OffloadEntriesDeviceGlobalVar)
4070 Action(E.getKey(), E.getValue());
4071}
4072
4073void CGOpenMPRuntime::createOffloadEntry(
4074 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4075 llvm::GlobalValue::LinkageTypes Linkage) {
4076 StringRef Name = Addr->getName();
4077 llvm::Module &M = CGM.getModule();
4078 llvm::LLVMContext &C = M.getContext();
4079
4080 // Create constant string with the name.
4081 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4082
4083 std::string StringName = getName({"omp_offloading", "entry_name"});
4084 auto *Str = new llvm::GlobalVariable(
4085 M, StrPtrInit->getType(), /*isConstant=*/true,
4086 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
4087 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4088
4089 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4090 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4091 llvm::ConstantInt::get(CGM.SizeTy, Size),
4092 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4093 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
4094 std::string EntryName = getName({"omp_offloading", "entry", ""});
4095 llvm::GlobalVariable *Entry = createGlobalStruct(
4096 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4097 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
4098
4099 // The entry has to be created in the section the linker expects it to be.
4100 Entry->setSection("omp_offloading_entries");
4101}
4102
4103void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4104 // Emit the offloading entries and metadata so that the device codegen side
4105 // can easily figure out what to emit. The produced metadata looks like
4106 // this:
4107 //
4108 // !omp_offload.info = !{!1, ...}
4109 //
4110 // Right now we only generate metadata for function that contain target
4111 // regions.
4112
4113 // If we are in simd mode or there are no entries, we don't need to do
4114 // anything.
4115 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty())
4116 return;
4117
4118 llvm::Module &M = CGM.getModule();
4119 llvm::LLVMContext &C = M.getContext();
4120 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *,
4121 SourceLocation, StringRef>,
4122 16>
4123 OrderedEntries(OffloadEntriesInfoManager.size());
4124 llvm::SmallVector<StringRef, 16> ParentFunctions(
4125 OffloadEntriesInfoManager.size());
4126
4127 // Auxiliary methods to create metadata values and strings.
4128 auto &&GetMDInt = [this](unsigned V) {
4129 return llvm::ConstantAsMetadata::get(
4130 llvm::ConstantInt::get(CGM.Int32Ty, V));
4131 };
4132
4133 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4134
4135 // Create the offloading info metadata node.
4136 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
4137
4138 // Create function that emits metadata for each target region entry;
4139 auto &&TargetRegionMetadataEmitter =
4140 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt,
4141 &GetMDString](
4142 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4143 unsigned Line,
4144 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4145 // Generate metadata for target regions. Each entry of this metadata
4146 // contains:
4147 // - Entry 0 -> Kind of this type of metadata (0).
4148 // - Entry 1 -> Device ID of the file where the entry was identified.
4149 // - Entry 2 -> File ID of the file where the entry was identified.
4150 // - Entry 3 -> Mangled name of the function where the entry was
4151 // identified.
4152 // - Entry 4 -> Line in the file where the entry was identified.
4153 // - Entry 5 -> Order the entry was created.
4154 // The first element of the metadata node is the kind.
4155 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4156 GetMDInt(FileID), GetMDString(ParentName),
4157 GetMDInt(Line), GetMDInt(E.getOrder())};
4158
4159 SourceLocation Loc;
4160 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
4161 E = CGM.getContext().getSourceManager().fileinfo_end();
4162 I != E; ++I) {
4163 if (I->getFirst()->getUniqueID().getDevice() == DeviceID &&
4164 I->getFirst()->getUniqueID().getFile() == FileID) {
4165 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
4166 I->getFirst(), Line, 1);
4167 break;
4168 }
4169 }
4170 // Save this entry in the right position of the ordered entries array.
4171 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName);
4172 ParentFunctions[E.getOrder()] = ParentName;
4173
4174 // Add metadata to the named metadata node.
4175 MD->addOperand(llvm::MDNode::get(C, Ops));
4176 };
4177
4178 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4179 TargetRegionMetadataEmitter);
4180
4181 // Create function that emits metadata for each device global variable entry;
4182 auto &&DeviceGlobalVarMetadataEmitter =
4183 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4184 MD](StringRef MangledName,
4185 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4186 &E) {
4187 // Generate metadata for global variables. Each entry of this metadata
4188 // contains:
4189 // - Entry 0 -> Kind of this type of metadata (1).
4190 // - Entry 1 -> Mangled name of the variable.
4191 // - Entry 2 -> Declare target kind.
4192 // - Entry 3 -> Order the entry was created.
4193 // The first element of the metadata node is the kind.
4194 llvm::Metadata *Ops[] = {
4195 GetMDInt(E.getKind()), GetMDString(MangledName),
4196 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4197
4198 // Save this entry in the right position of the ordered entries array.
4199 OrderedEntries[E.getOrder()] =
4200 std::make_tuple(&E, SourceLocation(), MangledName);
4201
4202 // Add metadata to the named metadata node.
4203 MD->addOperand(llvm::MDNode::get(C, Ops));
4204 };
4205
4206 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4207 DeviceGlobalVarMetadataEmitter);
4208
4209 for (const auto &E : OrderedEntries) {
4210 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4210, __PRETTY_FUNCTION__))
;
4211 if (const auto *CE =
4212 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
4213 std::get<0>(E))) {
4214 if (!CE->getID() || !CE->getAddress()) {
4215 // Do not blame the entry if the parent funtion is not emitted.
4216 StringRef FnName = ParentFunctions[CE->getOrder()];
4217 if (!CGM.GetGlobalValue(FnName))
4218 continue;
4219 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4220 DiagnosticsEngine::Error,
4221 "Offloading entry for target region in %0 is incorrect: either the "
4222 "address or the ID is invalid.");
4223 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName;
4224 continue;
4225 }
4226 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
4227 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
4228 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy::
4229 OffloadEntryInfoDeviceGlobalVar>(
4230 std::get<0>(E))) {
4231 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4232 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4233 CE->getFlags());
4234 switch (Flags) {
4235 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
4236 if (CGM.getLangOpts().OpenMPIsDevice &&
4237 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4238 continue;
4239 if (!CE->getAddress()) {
4240 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4241 DiagnosticsEngine::Error, "Offloading entry for declare target "
4242 "variable %0 is incorrect: the "
4243 "address is invalid.");
4244 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E);
4245 continue;
4246 }
4247 // The vaiable has no definition - no need to add the entry.
4248 if (CE->getVarSize().isZero())
4249 continue;
4250 break;
4251 }
4252 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4253 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4255, __PRETTY_FUNCTION__))
4254 (!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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4255, __PRETTY_FUNCTION__))
4255 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4255, __PRETTY_FUNCTION__))
;
4256 if (CGM.getLangOpts().OpenMPIsDevice)
4257 continue;
4258 if (!CE->getAddress()) {
4259 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4260 DiagnosticsEngine::Error,
4261 "Offloading entry for declare target variable is incorrect: the "
4262 "address is invalid.");
4263 CGM.getDiags().Report(DiagID);
4264 continue;
4265 }
4266 break;
4267 }
4268 createOffloadEntry(CE->getAddress(), CE->getAddress(),
4269 CE->getVarSize().getQuantity(), Flags,
4270 CE->getLinkage());
4271 } else {
4272 llvm_unreachable("Unsupported entry kind.")::llvm::llvm_unreachable_internal("Unsupported entry kind.", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4272)
;
4273 }
4274 }
4275}
4276
4277/// Loads all the offload entries information from the host IR
4278/// metadata.
4279void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4280 // If we are in target mode, load the metadata from the host IR. This code has
4281 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4282
4283 if (!CGM.getLangOpts().OpenMPIsDevice)
4284 return;
4285
4286 if (CGM.getLangOpts().OMPHostIRFile.empty())
4287 return;
4288
4289 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
4290 if (auto EC = Buf.getError()) {
4291 CGM.getDiags().Report(diag::err_cannot_open_file)
4292 << CGM.getLangOpts().OMPHostIRFile << EC.message();
4293 return;
4294 }
4295
4296 llvm::LLVMContext C;
4297 auto ME = expectedToErrorOrAndEmitErrors(
4298 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
4299
4300 if (auto EC = ME.getError()) {
4301 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4302 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4303 CGM.getDiags().Report(DiagID)
4304 << CGM.getLangOpts().OMPHostIRFile << EC.message();
4305 return;
4306 }
4307
4308 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4309 if (!MD)
4310 return;
4311
4312 for (llvm::MDNode *MN : MD->operands()) {
4313 auto &&GetMDInt = [MN](unsigned Idx) {
4314 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
4315 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4316 };
4317
4318 auto &&GetMDString = [MN](unsigned Idx) {
4319 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
4320 return V->getString();
4321 };
4322
4323 switch (GetMDInt(0)) {
4324 default:
4325 llvm_unreachable("Unexpected metadata!")::llvm::llvm_unreachable_internal("Unexpected metadata!", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4325)
;
4326 break;
4327 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4328 OffloadingEntryInfoTargetRegion:
4329 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
4330 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4331 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4332 /*Order=*/GetMDInt(5));
4333 break;
4334 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4335 OffloadingEntryInfoDeviceGlobalVar:
4336 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4337 /*MangledName=*/GetMDString(1),
4338 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4339 /*Flags=*/GetMDInt(2)),
4340 /*Order=*/GetMDInt(3));
4341 break;
4342 }
4343 }
4344}
4345
4346void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4347 if (!KmpRoutineEntryPtrTy) {
4348 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
4349 ASTContext &C = CGM.getContext();
4350 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4351 FunctionProtoType::ExtProtoInfo EPI;
4352 KmpRoutineEntryPtrQTy = C.getPointerType(
4353 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4354 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4355 }
4356}
4357
4358QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
4359 // Make sure the type of the entry is already created. This is the type we
4360 // have to create:
4361 // struct __tgt_offload_entry{
4362 // void *addr; // Pointer to the offload entry info.
4363 // // (function or global)
4364 // char *name; // Name of the function or global.
4365 // size_t size; // Size of the entry info (0 if it a function).
4366 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4367 // int32_t reserved; // Reserved, to use by the runtime library.
4368 // };
4369 if (TgtOffloadEntryQTy.isNull()) {
4370 ASTContext &C = CGM.getContext();
4371 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
4372 RD->startDefinition();
4373 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4374 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4375 addFieldToRecordDecl(C, RD, C.getSizeType());
4376 addFieldToRecordDecl(
4377 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4378 addFieldToRecordDecl(
4379 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4380 RD->completeDefinition();
4381 RD->addAttr(PackedAttr::CreateImplicit(C));
4382 TgtOffloadEntryQTy = C.getRecordType(RD);
4383 }
4384 return TgtOffloadEntryQTy;
4385}
4386
4387namespace {
4388struct PrivateHelpersTy {
4389 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4390 const VarDecl *PrivateElemInit)
4391 : Original(Original), PrivateCopy(PrivateCopy),
4392 PrivateElemInit(PrivateElemInit) {}
4393 const VarDecl *Original;
4394 const VarDecl *PrivateCopy;
4395 const VarDecl *PrivateElemInit;
4396};
4397typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
4398} // anonymous namespace
4399
4400static RecordDecl *
4401createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
4402 if (!Privates.empty()) {
4403 ASTContext &C = CGM.getContext();
4404 // Build struct .kmp_privates_t. {
4405 // /* private vars */
4406 // };
4407 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
4408 RD->startDefinition();
4409 for (const auto &Pair : Privates) {
4410 const VarDecl *VD = Pair.second.Original;
4411 QualType Type = VD->getType().getNonReferenceType();
4412 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
4413 if (VD->hasAttrs()) {
4414 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4415 E(VD->getAttrs().end());
4416 I != E; ++I)
4417 FD->addAttr(*I);
4418 }
4419 }
4420 RD->completeDefinition();
4421 return RD;
4422 }
4423 return nullptr;
4424}
4425
4426static RecordDecl *
4427createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4428 QualType KmpInt32Ty,
4429 QualType KmpRoutineEntryPointerQTy) {
4430 ASTContext &C = CGM.getContext();
4431 // Build struct kmp_task_t {
4432 // void * shareds;
4433 // kmp_routine_entry_t routine;
4434 // kmp_int32 part_id;
4435 // kmp_cmplrdata_t data1;
4436 // kmp_cmplrdata_t data2;
4437 // For taskloops additional fields:
4438 // kmp_uint64 lb;
4439 // kmp_uint64 ub;
4440 // kmp_int64 st;
4441 // kmp_int32 liter;
4442 // void * reductions;
4443 // };
4444 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
4445 UD->startDefinition();
4446 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4447 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4448 UD->completeDefinition();
4449 QualType KmpCmplrdataTy = C.getRecordType(UD);
4450 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
4451 RD->startDefinition();
4452 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4453 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4454 addFieldToRecordDecl(C, RD, KmpInt32Ty);
4455 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4456 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4457 if (isOpenMPTaskLoopDirective(Kind)) {
4458 QualType KmpUInt64Ty =
4459 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4460 QualType KmpInt64Ty =
4461 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4462 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4463 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4464 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4465 addFieldToRecordDecl(C, RD, KmpInt32Ty);
4466 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4467 }
4468 RD->completeDefinition();
4469 return RD;
4470}
4471
4472static RecordDecl *
4473createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
4474 ArrayRef<PrivateDataTy> Privates) {
4475 ASTContext &C = CGM.getContext();
4476 // Build struct kmp_task_t_with_privates {
4477 // kmp_task_t task_data;
4478 // .kmp_privates_t. privates;
4479 // };
4480 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
4481 RD->startDefinition();
4482 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
4483 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
4484 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
4485 RD->completeDefinition();
4486 return RD;
4487}
4488
4489/// Emit a proxy function which accepts kmp_task_t as the second
4490/// argument.
4491/// \code
4492/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
4493/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
4494/// For taskloops:
4495/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4496/// tt->reductions, tt->shareds);
4497/// return 0;
4498/// }
4499/// \endcode
4500static llvm::Function *
4501emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
4502 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4503 QualType KmpTaskTWithPrivatesPtrQTy,
4504 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
4505 QualType SharedsPtrTy, llvm::Function *TaskFunction,
4506 llvm::Value *TaskPrivatesMap) {
4507 ASTContext &C = CGM.getContext();
4508 FunctionArgList Args;
4509 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4510 ImplicitParamDecl::Other);
4511 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4512 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4513 ImplicitParamDecl::Other);
4514 Args.push_back(&GtidArg);
4515 Args.push_back(&TaskTypeArg);
4516 const auto &TaskEntryFnInfo =
4517 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
4518 llvm::FunctionType *TaskEntryTy =
4519 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
4520 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4521 auto *TaskEntry = llvm::Function::Create(
4522 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
4523 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
4524 TaskEntry->setDoesNotRecurse();
4525 CodeGenFunction CGF(CGM);
4526 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4527 Loc, Loc);
4528
4529 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
4530 // tt,
4531 // For taskloops:
4532 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4533 // tt->task_data.shareds);
4534 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
4535 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
4536 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4537 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4538 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4539 const auto *KmpTaskTWithPrivatesQTyRD =
4540 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4541 LValue Base =
4542 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4543 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
4544 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
4545 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
4546 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
4547
4548 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
4549 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4550 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4551 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
4552 CGF.ConvertTypeForMem(SharedsPtrTy));
4553
4554 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4555 llvm::Value *PrivatesParam;
4556 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
4557 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
4558 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4559 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy);
4560 } else {
4561 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
4562 }
4563
4564 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4565 TaskPrivatesMap,
4566 CGF.Builder
4567 .CreatePointerBitCastOrAddrSpaceCast(
4568 TDBase.getAddress(CGF), CGF.VoidPtrTy)
4569 .getPointer()};
4570 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4571 std::end(CommonArgs));
4572 if (isOpenMPTaskLoopDirective(Kind)) {
4573 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
4574 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4575 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
4576 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
4577 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4578 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
4579 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
4580 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4581 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
4582 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4583 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4584 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
4585 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
4586 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4587 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
4588 CallArgs.push_back(LBParam);
4589 CallArgs.push_back(UBParam);
4590 CallArgs.push_back(StParam);
4591 CallArgs.push_back(LIParam);
4592 CallArgs.push_back(RParam);
4593 }
4594 CallArgs.push_back(SharedsParam);
4595
4596 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4597 CallArgs);
4598 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4599 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
4600 CGF.FinishFunction();
4601 return TaskEntry;
4602}
4603
4604static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4605 SourceLocation Loc,
4606 QualType KmpInt32Ty,
4607 QualType KmpTaskTWithPrivatesPtrQTy,
4608 QualType KmpTaskTWithPrivatesQTy) {
4609 ASTContext &C = CGM.getContext();
4610 FunctionArgList Args;
4611 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4612 ImplicitParamDecl::Other);
4613 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4614 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4615 ImplicitParamDecl::Other);
4616 Args.push_back(&GtidArg);
4617 Args.push_back(&TaskTypeArg);
4618 const auto &DestructorFnInfo =
4619 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
4620 llvm::FunctionType *DestructorFnTy =
4621 CGM.getTypes().GetFunctionType(DestructorFnInfo);
4622 std::string Name =
4623 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
4624 auto *DestructorFn =
4625 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
4626 Name, &CGM.getModule());
4627 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
4628 DestructorFnInfo);
4629 DestructorFn->setDoesNotRecurse();
4630 CodeGenFunction CGF(CGM);
4631 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
4632 Args, Loc, Loc);
4633
4634 LValue Base = CGF.EmitLoadOfPointerLValue(
4635 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4636 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4637 const auto *KmpTaskTWithPrivatesQTyRD =
4638 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4639 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4640 Base = CGF.EmitLValueForField(Base, *FI);
4641 for (const auto *Field :
4642 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
4643 if (QualType::DestructionKind DtorKind =
4644 Field->getType().isDestructedType()) {
4645 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
4646 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType());
4647 }
4648 }
4649 CGF.FinishFunction();
4650 return DestructorFn;
4651}
4652
4653/// Emit a privates mapping function for correct handling of private and
4654/// firstprivate variables.
4655/// \code
4656/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4657/// **noalias priv1,..., <tyn> **noalias privn) {
4658/// *priv1 = &.privates.priv1;
4659/// ...;
4660/// *privn = &.privates.privn;
4661/// }
4662/// \endcode
4663static llvm::Value *
4664emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
4665 ArrayRef<const Expr *> PrivateVars,
4666 ArrayRef<const Expr *> FirstprivateVars,
4667 ArrayRef<const Expr *> LastprivateVars,
4668 QualType PrivatesQTy,
4669 ArrayRef<PrivateDataTy> Privates) {
4670 ASTContext &C = CGM.getContext();
4671 FunctionArgList Args;
4672 ImplicitParamDecl TaskPrivatesArg(
4673 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4674 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4675 ImplicitParamDecl::Other);
4676 Args.push_back(&TaskPrivatesArg);
4677 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4678 unsigned Counter = 1;
4679 for (const Expr *E : PrivateVars) {
4680 Args.push_back(ImplicitParamDecl::Create(
4681 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4682 C.getPointerType(C.getPointerType(E->getType()))
4683 .withConst()
4684 .withRestrict(),
4685 ImplicitParamDecl::Other));
4686 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4687 PrivateVarsPos[VD] = Counter;
4688 ++Counter;
4689 }
4690 for (const Expr *E : FirstprivateVars) {
4691 Args.push_back(ImplicitParamDecl::Create(
4692 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4693 C.getPointerType(C.getPointerType(E->getType()))
4694 .withConst()
4695 .withRestrict(),
4696 ImplicitParamDecl::Other));
4697 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4698 PrivateVarsPos[VD] = Counter;
4699 ++Counter;
4700 }
4701 for (const Expr *E : LastprivateVars) {
4702 Args.push_back(ImplicitParamDecl::Create(
4703 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4704 C.getPointerType(C.getPointerType(E->getType()))
4705 .withConst()
4706 .withRestrict(),
4707 ImplicitParamDecl::Other));
4708 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4709 PrivateVarsPos[VD] = Counter;
4710 ++Counter;
4711 }
4712 const auto &TaskPrivatesMapFnInfo =
4713 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
4714 llvm::FunctionType *TaskPrivatesMapTy =
4715 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
4716 std::string Name =
4717 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
4718 auto *TaskPrivatesMap = llvm::Function::Create(
4719 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4720 &CGM.getModule());
4721 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
4722 TaskPrivatesMapFnInfo);
4723 if (CGM.getLangOpts().Optimize) {
4724 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4725 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4726 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4727 }
4728 CodeGenFunction CGF(CGM);
4729 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
4730 TaskPrivatesMapFnInfo, Args, Loc, Loc);
4731
4732 // *privi = &.privates.privi;
4733 LValue Base = CGF.EmitLoadOfPointerLValue(
4734 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4735 TaskPrivatesArg.getType()->castAs<PointerType>());
4736 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
4737 Counter = 0;
4738 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4739 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4740 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4741 LValue RefLVal =
4742 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4743 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
4744 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>());
4745 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal);
4746 ++Counter;
4747 }
4748 CGF.FinishFunction();
4749 return TaskPrivatesMap;
4750}
4751
4752/// Emit initialization for private variables in task-based directives.
4753static void emitPrivatesInit(CodeGenFunction &CGF,
4754 const OMPExecutableDirective &D,
4755 Address KmpTaskSharedsPtr, LValue TDBase,
4756 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4757 QualType SharedsTy, QualType SharedsPtrTy,
4758 const OMPTaskDataTy &Data,
4759 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
4760 ASTContext &C = CGF.getContext();
4761 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4762 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
4763 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4764 ? OMPD_taskloop
4765 : OMPD_task;
4766 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4767 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
4768 LValue SrcBase;
4769 bool IsTargetTask =
4770 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4771 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4772 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4773 // PointersArray and SizesArray. The original variables for these arrays are
4774 // not captured and we get their addresses explicitly.
4775 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
4776 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
4777 SrcBase = CGF.MakeAddrLValue(
4778 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4779 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4780 SharedsTy);
4781 }
4782 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
4783 for (const PrivateDataTy &Pair : Privates) {
4784 const VarDecl *VD = Pair.second.PrivateCopy;
4785 const Expr *Init = VD->getAnyInitializer();
4786 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4787 !CGF.isTrivialInitializer(Init)))) {
4788 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
4789 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4790 const VarDecl *OriginalVD = Pair.second.Original;
4791 // Check if the variable is the target-based BasePointersArray,
4792 // PointersArray or SizesArray.
4793 LValue SharedRefLValue;
4794 QualType Type = PrivateLValue.getType();
4795 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
4796 if (IsTargetTask && !SharedField) {
4797 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4804, __PRETTY_FUNCTION__))
4798 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4804, __PRETTY_FUNCTION__))
4799 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4804, __PRETTY_FUNCTION__))
4800 ->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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4804, __PRETTY_FUNCTION__))
4801 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4804, __PRETTY_FUNCTION__))
4802 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4804, __PRETTY_FUNCTION__))
4803 ->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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4804, __PRETTY_FUNCTION__))
4804 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4804, __PRETTY_FUNCTION__))
;
4805 SharedRefLValue =
4806 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4807 } else {
4808 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4809 SharedRefLValue = CGF.MakeAddrLValue(
4810 Address(SharedRefLValue.getPointer(CGF),
4811 C.getDeclAlign(OriginalVD)),
4812 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4813 SharedRefLValue.getTBAAInfo());
4814 }
4815 if (Type->isArrayType()) {
4816 // Initialize firstprivate array.
4817 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4818 // Perform simple memcpy.
4819 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
4820 } else {
4821 // Initialize firstprivate array using element-by-element
4822 // initialization.
4823 CGF.EmitOMPAggregateAssign(
4824 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF),
4825 Type,
4826 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4827 Address SrcElement) {
4828 // Clean up any temporaries needed by the initialization.
4829 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4830 InitScope.addPrivate(
4831 Elem, [SrcElement]() -> Address { return SrcElement; });
4832 (void)InitScope.Privatize();
4833 // Emit initialization for single element.
4834 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4835 CGF, &CapturesInfo);
4836 CGF.EmitAnyExprToMem(Init, DestElement,
4837 Init->getType().getQualifiers(),
4838 /*IsInitializer=*/false);
4839 });
4840 }
4841 } else {
4842 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4843 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address {
4844 return SharedRefLValue.getAddress(CGF);
4845 });
4846 (void)InitScope.Privatize();
4847 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4848 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4849 /*capturedByInit=*/false);
4850 }
4851 } else {
4852 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
4853 }
4854 }
4855 ++FI;
4856 }
4857}
4858
4859/// Check if duplication function is required for taskloops.
4860static bool checkInitIsRequired(CodeGenFunction &CGF,
4861 ArrayRef<PrivateDataTy> Privates) {
4862 bool InitRequired = false;
4863 for (const PrivateDataTy &Pair : Privates) {
4864 const VarDecl *VD = Pair.second.PrivateCopy;
4865 const Expr *Init = VD->getAnyInitializer();
4866 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4867 !CGF.isTrivialInitializer(Init));
4868 if (InitRequired)
4869 break;
4870 }
4871 return InitRequired;
4872}
4873
4874
4875/// Emit task_dup function (for initialization of
4876/// private/firstprivate/lastprivate vars and last_iter flag)
4877/// \code
4878/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4879/// lastpriv) {
4880/// // setup lastprivate flag
4881/// task_dst->last = lastpriv;
4882/// // could be constructor calls here...
4883/// }
4884/// \endcode
4885static llvm::Value *
4886emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4887 const OMPExecutableDirective &D,
4888 QualType KmpTaskTWithPrivatesPtrQTy,
4889 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4890 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4891 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4892 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
4893 ASTContext &C = CGM.getContext();
4894 FunctionArgList Args;
4895 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4896 KmpTaskTWithPrivatesPtrQTy,
4897 ImplicitParamDecl::Other);
4898 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4899 KmpTaskTWithPrivatesPtrQTy,
4900 ImplicitParamDecl::Other);
4901 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4902 ImplicitParamDecl::Other);
4903 Args.push_back(&DstArg);
4904 Args.push_back(&SrcArg);
4905 Args.push_back(&LastprivArg);
4906 const auto &TaskDupFnInfo =
4907 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
4908 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
4909 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4910 auto *TaskDup = llvm::Function::Create(
4911 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
4912 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
4913 TaskDup->setDoesNotRecurse();
4914 CodeGenFunction CGF(CGM);
4915 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4916 Loc);
4917
4918 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4919 CGF.GetAddrOfLocalVar(&DstArg),
4920 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4921 // task_dst->liter = lastpriv;
4922 if (WithLastIter) {
4923 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4924 LValue Base = CGF.EmitLValueForField(
4925 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4926 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4927 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4928 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4929 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4930 }
4931
4932 // Emit initial values for private copies (if any).
4933 assert(!Privates.empty())((!Privates.empty()) ? static_cast<void> (0) : __assert_fail
("!Privates.empty()", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4933, __PRETTY_FUNCTION__))
;
4934 Address KmpTaskSharedsPtr = Address::invalid();
4935 if (!Data.FirstprivateVars.empty()) {
4936 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4937 CGF.GetAddrOfLocalVar(&SrcArg),
4938 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4939 LValue Base = CGF.EmitLValueForField(
4940 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4941 KmpTaskSharedsPtr = Address(
4942 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4943 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4944 KmpTaskTShareds)),
4945 Loc),
4946 CGF.getNaturalTypeAlignment(SharedsTy));
4947 }
4948 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4949 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
4950 CGF.FinishFunction();
4951 return TaskDup;
4952}
4953
4954/// Checks if destructor function is required to be generated.
4955/// \return true if cleanups are required, false otherwise.
4956static bool
4957checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
4958 bool NeedsCleanup = false;
4959 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4960 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
4961 for (const FieldDecl *FD : PrivateRD->fields()) {
4962 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
4963 if (NeedsCleanup)
4964 break;
4965 }
4966 return NeedsCleanup;
4967}
4968
4969CGOpenMPRuntime::TaskResultTy
4970CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4971 const OMPExecutableDirective &D,
4972 llvm::Function *TaskFunction, QualType SharedsTy,
4973 Address Shareds, const OMPTaskDataTy &Data) {
4974 ASTContext &C = CGM.getContext();
4975 llvm::SmallVector<PrivateDataTy, 4> Privates;
4976 // Aggregate privates and sort them by the alignment.
4977 auto I = Data.PrivateCopies.begin();
4978 for (const Expr *E : Data.PrivateVars) {
4979 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4980 Privates.emplace_back(
4981 C.getDeclAlign(VD),
4982 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
4983 /*PrivateElemInit=*/nullptr));
4984 ++I;
4985 }
4986 I = Data.FirstprivateCopies.begin();
4987 auto IElemInitRef = Data.FirstprivateInits.begin();
4988 for (const Expr *E : Data.FirstprivateVars) {
4989 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4990 Privates.emplace_back(
4991 C.getDeclAlign(VD),
4992 PrivateHelpersTy(
4993 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
4994 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
4995 ++I;
4996 ++IElemInitRef;
4997 }
4998 I = Data.LastprivateCopies.begin();
4999 for (const Expr *E : Data.LastprivateVars) {
5000 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5001 Privates.emplace_back(
5002 C.getDeclAlign(VD),
5003 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
5004 /*PrivateElemInit=*/nullptr));
5005 ++I;
5006 }
5007 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
5008 return L.first > R.first;
5009 });
5010 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
5011 // Build type kmp_routine_entry_t (if not built yet).
5012 emitKmpRoutineEntryT(KmpInt32Ty);
5013 // Build type kmp_task_t (if not built yet).
5014 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5015 if (SavedKmpTaskloopTQTy.isNull()) {
5016 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5017 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5018 }
5019 KmpTaskTQTy = SavedKmpTaskloopTQTy;
5020 } else {
5021 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 5024, __PRETTY_FUNCTION__))
5022 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 5024, __PRETTY_FUNCTION__))
5023 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 5024, __PRETTY_FUNCTION__))
5024 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 5024, __PRETTY_FUNCTION__))
;
5025 if (SavedKmpTaskTQTy.isNull()) {
5026 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5027 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5028 }
5029 KmpTaskTQTy = SavedKmpTaskTQTy;
5030 }
5031 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
5032 // Build particular struct kmp_task_t for the given task.
5033 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
5034 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
5035 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
5036 QualType KmpTaskTWithPrivatesPtrQTy =
5037 C.getPointerType(KmpTaskTWithPrivatesQTy);
5038 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5039 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5040 KmpTaskTWithPrivatesTy->getPointerTo();
5041 llvm::Value *KmpTaskTWithPrivatesTySize =
5042 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
5043 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5044
5045 // Emit initial values for private copies (if any).
5046 llvm::Value *TaskPrivatesMap = nullptr;
5047 llvm::Type *TaskPrivatesMapTy =
5048 std::next(TaskFunction->arg_begin(), 3)->getType();
5049 if (!Privates.empty()) {
5050 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
5051 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5052 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5053 FI->getType(), Privates);
5054 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5055 TaskPrivatesMap, TaskPrivatesMapTy);
5056 } else {
5057 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5058 cast<llvm::PointerType>(TaskPrivatesMapTy));
5059 }
5060 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5061 // kmp_task_t *tt);
5062 llvm::Function *TaskEntry = emitProxyTaskFunction(
5063 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5064 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5065 TaskPrivatesMap);
5066
5067 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5068 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5069 // kmp_routine_entry_t *task_entry);
5070 // Task flags. Format is taken from
5071 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
5072 // description of kmp_tasking_flags struct.
5073 enum {
5074 TiedFlag = 0x1,
5075 FinalFlag = 0x2,
5076 DestructorsFlag = 0x8,
5077 PriorityFlag = 0x20
5078 };
5079 unsigned Flags = Data.Tied ? TiedFlag : 0;
5080 bool NeedsCleanup = false;
5081 if (!Privates.empty()) {
5082 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5083 if (NeedsCleanup)
5084 Flags = Flags | DestructorsFlag;
5085 }
5086 if (Data.Priority.getInt())
5087 Flags = Flags | PriorityFlag;
5088 llvm::Value *TaskFlags =
5089 Data.Final.getPointer()
5090 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
5091 CGF.Builder.getInt32(FinalFlag),
5092 CGF.Builder.getInt32(/*C=*/0))
5093 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
5094 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
5095 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
5096 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5097 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5098 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5099 TaskEntry, KmpRoutineEntryPtrTy)};
5100 llvm::Value *NewTask;
5101 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5102 // Check if we have any device clause associated with the directive.
5103 const Expr *Device = nullptr;
5104 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5105 Device = C->getDevice();
5106 // Emit device ID if any otherwise use default value.
5107 llvm::Value *DeviceID;
5108 if (Device)
5109 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5110 CGF.Int64Ty, /*isSigned=*/true);
5111 else
5112 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5113 AllocArgs.push_back(DeviceID);
5114 NewTask = CGF.EmitRuntimeCall(
5115 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5116 } else {
5117 NewTask = CGF.EmitRuntimeCall(
5118 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
5119 }
5120 llvm::Value *NewTaskNewTaskTTy =
5121 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5122 NewTask, KmpTaskTWithPrivatesPtrTy);
5123 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5124 KmpTaskTWithPrivatesQTy);
5125 LValue TDBase =
5126 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
5127 // Fill the data in the resulting kmp_task_t record.
5128 // Copy shareds if there are any.
5129 Address KmpTaskSharedsPtr = Address::invalid();
5130 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
5131 KmpTaskSharedsPtr =
5132 Address(CGF.EmitLoadOfScalar(
5133 CGF.EmitLValueForField(
5134 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5135 KmpTaskTShareds)),
5136 Loc),
5137 CGF.getNaturalTypeAlignment(SharedsTy));
5138 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5139 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
5140 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
5141 }
5142 // Emit initial values for private copies (if any).
5143 TaskResultTy Result;
5144 if (!Privates.empty()) {
5145 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5146 SharedsTy, SharedsPtrTy, Data, Privates,
5147 /*ForDup=*/false);
5148 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5149 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5150 Result.TaskDupFn = emitTaskDupFunction(
5151 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5152 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5153 /*WithLastIter=*/!Data.LastprivateVars.empty());
5154 }
5155 }
5156 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5157 enum { Priority = 0, Destructors = 1 };
5158 // Provide pointer to function with destructors for privates.
5159 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
5160 const RecordDecl *KmpCmplrdataUD =
5161 (*FI)->getType()->getAsUnionType()->getDecl();
5162 if (NeedsCleanup) {
5163 llvm::Value *DestructorFn = emitDestructorsFunction(
5164 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5165 KmpTaskTWithPrivatesQTy);
5166 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5167 LValue DestructorsLV = CGF.EmitLValueForField(
5168 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5169 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5170 DestructorFn, KmpRoutineEntryPtrTy),
5171 DestructorsLV);
5172 }
5173 // Set priority.
5174 if (Data.Priority.getInt()) {
5175 LValue Data2LV = CGF.EmitLValueForField(
5176 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5177 LValue PriorityLV = CGF.EmitLValueForField(
5178 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5179 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5180 }
5181 Result.NewTask = NewTask;
5182 Result.TaskEntry = TaskEntry;
5183 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5184 Result.TDBase = TDBase;
5185 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5186 return Result;
5187}
5188
5189namespace {
5190/// Dependence kind for RTL.
5191enum RTLDependenceKindTy {
5192 DepIn = 0x01,
5193 DepInOut = 0x3,
5194 DepMutexInOutSet = 0x4
5195};
5196/// Fields ids in kmp_depend_info record.
5197enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5198} // namespace
5199
5200/// Translates internal dependency kind into the runtime kind.
5201static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) {
5202 RTLDependenceKindTy DepKind;
5203 switch (K) {
5204 case OMPC_DEPEND_in:
5205 DepKind = DepIn;
5206 break;
5207 // Out and InOut dependencies must use the same code.
5208 case OMPC_DEPEND_out:
5209 case OMPC_DEPEND_inout:
5210 DepKind = DepInOut;
5211 break;
5212 case OMPC_DEPEND_mutexinoutset:
5213 DepKind = DepMutexInOutSet;
5214 break;
5215 case OMPC_DEPEND_source:
5216 case OMPC_DEPEND_sink:
5217 case OMPC_DEPEND_depobj:
5218 case OMPC_DEPEND_unknown:
5219 llvm_unreachable("Unknown task dependence type")::llvm::llvm_unreachable_internal("Unknown task dependence type"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 5219)
;
5220 }
5221 return DepKind;
5222}
5223
5224/// Builds kmp_depend_info, if it is not built yet, and builds flags type.
5225static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy,
5226 QualType &FlagsTy) {
5227 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
5228 if (KmpDependInfoTy.isNull()) {
5229 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5230 KmpDependInfoRD->startDefinition();
5231 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5232 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5233 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5234 KmpDependInfoRD->completeDefinition();
5235 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
5236 }
5237}
5238
5239Address CGOpenMPRuntime::emitDependClause(
5240 CodeGenFunction &CGF,
5241 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependencies,
5242 bool ForDepobj, SourceLocation Loc) {
5243 // Process list of dependencies.
5244 ASTContext &C = CGM.getContext();
5245 Address DependenciesArray = Address::invalid();
5246 unsigned NumDependencies = Dependencies.size();
5247 if (NumDependencies) {
5248 QualType FlagsTy;
5249 getDependTypes(C, KmpDependInfoTy, FlagsTy);
5250 RecordDecl *KmpDependInfoRD =
5251 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
5252 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5253 // Define type kmp_depend_info[<Dependencies.size()>];
5254 // For depobj reserve one extra element to store the number of elements.
5255 // It is required to handle depobj(x) update(in) construct.
5256 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
5257 KmpDependInfoTy,
5258 llvm::APInt(/*numBits=*/64, NumDependencies + (ForDepobj ? 1 : 0)),
5259 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
5260 // kmp_depend_info[<Dependencies.size()>] deps;
5261 if (ForDepobj) {
5262 // Need to allocate on the dynamic memory.
5263 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5264 // Use default allocator.
5265 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5266 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoArrayTy);
5267 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy);
5268 llvm::Value *Size = CGF.CGM.getSize(Sz.alignTo(Align));
5269 llvm::Value *Args[] = {ThreadID, Size, Allocator};
5270
5271 llvm::Value *Addr = CGF.EmitRuntimeCall(
5272 createRuntimeFunction(OMPRTL__kmpc_alloc), Args, ".dep.arr.addr");
5273 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5274 Addr, CGF.ConvertTypeForMem(KmpDependInfoArrayTy)->getPointerTo());
5275 DependenciesArray = Address(Addr, Align);
5276 } else {
5277 DependenciesArray =
5278 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
5279 }
5280 if (ForDepobj) {
5281 // Write number of elements in the first element of array for depobj.
5282 llvm::Value *NumVal =
5283 llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies);
5284 LValue Base = CGF.MakeAddrLValue(
5285 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0),
5286 KmpDependInfoTy);
5287 // deps[i].base_addr = NumDependencies;
5288 LValue BaseAddrLVal = CGF.EmitLValueForField(
5289 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
5290 CGF.EmitStoreOfScalar(NumVal, BaseAddrLVal);
5291 }
5292 for (unsigned I = 0; I < NumDependencies; ++I) {
5293 const Expr *E = Dependencies[I].second;
5294 LValue Addr = CGF.EmitLValue(E);
5295 llvm::Value *Size;
5296 QualType Ty = E->getType();
5297 if (const auto *ASE =
5298 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
5299 LValue UpAddrLVal =
5300 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
5301 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32(
5302 UpAddrLVal.getPointer(CGF), /*Idx0=*/1);
5303 llvm::Value *LowIntPtr =
5304 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy);
5305 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5306 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
5307 } else {
5308 Size = CGF.getTypeSize(Ty);
5309 }
5310 LValue Base =
5311 CGF.MakeAddrLValue(CGF.Builder.CreateConstArrayGEP(
5312 DependenciesArray, I + (ForDepobj ? 1 : 0)),
5313 KmpDependInfoTy);
5314 // deps[i].base_addr = &<Dependencies[i].second>;
5315 LValue BaseAddrLVal = CGF.EmitLValueForField(
5316 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
5317 CGF.EmitStoreOfScalar(
5318 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy),
5319 BaseAddrLVal);
5320 // deps[i].len = sizeof(<Dependencies[i].second>);
5321 LValue LenLVal = CGF.EmitLValueForField(
5322 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5323 CGF.EmitStoreOfScalar(Size, LenLVal);
5324 // deps[i].flags = <Dependencies[i].first>;
5325 RTLDependenceKindTy DepKind =
5326 translateDependencyKind(Dependencies[I].first);
5327 LValue FlagsLVal = CGF.EmitLValueForField(
5328 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5329 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5330 FlagsLVal);
5331 }
5332 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5333 CGF.Builder.CreateConstArrayGEP(DependenciesArray, ForDepobj ? 1 : 0),
5334 CGF.VoidPtrTy);
5335 }
5336 return DependenciesArray;
5337}
5338
5339void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal,
5340 SourceLocation Loc) {
5341 ASTContext &C = CGM.getContext();
5342 QualType FlagsTy;
5343 getDependTypes(C, KmpDependInfoTy, FlagsTy);
5344 LValue Base = CGF.EmitLoadOfPointerLValue(
5345 DepobjLVal.getAddress(CGF),
5346 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5347 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
5348 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5349 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy));
5350 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
5351 Addr.getPointer(),
5352 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
5353 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr,
5354 CGF.VoidPtrTy);
5355 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5356 // Use default allocator.
5357 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5358 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
5359
5360 // _kmpc_free(gtid, addr, nullptr);
5361 (void)CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_free), Args);
5362}
5363
5364void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal,
5365 OpenMPDependClauseKind NewDepKind,
5366 SourceLocation Loc) {
5367 ASTContext &C = CGM.getContext();
5368 QualType FlagsTy;
5369 getDependTypes(C, KmpDependInfoTy, FlagsTy);
5370 RecordDecl *KmpDependInfoRD =
5371 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
5372 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5373 LValue Base = CGF.EmitLoadOfPointerLValue(
5374 DepobjLVal.getAddress(CGF),
5375 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5376 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
5377 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5378 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy));
5379 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
5380 Base.getTBAAInfo());
5381 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
5382 Addr.getPointer(),
5383 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
5384 LValue NumDepsBase = CGF.MakeAddrLValue(
5385 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
5386 Base.getBaseInfo(), Base.getTBAAInfo());
5387 // NumDeps = deps[i].base_addr;
5388 LValue BaseAddrLVal = CGF.EmitLValueForField(
5389 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
5390 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc);
5391
5392 Address Begin = Base.getAddress(CGF);
5393 // Cast from pointer to array type to pointer to single element.
5394 llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps);
5395 // The basic structure here is a while-do loop.
5396 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body");
5397 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done");
5398 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
5399 CGF.EmitBlock(BodyBB);
5400 llvm::PHINode *ElementPHI =
5401 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast");
5402 ElementPHI->addIncoming(Begin.getPointer(), EntryBB);
5403 Begin = Address(ElementPHI, Begin.getAlignment());
5404 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(),
5405 Base.getTBAAInfo());
5406 // deps[i].flags = NewDepKind;
5407 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind);
5408 LValue FlagsLVal = CGF.EmitLValueForField(
5409 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5410 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5411 FlagsLVal);
5412
5413 // Shift the address forward by one element.
5414 Address ElementNext =
5415 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext");
5416 ElementPHI->addIncoming(ElementNext.getPointer(),
5417 CGF.Builder.GetInsertBlock());
5418 llvm::Value *IsEmpty =
5419 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty");
5420 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5421 // Done.
5422 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5423}
5424
5425void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5426 const OMPExecutableDirective &D,
5427 llvm::Function *TaskFunction,
5428 QualType SharedsTy, Address Shareds,
5429 const Expr *IfCond,
5430 const OMPTaskDataTy &Data) {
5431 if (!CGF.HaveInsertPoint())
5432 return;
5433
5434 TaskResultTy Result =
5435 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5436 llvm::Value *NewTask = Result.NewTask;
5437 llvm::Function *TaskEntry = Result.TaskEntry;
5438 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5439 LValue TDBase = Result.TDBase;
5440 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5441 // Process list of dependences.
5442 Address DependenciesArray =
5443 emitDependClause(CGF, Data.Dependences, /*ForDepobj=*/false, Loc);
5444 unsigned NumDependencies = Data.Dependences.size();
5445
5446 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
5447 // libcall.
5448 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5449 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5450 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5451 // list is not empty
5452 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5453 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5454 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5455 llvm::Value *DepTaskArgs[7];
5456 if (NumDependencies) {
5457 DepTaskArgs[0] = UpLoc;
5458 DepTaskArgs[1] = ThreadID;
5459 DepTaskArgs[2] = NewTask;
5460 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5461 DepTaskArgs[4] = DependenciesArray.getPointer();
5462 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5463 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5464 }
5465 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5466 &TaskArgs,
5467 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
5468 if (!Data.Tied) {
5469 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
5470 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
5471 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5472 }
5473 if (NumDependencies) {
5474 CGF.EmitRuntimeCall(
5475 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
5476 } else {
5477 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
5478 TaskArgs);
5479 }
5480 // Check if parent region is untied and build return for untied task;
5481 if (auto *Region =
5482 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5483 Region->emitUntiedSwitch(CGF);
5484 };
5485
5486 llvm::Value *DepWaitTaskArgs[6];
5487 if (NumDependencies) {
5488 DepWaitTaskArgs[0] = UpLoc;
5489 DepWaitTaskArgs[1] = ThreadID;
5490 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5491 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5492 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5493 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5494 }
5495 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
5496 NumDependencies, &DepWaitTaskArgs,
5497 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
5498 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
5499 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5500 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5501 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5502 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5503 // is specified.
5504 if (NumDependencies)
5505 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
5506 DepWaitTaskArgs);
5507 // Call proxy_task_entry(gtid, new_task);
5508 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5509 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
5510 Action.Enter(CGF);
5511 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
5512 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
5513 OutlinedFnArgs);
5514 };
5515
5516 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5517 // kmp_task_t *new_task);
5518 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5519 // kmp_task_t *new_task);
5520 RegionCodeGenTy RCG(CodeGen);
5521 CommonActionTy Action(
5522 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5523 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5524 RCG.setAction(Action);
5525 RCG(CGF);
5526 };
5527
5528 if (IfCond) {
5529 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
5530 } else {
5531 RegionCodeGenTy ThenRCG(ThenCodeGen);
5532 ThenRCG(CGF);
5533 }
5534}
5535
5536void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5537 const OMPLoopDirective &D,
5538 llvm::Function *TaskFunction,
5539 QualType SharedsTy, Address Shareds,
5540 const Expr *IfCond,
5541 const OMPTaskDataTy &Data) {
5542 if (!CGF.HaveInsertPoint())
5543 return;
5544 TaskResultTy Result =
5545 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5546 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
5547 // libcall.
5548 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5549 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5550 // sched, kmp_uint64 grainsize, void *task_dup);
5551 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5552 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5553 llvm::Value *IfVal;
5554 if (IfCond) {
5555 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5556 /*isSigned=*/true);
5557 } else {
5558 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
5559 }
5560
5561 LValue LBLVal = CGF.EmitLValueForField(
5562 Result.TDBase,
5563 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
5564 const auto *LBVar =
5565 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5566 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF),
5567 LBLVal.getQuals(),
5568 /*IsInitializer=*/true);
5569 LValue UBLVal = CGF.EmitLValueForField(
5570 Result.TDBase,
5571 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
5572 const auto *UBVar =
5573 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5574 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF),
5575 UBLVal.getQuals(),
5576 /*IsInitializer=*/true);
5577 LValue StLVal = CGF.EmitLValueForField(
5578 Result.TDBase,
5579 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
5580 const auto *StVar =
5581 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5582 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF),
5583 StLVal.getQuals(),
5584 /*IsInitializer=*/true);
5585 // Store reductions address.
5586 LValue RedLVal = CGF.EmitLValueForField(
5587 Result.TDBase,
5588 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
5589 if (Data.Reductions) {
5590 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
5591 } else {
5592 CGF.EmitNullInitialization(RedLVal.getAddress(CGF),
5593 CGF.getContext().VoidPtrTy);
5594 }
5595 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
5596 llvm::Value *TaskArgs[] = {
5597 UpLoc,
5598 ThreadID,
5599 Result.NewTask,
5600 IfVal,
5601 LBLVal.getPointer(CGF),
5602 UBLVal.getPointer(CGF),
5603 CGF.EmitLoadOfScalar(StLVal, Loc),
5604 llvm::ConstantInt::getSigned(
5605 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
5606 llvm::ConstantInt::getSigned(
5607 CGF.IntTy, Data.Schedule.getPointer()
5608 ? Data.Schedule.getInt() ? NumTasks : Grainsize
5609 : NoSchedule),
5610 Data.Schedule.getPointer()
5611 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
5612 /*isSigned=*/false)
5613 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
5614 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5615 Result.TaskDupFn, CGF.VoidPtrTy)
5616 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
5617 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5618}
5619
5620/// Emit reduction operation for each element of array (required for
5621/// array sections) LHS op = RHS.
5622/// \param Type Type of array.
5623/// \param LHSVar Variable on the left side of the reduction operation
5624/// (references element of array in original variable).
5625/// \param RHSVar Variable on the right side of the reduction operation
5626/// (references element of array in original variable).
5627/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5628/// RHSVar.
5629static void EmitOMPAggregateReduction(
5630 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5631 const VarDecl *RHSVar,
5632 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5633 const Expr *, const Expr *)> &RedOpGen,
5634 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5635 const Expr *UpExpr = nullptr) {
5636 // Perform element-by-element initialization.
5637 QualType ElementTy;
5638 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5639 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5640
5641 // Drill down to the base element type on both arrays.
5642 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5643 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
5644
5645 llvm::Value *RHSBegin = RHSAddr.getPointer();
5646 llvm::Value *LHSBegin = LHSAddr.getPointer();
5647 // Cast from pointer to array type to pointer to single element.
5648 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
5649 // The basic structure here is a while-do loop.
5650 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5651 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5652 llvm::Value *IsEmpty =
5653 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5654 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5655
5656 // Enter the loop body, making that address the current address.
5657 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
5658 CGF.EmitBlock(BodyBB);
5659
5660 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5661
5662 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5663 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5664 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5665 Address RHSElementCurrent =
5666 Address(RHSElementPHI,
5667 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5668
5669 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5670 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5671 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5672 Address LHSElementCurrent =
5673 Address(LHSElementPHI,
5674 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5675
5676 // Emit copy.
5677 CodeGenFunction::OMPPrivateScope Scope(CGF);
5678 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5679 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
5680 Scope.Privatize();
5681 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5682 Scope.ForceCleanup();
5683
5684 // Shift the address forward by one element.
5685 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
5686 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
5687 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
5688 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5689 // Check whether we've reached the end.
5690 llvm::Value *Done =
5691 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5692 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5693 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5694 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5695
5696 // Done.
5697 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5698}
5699
5700/// Emit reduction combiner. If the combiner is a simple expression emit it as
5701/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5702/// UDR combiner function.
5703static void emitReductionCombiner(CodeGenFunction &CGF,
5704 const Expr *ReductionOp) {
5705 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5706 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5707 if (const auto *DRE =
5708 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
5709 if (const auto *DRD =
5710 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
5711 std::pair<llvm::Function *, llvm::Function *> Reduction =
5712 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5713 RValue Func = RValue::get(Reduction.first);
5714 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5715 CGF.EmitIgnoredExpr(ReductionOp);
5716 return;
5717 }
5718 CGF.EmitIgnoredExpr(ReductionOp);
5719}
5720
5721llvm::Function *CGOpenMPRuntime::emitReductionFunction(
5722 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5723 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5724 ArrayRef<const Expr *> ReductionOps) {
5725 ASTContext &C = CGM.getContext();
5726
5727 // void reduction_func(void *LHSArg, void *RHSArg);
5728 FunctionArgList Args;
5729 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5730 ImplicitParamDecl::Other);
5731 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5732 ImplicitParamDecl::Other);
5733 Args.push_back(&LHSArg);
5734 Args.push_back(&RHSArg);
5735 const auto &CGFI =
5736 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5737 std::string Name = getName({"omp", "reduction", "reduction_func"});
5738 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5739 llvm::GlobalValue::InternalLinkage, Name,
5740 &CGM.getModule());
5741 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
5742 Fn->setDoesNotRecurse();
5743 CodeGenFunction CGF(CGM);
5744 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
5745
5746 // Dst = (void*[n])(LHSArg);
5747 // Src = (void*[n])(RHSArg);
5748 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5749 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5750 ArgsType), CGF.getPointerAlign());
5751 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5752 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5753 ArgsType), CGF.getPointerAlign());
5754
5755 // ...
5756 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5757 // ...
5758 CodeGenFunction::OMPPrivateScope Scope(CGF);
5759 auto IPriv = Privates.begin();
5760 unsigned Idx = 0;
5761 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5762 const auto *RHSVar =
5763 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5764 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
5765 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
5766 });
5767 const auto *LHSVar =
5768 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5769 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
5770 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
5771 });
5772 QualType PrivTy = (*IPriv)->getType();
5773 if (PrivTy->isVariablyModifiedType()) {
5774 // Get array size and emit VLA type.
5775 ++Idx;
5776 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
5777 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
5778 const VariableArrayType *VLA =
5779 CGF.getContext().getAsVariableArrayType(PrivTy);
5780 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
5781 CodeGenFunction::OpaqueValueMapping OpaqueMap(
5782 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
5783 CGF.EmitVariablyModifiedType(PrivTy);
5784 }
5785 }
5786 Scope.Privatize();
5787 IPriv = Privates.begin();
5788 auto ILHS = LHSExprs.begin();
5789 auto IRHS = RHSExprs.begin();
5790 for (const Expr *E : ReductionOps) {
5791 if ((*IPriv)->getType()->isArrayType()) {
5792 // Emit reduction for array section.
5793 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5794 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5795 EmitOMPAggregateReduction(
5796 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5797 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5798 emitReductionCombiner(CGF, E);
5799 });
5800 } else {
5801 // Emit reduction for array subscript or single variable.
5802 emitReductionCombiner(CGF, E);
5803 }
5804 ++IPriv;
5805 ++ILHS;
5806 ++IRHS;
5807 }
5808 Scope.ForceCleanup();
5809 CGF.FinishFunction();
5810 return Fn;
5811}
5812
5813void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5814 const Expr *ReductionOp,
5815 const Expr *PrivateRef,
5816 const DeclRefExpr *LHS,
5817 const DeclRefExpr *RHS) {
5818 if (PrivateRef->getType()->isArrayType()) {
5819 // Emit reduction for array section.
5820 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5821 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
5822 EmitOMPAggregateReduction(
5823 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5824 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5825 emitReductionCombiner(CGF, ReductionOp);
5826 });
5827 } else {
5828 // Emit reduction for array subscript or single variable.
5829 emitReductionCombiner(CGF, ReductionOp);
5830 }
5831}
5832
5833void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
5834 ArrayRef<const Expr *> Privates,
5835 ArrayRef<const Expr *> LHSExprs,
5836 ArrayRef<const Expr *> RHSExprs,
5837 ArrayRef<const Expr *> ReductionOps,
5838 ReductionOptionsTy Options) {
5839 if (!CGF.HaveInsertPoint())
5840 return;
5841
5842 bool WithNowait = Options.WithNowait;
5843 bool SimpleReduction = Options.SimpleReduction;
5844
5845 // Next code should be emitted for reduction:
5846 //
5847 // static kmp_critical_name lock = { 0 };
5848 //
5849 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5850 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5851 // ...
5852 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5853 // *(Type<n>-1*)rhs[<n>-1]);
5854 // }
5855 //
5856 // ...
5857 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5858 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5859 // RedList, reduce_func, &<lock>)) {
5860 // case 1:
5861 // ...
5862 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5863 // ...
5864 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5865 // break;
5866 // case 2:
5867 // ...
5868 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5869 // ...
5870 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
5871 // break;
5872 // default:;
5873 // }
5874 //
5875 // if SimpleReduction is true, only the next code is generated:
5876 // ...
5877 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5878 // ...
5879
5880 ASTContext &C = CGM.getContext();
5881
5882 if (SimpleReduction) {
5883 CodeGenFunction::RunCleanupsScope Scope(CGF);
5884 auto IPriv = Privates.begin();
5885 auto ILHS = LHSExprs.begin();
5886 auto IRHS = RHSExprs.begin();
5887 for (const Expr *E : ReductionOps) {
5888 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5889 cast<DeclRefExpr>(*IRHS));
5890 ++IPriv;
5891 ++ILHS;
5892 ++IRHS;
5893 }
5894 return;
5895 }
5896
5897 // 1. Build a list of reduction variables.
5898 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
5899 auto Size = RHSExprs.size();
5900 for (const Expr *E : Privates) {
5901 if (E->getType()->isVariablyModifiedType())
5902 // Reserve place for array size.
5903 ++Size;
5904 }
5905 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
5906 QualType ReductionArrayTy =
5907 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
5908 /*IndexTypeQuals=*/0);
5909 Address ReductionList =
5910 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
5911 auto IPriv = Privates.begin();
5912 unsigned Idx = 0;
5913 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5914 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
5915 CGF.Builder.CreateStore(
5916 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5917 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy),
5918 Elem);
5919 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5920 // Store array size.
5921 ++Idx;
5922 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
5923 llvm::Value *Size = CGF.Builder.CreateIntCast(
5924 CGF.getVLASize(
5925 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
5926 .NumElts,
5927 CGF.SizeTy, /*isSigned=*/false);
5928 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5929 Elem);
5930 }
5931 }
5932
5933 // 2. Emit reduce_func().
5934 llvm::Function *ReductionFn = emitReductionFunction(
5935 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5936 LHSExprs, RHSExprs, ReductionOps);
5937
5938 // 3. Create static kmp_critical_name lock = { 0 };
5939 std::string Name = getName({"reduction"});
5940 llvm::Value *Lock = getCriticalRegionLock(Name);
5941
5942 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5943 // RedList, reduce_func, &<lock>);
5944 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5945 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5946 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5947 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5948 ReductionList.getPointer(), CGF.VoidPtrTy);
5949 llvm::Value *Args[] = {
5950 IdentTLoc, // ident_t *<loc>
5951 ThreadId, // i32 <gtid>
5952 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5953 ReductionArrayTySize, // size_type sizeof(RedList)
5954 RL, // void *RedList
5955 ReductionFn, // void (*) (void *, void *) <reduce_func>
5956 Lock // kmp_critical_name *&<lock>
5957 };
5958 llvm::Value *Res = CGF.EmitRuntimeCall(
5959 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5960 : OMPRTL__kmpc_reduce),
5961 Args);
5962
5963 // 5. Build switch(res)
5964 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5965 llvm::SwitchInst *SwInst =
5966 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
5967
5968 // 6. Build case 1:
5969 // ...
5970 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5971 // ...
5972 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5973 // break;
5974 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
5975 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5976 CGF.EmitBlock(Case1BB);
5977
5978 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5979 llvm::Value *EndArgs[] = {
5980 IdentTLoc, // ident_t *<loc>
5981 ThreadId, // i32 <gtid>
5982 Lock // kmp_critical_name *&<lock>
5983 };
5984 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5985 CodeGenFunction &CGF, PrePostActionTy &Action) {
5986 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
5987 auto IPriv = Privates.begin();
5988 auto ILHS = LHSExprs.begin();
5989 auto IRHS = RHSExprs.begin();
5990 for (const Expr *E : ReductionOps) {
5991 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5992 cast<DeclRefExpr>(*IRHS));
5993 ++IPriv;
5994 ++ILHS;
5995 ++IRHS;
5996 }
5997 };
5998 RegionCodeGenTy RCG(CodeGen);
5999 CommonActionTy Action(
6000 nullptr, llvm::None,
6001 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
6002 : OMPRTL__kmpc_end_reduce),
6003 EndArgs);
6004 RCG.setAction(Action);
6005 RCG(CGF);
6006
6007 CGF.EmitBranch(DefaultBB);
6008
6009 // 7. Build case 2:
6010 // ...
6011 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
6012 // ...
6013 // break;
6014 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
6015 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
6016 CGF.EmitBlock(Case2BB);
6017
6018 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
6019 CodeGenFunction &CGF, PrePostActionTy &Action) {
6020 auto ILHS = LHSExprs.begin();
6021 auto IRHS = RHSExprs.begin();
6022 auto IPriv = Privates.begin();
6023 for (const Expr *E : ReductionOps) {
6024 const Expr *XExpr = nullptr;
6025 const Expr *EExpr = nullptr;
6026 const Expr *UpExpr = nullptr;
6027 BinaryOperatorKind BO = BO_Comma;
6028 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
6029 if (BO->getOpcode() == BO_Assign) {
6030 XExpr = BO->getLHS();
6031 UpExpr = BO->getRHS();
6032 }
6033 }
6034 // Try to emit update expression as a simple atomic.
6035 const Expr *RHSExpr = UpExpr;
6036 if (RHSExpr) {
6037 // Analyze RHS part of the whole expression.
6038 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
6039 RHSExpr->IgnoreParenImpCasts())) {
6040 // If this is a conditional operator, analyze its condition for
6041 // min/max reduction operator.
6042 RHSExpr = ACO->getCond();
6043 }
6044 if (const auto *BORHS =
6045 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
6046 EExpr = BORHS->getRHS();
6047 BO = BORHS->getOpcode();
6048 }
6049 }
6050 if (XExpr) {
6051 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
6052 auto &&AtomicRedGen = [BO, VD,
6053 Loc](CodeGenFunction &CGF, const Expr *XExpr,
6054 const Expr *EExpr, const Expr *UpExpr) {
6055 LValue X = CGF.EmitLValue(XExpr);
6056 RValue E;
6057 if (EExpr)
6058 E = CGF.EmitAnyExpr(EExpr);
6059 CGF.EmitOMPAtomicSimpleUpdateExpr(
6060 X, E, BO, /*IsXLHSInRHSPart=*/true,
6061 llvm::AtomicOrdering::Monotonic, Loc,
6062 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
6063 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
6064 PrivateScope.addPrivate(
6065 VD, [&CGF, VD, XRValue, Loc]() {
6066 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
6067 CGF.emitOMPSimpleStore(
6068 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
6069 VD->getType().getNonReferenceType(), Loc);
6070 return LHSTemp;
6071 });
6072 (void)PrivateScope.Privatize();
6073 return CGF.EmitAnyExpr(UpExpr);
6074 });
6075 };
6076 if ((*IPriv)->getType()->isArrayType()) {
6077 // Emit atomic reduction for array section.
6078 const auto *RHSVar =
6079 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
6080 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
6081 AtomicRedGen, XExpr, EExpr, UpExpr);
6082 } else {
6083 // Emit atomic reduction for array subscript or single variable.
6084 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
6085 }
6086 } else {
6087 // Emit as a critical region.
6088 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
6089 const Expr *, const Expr *) {
6090 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
6091 std::string Name = RT.getName({"atomic_reduction"});
6092 RT.emitCriticalRegion(
6093 CGF, Name,
6094 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
6095 Action.Enter(CGF);
6096 emitReductionCombiner(CGF, E);
6097 },
6098 Loc);
6099 };
6100 if ((*IPriv)->getType()->isArrayType()) {
6101 const auto *LHSVar =
6102 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
6103 const auto *RHSVar =
6104 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
6105 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
6106 CritRedGen);
6107 } else {
6108 CritRedGen(CGF, nullptr, nullptr, nullptr);
6109 }
6110 }
6111 ++ILHS;
6112 ++IRHS;
6113 ++IPriv;
6114 }
6115 };
6116 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
6117 if (!WithNowait) {
6118 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
6119 llvm::Value *EndArgs[] = {
6120 IdentTLoc, // ident_t *<loc>
6121 ThreadId, // i32 <gtid>
6122 Lock // kmp_critical_name *&<lock>
6123 };
6124 CommonActionTy Action(nullptr, llvm::None,
6125 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
6126 EndArgs);
6127 AtomicRCG.setAction(Action);
6128 AtomicRCG(CGF);
6129 } else {
6130 AtomicRCG(CGF);
6131 }
6132
6133 CGF.EmitBranch(DefaultBB);
6134 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
6135}
6136
6137/// Generates unique name for artificial threadprivate variables.
6138/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
6139static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
6140 const Expr *Ref) {
6141 SmallString<256> Buffer;
6142 llvm::raw_svector_ostream Out(Buffer);
6143 const clang::DeclRefExpr *DE;
6144 const VarDecl *D = ::getBaseDecl(Ref, DE);
6145 if (!D)
6146 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
6147 D = D->getCanonicalDecl();
6148 std::string Name = CGM.getOpenMPRuntime().getName(
6149 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
6150 Out << Prefix << Name << "_"
6151 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
6152 return std::string(Out.str());
6153}
6154
6155/// Emits reduction initializer function:
6156/// \code
6157/// void @.red_init(void* %arg) {
6158/// %0 = bitcast void* %arg to <type>*
6159/// store <type> <init>, <type>* %0
6160/// ret void
6161/// }
6162/// \endcode
6163static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6164 SourceLocation Loc,
6165 ReductionCodeGen &RCG, unsigned N) {
6166 ASTContext &C = CGM.getContext();
6167 FunctionArgList Args;
6168 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6169 ImplicitParamDecl::Other);
6170 Args.emplace_back(&Param);
6171 const auto &FnInfo =
6172 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
6173 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
6174 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
6175 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
6176 Name, &CGM.getModule());
6177 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
6178 Fn->setDoesNotRecurse();
6179 CodeGenFunction CGF(CGM);
6180 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
6181 Address PrivateAddr = CGF.EmitLoadOfPointer(
6182 CGF.GetAddrOfLocalVar(&Param),
6183 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6184 llvm::Value *Size = nullptr;
6185 // If the size of the reduction item is non-constant, load it from global
6186 // threadprivate variable.
6187 if (RCG.getSizes(N).second) {
6188 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6189 CGF, CGM.getContext().getSizeType(),
6190 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
6191 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6192 CGM.getContext().getSizeType(), Loc);
6193 }
6194 RCG.emitAggregateType(CGF, N, Size);
6195 LValue SharedLVal;
6196 // If initializer uses initializer from declare reduction construct, emit a
6197 // pointer to the address of the original reduction item (reuired by reduction
6198 // initializer)
6199 if (RCG.usesReductionInitializer(N)) {
6200 Address SharedAddr =
6201 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6202 CGF, CGM.getContext().VoidPtrTy,
6203 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
6204 SharedAddr = CGF.EmitLoadOfPointer(
6205 SharedAddr,
6206 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
6207 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6208 } else {
6209 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6210 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6211 CGM.getContext().VoidPtrTy);
6212 }
6213 // Emit the initializer:
6214 // %0 = bitcast void* %arg to <type>*
6215 // store <type> <init>, <type>* %0
6216 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6217 [](CodeGenFunction &) { return false; });
6218 CGF.FinishFunction();
6219 return Fn;
6220}
6221
6222/// Emits reduction combiner function:
6223/// \code
6224/// void @.red_comb(void* %arg0, void* %arg1) {
6225/// %lhs = bitcast void* %arg0 to <type>*
6226/// %rhs = bitcast void* %arg1 to <type>*
6227/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6228/// store <type> %2, <type>* %lhs
6229/// ret void
6230/// }
6231/// \endcode
6232static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6233 SourceLocation Loc,
6234 ReductionCodeGen &RCG, unsigned N,
6235 const Expr *ReductionOp,
6236 const Expr *LHS, const Expr *RHS,
6237 const Expr *PrivateRef) {
6238 ASTContext &C = CGM.getContext();
6239 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6240 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
6241 FunctionArgList Args;
6242 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6243 C.VoidPtrTy, ImplicitParamDecl::Other);
6244 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6245 ImplicitParamDecl::Other);
6246 Args.emplace_back(&ParamInOut);
6247 Args.emplace_back(&ParamIn);
6248 const auto &FnInfo =
6249 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
6250 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
6251 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
6252 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
6253 Name, &CGM.getModule());
6254 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
6255 Fn->setDoesNotRecurse();
6256 CodeGenFunction CGF(CGM);
6257 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
6258 llvm::Value *Size = nullptr;
6259 // If the size of the reduction item is non-constant, load it from global
6260 // threadprivate variable.
6261 if (RCG.getSizes(N).second) {
6262 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6263 CGF, CGM.getContext().getSizeType(),
6264 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
6265 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6266 CGM.getContext().getSizeType(), Loc);
6267 }
6268 RCG.emitAggregateType(CGF, N, Size);
6269 // Remap lhs and rhs variables to the addresses of the function arguments.
6270 // %lhs = bitcast void* %arg0 to <type>*
6271 // %rhs = bitcast void* %arg1 to <type>*
6272 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
6273 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
6274 // Pull out the pointer to the variable.
6275 Address PtrAddr = CGF.EmitLoadOfPointer(
6276 CGF.GetAddrOfLocalVar(&ParamInOut),
6277 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6278 return CGF.Builder.CreateElementBitCast(
6279 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6280 });
6281 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
6282 // Pull out the pointer to the variable.
6283 Address PtrAddr = CGF.EmitLoadOfPointer(
6284 CGF.GetAddrOfLocalVar(&ParamIn),
6285 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6286 return CGF.Builder.CreateElementBitCast(
6287 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6288 });
6289 PrivateScope.Privatize();
6290 // Emit the combiner body:
6291 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6292 // store <type> %2, <type>* %lhs
6293 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6294 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6295 cast<DeclRefExpr>(RHS));
6296 CGF.FinishFunction();
6297 return Fn;
6298}
6299
6300/// Emits reduction finalizer function:
6301/// \code
6302/// void @.red_fini(void* %arg) {
6303/// %0 = bitcast void* %arg to <type>*
6304/// <destroy>(<type>* %0)
6305/// ret void
6306/// }
6307/// \endcode
6308static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6309 SourceLocation Loc,
6310 ReductionCodeGen &RCG, unsigned N) {
6311 if (!RCG.needCleanups(N))
6312 return nullptr;
6313 ASTContext &C = CGM.getContext();
6314 FunctionArgList Args;
6315 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6316 ImplicitParamDecl::Other);
6317 Args.emplace_back(&Param);
6318 const auto &FnInfo =
6319 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
6320 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
6321 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
6322 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
6323 Name, &CGM.getModule());
6324 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
6325 Fn->setDoesNotRecurse();
6326 CodeGenFunction CGF(CGM);
6327 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
6328 Address PrivateAddr = CGF.EmitLoadOfPointer(
6329 CGF.GetAddrOfLocalVar(&Param),
6330 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6331 llvm::Value *Size = nullptr;
6332 // If the size of the reduction item is non-constant, load it from global
6333 // threadprivate variable.
6334 if (RCG.getSizes(N).second) {
6335 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6336 CGF, CGM.getContext().getSizeType(),
6337 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
6338 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6339 CGM.getContext().getSizeType(), Loc);
6340 }
6341 RCG.emitAggregateType(CGF, N, Size);
6342 // Emit the finalizer body:
6343 // <destroy>(<type>* %0)
6344 RCG.emitCleanups(CGF, N, PrivateAddr);
6345 CGF.FinishFunction(Loc);
6346 return Fn;
6347}
6348
6349llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6350 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6351 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6352 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6353 return nullptr;
6354
6355 // Build typedef struct:
6356 // kmp_task_red_input {
6357 // void *reduce_shar; // shared reduction item
6358 // size_t reduce_size; // size of data item
6359 // void *reduce_init; // data initialization routine
6360 // void *reduce_fini; // data finalization routine
6361 // void *reduce_comb; // data combiner routine
6362 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6363 // } kmp_task_red_input_t;
6364 ASTContext &C = CGM.getContext();
6365 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
6366 RD->startDefinition();
6367 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6368 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6369 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6370 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6371 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6372 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6373 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6374 RD->completeDefinition();
6375 QualType RDType = C.getRecordType(RD);
6376 unsigned Size = Data.ReductionVars.size();
6377 llvm::APInt ArraySize(/*numBits=*/64, Size);
6378 QualType ArrayRDType = C.getConstantArrayType(
6379 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
6380 // kmp_task_red_input_t .rd_input.[Size];
6381 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6382 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6383 Data.ReductionOps);
6384 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6385 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6386 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6387 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6388 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6389 TaskRedInput.getPointer(), Idxs,
6390 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6391 ".rd_input.gep.");
6392 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6393 // ElemLVal.reduce_shar = &Shareds[Cnt];
6394 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6395 RCG.emitSharedLValue(CGF, Cnt);
6396 llvm::Value *CastedShared =
6397 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF));
6398 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6399 RCG.emitAggregateType(CGF, Cnt);
6400 llvm::Value *SizeValInChars;
6401 llvm::Value *SizeVal;
6402 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6403 // We use delayed creation/initialization for VLAs, array sections and
6404 // custom reduction initializations. It is required because runtime does not
6405 // provide the way to pass the sizes of VLAs/array sections to
6406 // initializer/combiner/finalizer functions and does not pass the pointer to
6407 // original reduction item to the initializer. Instead threadprivate global
6408 // variables are used to store these values and use them in the functions.
6409 bool DelayedCreation = !!SizeVal;
6410 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6411 /*isSigned=*/false);
6412 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6413 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6414 // ElemLVal.reduce_init = init;
6415 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6416 llvm::Value *InitAddr =
6417 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6418 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6419 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6420 // ElemLVal.reduce_fini = fini;
6421 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6422 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6423 llvm::Value *FiniAddr = Fini
6424 ? CGF.EmitCastToVoidPtr(Fini)
6425 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6426 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6427 // ElemLVal.reduce_comb = comb;
6428 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6429 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6430 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6431 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6432 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6433 // ElemLVal.flags = 0;
6434 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6435 if (DelayedCreation) {
6436 CGF.EmitStoreOfScalar(
6437 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
6438 FlagsLVal);
6439 } else
6440 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF),
6441 FlagsLVal.getType());
6442 }
6443 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6444 // *data);
6445 llvm::Value *Args[] = {
6446 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6447 /*isSigned=*/true),
6448 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6449 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6450 CGM.VoidPtrTy)};
6451 return CGF.EmitRuntimeCall(
6452 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6453}
6454
6455void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6456 SourceLocation Loc,
6457 ReductionCodeGen &RCG,
6458 unsigned N) {
6459 auto Sizes = RCG.getSizes(N);
6460 // Emit threadprivate global variable if the type is non-constant
6461 // (Sizes.second = nullptr).
6462 if (Sizes.second) {
6463 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6464 /*isSigned=*/false);
6465 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6466 CGF, CGM.getContext().getSizeType(),
6467 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
6468 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6469 }
6470 // Store address of the original reduction item if custom initializer is used.
6471 if (RCG.usesReductionInitializer(N)) {
6472 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6473 CGF, CGM.getContext().VoidPtrTy,
6474 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
6475 CGF.Builder.CreateStore(
6476 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6477 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy),
6478 SharedAddr, /*IsVolatile=*/false);
6479 }
6480}
6481
6482Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6483 SourceLocation Loc,
6484 llvm::Value *ReductionsPtr,
6485 LValue SharedLVal) {
6486 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6487 // *d);
6488 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
6489 CGM.IntTy,
6490 /*isSigned=*/true),
6491 ReductionsPtr,
6492 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6493 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)};
6494 return Address(
6495 CGF.EmitRuntimeCall(
6496 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6497 SharedLVal.getAlignment());
6498}
6499
6500void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6501 SourceLocation Loc) {
6502 if (!CGF.HaveInsertPoint())
6503 return;
6504
6505 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder();
6506 if (OMPBuilder) {
6507 OMPBuilder->CreateTaskwait(CGF.Builder);
6508 } else {
6509 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6510 // global_tid);
6511 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6512 // Ignore return result until untied tasks are supported.
6513 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
6514 }
6515
6516 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6517 Region->emitUntiedSwitch(CGF);
6518}
6519
6520void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
6521 OpenMPDirectiveKind InnerKind,
6522 const RegionCodeGenTy &CodeGen,
6523 bool HasCancel) {
6524 if (!CGF.HaveInsertPoint())
6525 return;
6526 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
6527 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
6528}
6529
6530namespace {
6531enum RTCancelKind {
6532 CancelNoreq = 0,
6533 CancelParallel = 1,
6534 CancelLoop = 2,
6535 CancelSections = 3,
6536 CancelTaskgroup = 4
6537};
6538} // anonymous namespace
6539
6540static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6541 RTCancelKind CancelKind = CancelNoreq;
6542 if (CancelRegion == OMPD_parallel)
6543 CancelKind = CancelParallel;
6544 else if (CancelRegion == OMPD_for)
6545 CancelKind = CancelLoop;
6546 else if (CancelRegion == OMPD_sections)
6547 CancelKind = CancelSections;
6548 else {
6549 assert(CancelRegion == OMPD_taskgroup)((CancelRegion == OMPD_taskgroup) ? static_cast<void> (
0) : __assert_fail ("CancelRegion == OMPD_taskgroup", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6549, __PRETTY_FUNCTION__))
;
6550 CancelKind = CancelTaskgroup;
6551 }
6552 return CancelKind;
6553}
6554
6555void CGOpenMPRuntime::emitCancellationPointCall(
6556 CodeGenFunction &CGF, SourceLocation Loc,
6557 OpenMPDirectiveKind CancelRegion) {
6558 if (!CGF.HaveInsertPoint())
6559 return;
6560 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6561 // global_tid, kmp_int32 cncl_kind);
6562 if (auto *OMPRegionInfo =
6563 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
6564 // For 'cancellation point taskgroup', the task region info may not have a
6565 // cancel. This may instead happen in another adjacent task.
6566 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6567 llvm::Value *Args[] = {
6568 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6569 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6570 // Ignore return result until untied tasks are supported.
6571 llvm::Value *Result = CGF.EmitRuntimeCall(
6572 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6573 // if (__kmpc_cancellationpoint()) {
6574 // exit from construct;
6575 // }
6576 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6577 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6578 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
6579 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6580 CGF.EmitBlock(ExitBB);
6581 // exit from construct;
6582 CodeGenFunction::JumpDest CancelDest =
6583 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6584 CGF.EmitBranchThroughCleanup(CancelDest);
6585 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6586 }
6587 }
6588}
6589
6590void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
6591 const Expr *IfCond,
6592 OpenMPDirectiveKind CancelRegion) {
6593 if (!CGF.HaveInsertPoint())
6594 return;
6595 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6596 // kmp_int32 cncl_kind);
6597 if (auto *OMPRegionInfo =
6598 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
6599 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6600 PrePostActionTy &) {
6601 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
6602 llvm::Value *Args[] = {
6603 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
6604 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6605 // Ignore return result until untied tasks are supported.
6606 llvm::Value *Result = CGF.EmitRuntimeCall(
6607 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
6608 // if (__kmpc_cancel()) {
6609 // exit from construct;
6610 // }
6611 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6612 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6613 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
6614 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6615 CGF.EmitBlock(ExitBB);
6616 // exit from construct;
6617 CodeGenFunction::JumpDest CancelDest =
6618 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6619 CGF.EmitBranchThroughCleanup(CancelDest);
6620 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6621 };
6622 if (IfCond) {
6623 emitIfClause(CGF, IfCond, ThenGen,
6624 [](CodeGenFunction &, PrePostActionTy &) {});
6625 } else {
6626 RegionCodeGenTy ThenRCG(ThenGen);
6627 ThenRCG(CGF);
6628 }
6629 }
6630}
6631
6632void CGOpenMPRuntime::emitTargetOutlinedFunction(
6633 const OMPExecutableDirective &D, StringRef ParentName,
6634 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6635 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
6636 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6636, __PRETTY_FUNCTION__))
;
6637 HasEmittedTargetRegion = true;
6638 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6639 IsOffloadEntry, CodeGen);
6640}
6641
6642void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6643 const OMPExecutableDirective &D, StringRef ParentName,
6644 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6645 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
6646 // Create a unique name for the entry function using the source location
6647 // information of the current target region. The name will be something like:
6648 //
6649 // __omp_offloading_DD_FFFF_PP_lBB
6650 //
6651 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
6652 // mangled name of the function that encloses the target region and BB is the
6653 // line number of the target region.
6654
6655 unsigned DeviceID;
6656 unsigned FileID;
6657 unsigned Line;
6658 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
6659 Line);
6660 SmallString<64> EntryFnName;
6661 {
6662 llvm::raw_svector_ostream OS(EntryFnName);
6663 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6664 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
6665 }
6666
6667 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6668
6669 CodeGenFunction CGF(CGM, true);
6670 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
6671 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6672
6673 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc());
6674
6675 // If this target outline function is not an offload entry, we don't need to
6676 // register it.
6677 if (!IsOffloadEntry)
6678 return;
6679
6680 // The target region ID is used by the runtime library to identify the current
6681 // target region, so it only has to be unique and not necessarily point to
6682 // anything. It could be the pointer to the outlined function that implements
6683 // the target region, but we aren't using that so that the compiler doesn't
6684 // need to keep that, and could therefore inline the host function if proven
6685 // worthwhile during optimization. In the other hand, if emitting code for the
6686 // device, the ID has to be the function address so that it can retrieved from
6687 // the offloading entry and launched by the runtime library. We also mark the
6688 // outlined function to have external linkage in case we are emitting code for
6689 // the device, because these functions will be entry points to the device.
6690
6691 if (CGM.getLangOpts().OpenMPIsDevice) {
6692 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
6693 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
6694 OutlinedFn->setDSOLocal(false);
6695 } else {
6696 std::string Name = getName({EntryFnName, "region_id"});
6697 OutlinedFnID = new llvm::GlobalVariable(
6698 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
6699 llvm::GlobalValue::WeakAnyLinkage,
6700 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
6701 }
6702
6703 // Register the information for the entry associated with this target region.
6704 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
6705 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
6706 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
6707}
6708
6709/// Checks if the expression is constant or does not have non-trivial function
6710/// calls.
6711static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6712 // We can skip constant expressions.
6713 // We can skip expressions with trivial calls or simple expressions.
6714 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6715 !E->hasNonTrivialCall(Ctx)) &&
6716 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6717}
6718
6719const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6720 const Stmt *Body) {
6721 const Stmt *Child = Body->IgnoreContainers();
6722 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6723 Child = nullptr;
6724 for (const Stmt *S : C->body()) {
6725 if (const auto *E = dyn_cast<Expr>(S)) {
6726 if (isTrivial(Ctx, E))
6727 continue;
6728 }
6729 // Some of the statements can be ignored.
6730 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6731 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6732 continue;
6733 // Analyze declarations.
6734 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6735 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6736 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6737 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6738 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6739 isa<UsingDirectiveDecl>(D) ||
6740 isa<OMPDeclareReductionDecl>(D) ||
6741 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6742 return true;
6743 const auto *VD = dyn_cast<VarDecl>(D);
6744 if (!VD)
6745 return false;
6746 return VD->isConstexpr() ||
6747 ((VD->getType().isTrivialType(Ctx) ||
6748 VD->getType()->isReferenceType()) &&
6749 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6750 }))
6751 continue;
6752 }
6753 // Found multiple children - cannot get the one child only.
6754 if (Child)
6755 return nullptr;
6756 Child = S;
6757 }
6758 if (Child)
6759 Child = Child->IgnoreContainers();
6760 }
6761 return Child;
6762}
6763
6764/// Emit the number of teams for a target directive. Inspect the num_teams
6765/// clause associated with a teams construct combined or closely nested
6766/// with the target directive.
6767///
6768/// Emit a team of size one for directives such as 'target parallel' that
6769/// have no associated teams construct.
6770///
6771/// Otherwise, return nullptr.
6772static llvm::Value *
6773emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
6774 const OMPExecutableDirective &D) {
6775 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6777, __PRETTY_FUNCTION__))
6776 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6777, __PRETTY_FUNCTION__))
6777 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6777, __PRETTY_FUNCTION__))
;
6778 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6779 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6780, __PRETTY_FUNCTION__))
6780 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6780, __PRETTY_FUNCTION__))
;
6781 CGBuilderTy &Bld = CGF.Builder;
6782 switch (DirectiveKind) {
6783 case OMPD_target: {
6784 const auto *CS = D.getInnermostCapturedStmt();
6785 const auto *Body =
6786 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6787 const Stmt *ChildStmt =
6788 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6789 if (const auto *NestedDir =
6790 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6791 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6792 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6793 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6794 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6795 const Expr *NumTeams =
6796 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6797 llvm::Value *NumTeamsVal =
6798 CGF.EmitScalarExpr(NumTeams,
6799 /*IgnoreResultAssign*/ true);
6800 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6801 /*isSigned=*/true);
6802 }
6803 return Bld.getInt32(0);
6804 }
6805 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6806 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6807 return Bld.getInt32(1);
6808 return Bld.getInt32(0);
6809 }
6810 return nullptr;
6811 }
6812 case OMPD_target_teams:
6813 case OMPD_target_teams_distribute:
6814 case OMPD_target_teams_distribute_simd:
6815 case OMPD_target_teams_distribute_parallel_for:
6816 case OMPD_target_teams_distribute_parallel_for_simd: {
6817 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6818 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6819 const Expr *NumTeams =
6820 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6821 llvm::Value *NumTeamsVal =
6822 CGF.EmitScalarExpr(NumTeams,
6823 /*IgnoreResultAssign*/ true);
6824 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6825 /*isSigned=*/true);
6826 }
6827 return Bld.getInt32(0);
6828 }
6829 case OMPD_target_parallel:
6830 case OMPD_target_parallel_for:
6831 case OMPD_target_parallel_for_simd:
6832 case OMPD_target_simd:
6833 return Bld.getInt32(1);
6834 case OMPD_parallel:
6835 case OMPD_for:
6836 case OMPD_parallel_for:
6837 case OMPD_parallel_master:
6838 case OMPD_parallel_sections:
6839 case OMPD_for_simd:
6840 case OMPD_parallel_for_simd:
6841 case OMPD_cancel:
6842 case OMPD_cancellation_point:
6843 case OMPD_ordered:
6844 case OMPD_threadprivate:
6845 case OMPD_allocate:
6846 case OMPD_task:
6847 case OMPD_simd:
6848 case OMPD_sections:
6849 case OMPD_section:
6850 case OMPD_single:
6851 case OMPD_master:
6852 case OMPD_critical:
6853 case OMPD_taskyield:
6854 case OMPD_barrier:
6855 case OMPD_taskwait:
6856 case OMPD_taskgroup:
6857 case OMPD_atomic:
6858 case OMPD_flush:
6859 case OMPD_depobj:
6860 case OMPD_teams:
6861 case OMPD_target_data:
6862 case OMPD_target_exit_data:
6863 case OMPD_target_enter_data:
6864 case OMPD_distribute:
6865 case OMPD_distribute_simd:
6866 case OMPD_distribute_parallel_for:
6867 case OMPD_distribute_parallel_for_simd:
6868 case OMPD_teams_distribute:
6869 case OMPD_teams_distribute_simd:
6870 case OMPD_teams_distribute_parallel_for:
6871 case OMPD_teams_distribute_parallel_for_simd:
6872 case OMPD_target_update:
6873 case OMPD_declare_simd:
6874 case OMPD_declare_variant:
6875 case OMPD_declare_target:
6876 case OMPD_end_declare_target:
6877 case OMPD_declare_reduction:
6878 case OMPD_declare_mapper:
6879 case OMPD_taskloop:
6880 case OMPD_taskloop_simd:
6881 case OMPD_master_taskloop:
6882 case OMPD_master_taskloop_simd:
6883 case OMPD_parallel_master_taskloop:
6884 case OMPD_parallel_master_taskloop_simd:
6885 case OMPD_requires:
6886 case OMPD_unknown:
6887 break;
6888 }
6889 llvm_unreachable("Unexpected directive kind.")::llvm::llvm_unreachable_internal("Unexpected directive kind."
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6889)
;
6890}
6891
6892static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6893 llvm::Value *DefaultThreadLimitVal) {
6894 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6895 CGF.getContext(), CS->getCapturedStmt());
6896 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6897 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
6898 llvm::Value *NumThreads = nullptr;
6899 llvm::Value *CondVal = nullptr;
6900 // Handle if clause. If if clause present, the number of threads is
6901 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6902 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6903 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6904 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6905 const OMPIfClause *IfClause = nullptr;
6906 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6907 if (C->getNameModifier() == OMPD_unknown ||
6908 C->getNameModifier() == OMPD_parallel) {
6909 IfClause = C;
6910 break;
6911 }
6912 }
6913 if (IfClause) {
6914 const Expr *Cond = IfClause->getCondition();
6915 bool Result;
6916 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6917 if (!Result)
6918 return CGF.Builder.getInt32(1);
6919 } else {
6920 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6921 if (const auto *PreInit =
6922 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6923 for (const auto *I : PreInit->decls()) {
6924 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6925 CGF.EmitVarDecl(cast<VarDecl>(*I));
6926 } else {
6927 CodeGenFunction::AutoVarEmission Emission =
6928 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6929 CGF.EmitAutoVarCleanups(Emission);
6930 }
6931 }
6932 }
6933 CondVal = CGF.EvaluateExprAsBool(Cond);
6934 }
6935 }
6936 }
6937 // Check the value of num_threads clause iff if clause was not specified
6938 // or is not evaluated to false.
6939 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6940 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6941 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6942 const auto *NumThreadsClause =
6943 Dir->getSingleClause<OMPNumThreadsClause>();
6944 CodeGenFunction::LexicalScope Scope(
6945 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6946 if (const auto *PreInit =
6947 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6948 for (const auto *I : PreInit->decls()) {
6949 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6950 CGF.EmitVarDecl(cast<VarDecl>(*I));
6951 } else {
6952 CodeGenFunction::AutoVarEmission Emission =
6953 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6954 CGF.EmitAutoVarCleanups(Emission);
6955 }
6956 }
6957 }
6958 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
6959 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
6960 /*isSigned=*/false);
6961 if (DefaultThreadLimitVal)
6962 NumThreads = CGF.Builder.CreateSelect(
6963 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6964 DefaultThreadLimitVal, NumThreads);
6965 } else {
6966 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6967 : CGF.Builder.getInt32(0);
6968 }
6969 // Process condition of the if clause.
6970 if (CondVal) {
6971 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6972 CGF.Builder.getInt32(1));
6973 }
6974 return NumThreads;
6975 }
6976 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6977 return CGF.Builder.getInt32(1);
6978 return DefaultThreadLimitVal;
6979 }
6980 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6981 : CGF.Builder.getInt32(0);
6982}
6983
6984/// Emit the number of threads for a target directive. Inspect the
6985/// thread_limit clause associated with a teams construct combined or closely
6986/// nested with the target directive.
6987///
6988/// Emit the num_threads clause for directives such as 'target parallel' that
6989/// have no associated teams construct.
6990///
6991/// Otherwise, return nullptr.
6992static llvm::Value *
6993emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
6994 const OMPExecutableDirective &D) {
6995 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6997, __PRETTY_FUNCTION__))
6996 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6997, __PRETTY_FUNCTION__))
6997 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6997, __PRETTY_FUNCTION__))
;
6998 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6999 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7000, __PRETTY_FUNCTION__))
7000 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7000, __PRETTY_FUNCTION__))
;
7001 CGBuilderTy &Bld = CGF.Builder;
7002 llvm::Value *ThreadLimitVal = nullptr;
7003 llvm::Value *NumThreadsVal = nullptr;
7004 switch (DirectiveKind) {
7005 case OMPD_target: {
7006 const CapturedStmt *CS = D.getInnermostCapturedStmt();
7007 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
7008 return NumThreads;
7009 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
7010 CGF.getContext(), CS->getCapturedStmt());
7011 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
7012 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
7013 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
7014 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
7015 const auto *ThreadLimitClause =
7016 Dir->getSingleClause<OMPThreadLimitClause>();
7017 CodeGenFunction::LexicalScope Scope(
7018 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
7019 if (const auto *PreInit =
7020 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
7021 for (const auto *I : PreInit->decls()) {
7022 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
7023 CGF.EmitVarDecl(cast<VarDecl>(*I));
7024 } else {
7025 CodeGenFunction::AutoVarEmission Emission =
7026 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
7027 CGF.EmitAutoVarCleanups(Emission);
7028 }
7029 }
7030 }
7031 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
7032 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
7033 ThreadLimitVal =
7034 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
7035 }
7036 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
7037 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
7038 CS = Dir->getInnermostCapturedStmt();
7039 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
7040 CGF.getContext(), CS->getCapturedStmt());
7041 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
7042 }
7043 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
7044 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
7045 CS = Dir->getInnermostCapturedStmt();
7046 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
7047 return NumThreads;
7048 }
7049 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
7050 return Bld.getInt32(1);
7051 }
7052 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
7053 }
7054 case OMPD_target_teams: {
7055 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
7056 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
7057 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
7058 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
7059 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
7060 ThreadLimitVal =
7061 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
7062 }
7063 const CapturedStmt *CS = D.getInnermostCapturedStmt();
7064 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
7065 return NumThreads;
7066 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
7067 CGF.getContext(), CS->getCapturedStmt());
7068 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
7069 if (Dir->getDirectiveKind() == OMPD_distribute) {
7070 CS = Dir->getInnermostCapturedStmt();
7071 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
7072 return NumThreads;
7073 }
7074 }
7075 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
7076 }
7077 case OMPD_target_teams_distribute:
7078 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
7079 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
7080 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
7081 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
7082 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
7083 ThreadLimitVal =
7084 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
7085 }
7086 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
7087 case OMPD_target_parallel:
7088 case OMPD_target_parallel_for:
7089 case OMPD_target_parallel_for_simd:
7090 case OMPD_target_teams_distribute_parallel_for:
7091 case OMPD_target_teams_distribute_parallel_for_simd: {
7092 llvm::Value *CondVal = nullptr;
7093 // Handle if clause. If if clause present, the number of threads is
7094 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
7095 if (D.hasClausesOfKind<OMPIfClause>()) {
7096 const OMPIfClause *IfClause = nullptr;
7097 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
7098 if (C->getNameModifier() == OMPD_unknown ||
7099 C->getNameModifier() == OMPD_parallel) {
7100 IfClause = C;
7101 break;
7102 }
7103 }
7104 if (IfClause) {
7105 const Expr *Cond = IfClause->getCondition();
7106 bool Result;
7107 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
7108 if (!Result)
7109 return Bld.getInt32(1);
7110 } else {
7111 CodeGenFunction::RunCleanupsScope Scope(CGF);
7112 CondVal = CGF.EvaluateExprAsBool(Cond);
7113 }
7114 }
7115 }
7116 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
7117 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
7118 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
7119 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
7120 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
7121 ThreadLimitVal =
7122 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
7123 }
7124 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
7125 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
7126 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
7127 llvm::Value *NumThreads = CGF.EmitScalarExpr(
7128 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
7129 NumThreadsVal =
7130 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
7131 ThreadLimitVal = ThreadLimitVal
7132 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
7133 ThreadLimitVal),
7134 NumThreadsVal, ThreadLimitVal)
7135 : NumThreadsVal;
7136 }
7137 if (!ThreadLimitVal)
7138 ThreadLimitVal = Bld.getInt32(0);
7139 if (CondVal)
7140 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
7141 return ThreadLimitVal;
7142 }
7143 case OMPD_target_teams_distribute_simd:
7144 case OMPD_target_simd:
7145 return Bld.getInt32(1);
7146 case OMPD_parallel:
7147 case OMPD_for:
7148 case OMPD_parallel_for:
7149 case OMPD_parallel_master:
7150 case OMPD_parallel_sections:
7151 case OMPD_for_simd:
7152 case OMPD_parallel_for_simd:
7153 case OMPD_cancel:
7154 case OMPD_cancellation_point:
7155 case OMPD_ordered:
7156 case OMPD_threadprivate:
7157 case OMPD_allocate:
7158 case OMPD_task:
7159 case OMPD_simd:
7160 case OMPD_sections:
7161 case OMPD_section:
7162 case OMPD_single:
7163 case OMPD_master:
7164 case OMPD_critical:
7165 case OMPD_taskyield:
7166 case OMPD_barrier:
7167 case OMPD_taskwait:
7168 case OMPD_taskgroup:
7169 case OMPD_atomic:
7170 case OMPD_flush:
7171 case OMPD_depobj:
7172 case OMPD_teams:
7173 case OMPD_target_data:
7174 case OMPD_target_exit_data:
7175 case OMPD_target_enter_data:
7176 case OMPD_distribute:
7177 case OMPD_distribute_simd:
7178 case OMPD_distribute_parallel_for:
7179 case OMPD_distribute_parallel_for_simd:
7180 case OMPD_teams_distribute:
7181 case OMPD_teams_distribute_simd:
7182 case OMPD_teams_distribute_parallel_for:
7183 case OMPD_teams_distribute_parallel_for_simd:
7184 case OMPD_target_update:
7185 case OMPD_declare_simd:
7186 case OMPD_declare_variant:
7187 case OMPD_declare_target:
7188 case OMPD_end_declare_target:
7189 case OMPD_declare_reduction:
7190 case OMPD_declare_mapper:
7191 case OMPD_taskloop:
7192 case OMPD_taskloop_simd:
7193 case OMPD_master_taskloop:
7194 case OMPD_master_taskloop_simd:
7195 case OMPD_parallel_master_taskloop:
7196 case OMPD_parallel_master_taskloop_simd:
7197 case OMPD_requires:
7198 case OMPD_unknown:
7199 break;
7200 }
7201 llvm_unreachable("Unsupported directive kind.")::llvm::llvm_unreachable_internal("Unsupported directive kind."
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7201)
;
7202}
7203
7204namespace {
7205LLVM_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^=
;
7206
7207// Utility to handle information from clauses associated with a given
7208// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7209// It provides a convenient interface to obtain the information and generate
7210// code for that information.
7211class MappableExprsHandler {
7212public:
7213 /// Values for bit flags used to specify the mapping type for
7214 /// offloading.
7215 enum OpenMPOffloadMappingFlags : uint64_t {
7216 /// No flags
7217 OMP_MAP_NONE = 0x0,
7218 /// Allocate memory on the device and move data from host to device.
7219 OMP_MAP_TO = 0x01,
7220 /// Allocate memory on the device and move data from device to host.
7221 OMP_MAP_FROM = 0x02,
7222 /// Always perform the requested mapping action on the element, even
7223 /// if it was already mapped before.
7224 OMP_MAP_ALWAYS = 0x04,
7225 /// Delete the element from the device environment, ignoring the
7226 /// current reference count associated with the element.
7227 OMP_MAP_DELETE = 0x08,
7228 /// The element being mapped is a pointer-pointee pair; both the
7229 /// pointer and the pointee should be mapped.
7230 OMP_MAP_PTR_AND_OBJ = 0x10,
7231 /// This flags signals that the base address of an entry should be
7232 /// passed to the target kernel as an argument.
7233 OMP_MAP_TARGET_PARAM = 0x20,
7234 /// Signal that the runtime library has to return the device pointer
7235 /// in the current position for the data being mapped. Used when we have the
7236 /// use_device_ptr clause.
7237 OMP_MAP_RETURN_PARAM = 0x40,
7238 /// This flag signals that the reference being passed is a pointer to
7239 /// private data.
7240 OMP_MAP_PRIVATE = 0x80,
7241 /// Pass the element to the device by value.
7242 OMP_MAP_LITERAL = 0x100,
7243 /// Implicit map
7244 OMP_MAP_IMPLICIT = 0x200,
7245 /// Close is a hint to the runtime to allocate memory close to
7246 /// the target device.
7247 OMP_MAP_CLOSE = 0x400,
7248 /// The 16 MSBs of the flags indicate whether the entry is member of some
7249 /// struct/class.
7250 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7251 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_MAP_MEMBER_OF,
7252 };
7253
7254 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7255 static unsigned getFlagMemberOffset() {
7256 unsigned Offset = 0;
7257 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7258 Remain = Remain >> 1)
7259 Offset++;
7260 return Offset;
7261 }
7262
7263 /// Class that associates information with a base pointer to be passed to the
7264 /// runtime library.
7265 class BasePointerInfo {
7266 /// The base pointer.
7267 llvm::Value *Ptr = nullptr;
7268 /// The base declaration that refers to this device pointer, or null if
7269 /// there is none.
7270 const ValueDecl *DevPtrDecl = nullptr;
7271
7272 public:
7273 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7274 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7275 llvm::Value *operator*() const { return Ptr; }
7276 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7277 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7278 };
7279
7280 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7281 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7282 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7283
7284 /// Map between a struct and the its lowest & highest elements which have been
7285 /// mapped.
7286 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7287 /// HE(FieldIndex, Pointer)}
7288 struct StructRangeInfoTy {
7289 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7290 0, Address::invalid()};
7291 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7292 0, Address::invalid()};
7293 Address Base = Address::invalid();
7294 };
7295
7296private:
7297 /// Kind that defines how a device pointer has to be returned.
7298 struct MapInfo {
7299 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7300 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
7301 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7302 bool ReturnDevicePointer = false;
7303 bool IsImplicit = false;
7304
7305 MapInfo() = default;
7306 MapInfo(
7307 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
7308 OpenMPMapClauseKind MapType,
7309 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7310 bool ReturnDevicePointer, bool IsImplicit)
7311 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7312 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7313 };
7314
7315 /// If use_device_ptr is used on a pointer which is a struct member and there
7316 /// is no map information about it, then emission of that entry is deferred
7317 /// until the whole struct has been processed.
7318 struct DeferredDevicePtrEntryTy {
7319 const Expr *IE = nullptr;
7320 const ValueDecl *VD = nullptr;
7321
7322 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7323 : IE(IE), VD(VD) {}
7324 };
7325
7326 /// The target directive from where the mappable clauses were extracted. It
7327 /// is either a executable directive or a user-defined mapper directive.
7328 llvm::PointerUnion<const OMPExecutableDirective *,
7329 const OMPDeclareMapperDecl *>
7330 CurDir;
7331
7332 /// Function the directive is being generated for.
7333 CodeGenFunction &CGF;
7334
7335 /// Set of all first private variables in the current directive.
7336 /// bool data is set to true if the variable is implicitly marked as
7337 /// firstprivate, false otherwise.
7338 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
7339
7340 /// Map between device pointer declarations and their expression components.
7341 /// The key value for declarations in 'this' is null.
7342 llvm::DenseMap<
7343 const ValueDecl *,
7344 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7345 DevPointersMap;
7346
7347 llvm::Value *getExprTypeSize(const Expr *E) const {
7348 QualType ExprTy = E->getType().getCanonicalType();
7349
7350 // Reference types are ignored for mapping purposes.
7351 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
7352 ExprTy = RefTy->getPointeeType().getCanonicalType();
7353
7354 // Given that an array section is considered a built-in type, we need to
7355 // do the calculation based on the length of the section instead of relying
7356 // on CGF.getTypeSize(E->getType()).
7357 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7358 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7359 OAE->getBase()->IgnoreParenImpCasts())
7360 .getCanonicalType();
7361
7362 // If there is no length associated with the expression and lower bound is
7363 // not specified too, that means we are using the whole length of the
7364 // base.
7365 if (!OAE->getLength() && OAE->getColonLoc().isValid() &&
7366 !OAE->getLowerBound())
7367 return CGF.getTypeSize(BaseTy);
7368
7369 llvm::Value *ElemSize;
7370 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
7371 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
7372 } else {
7373 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
7374 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7374, __PRETTY_FUNCTION__))
;
7375 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7376 }
7377
7378 // If we don't have a length at this point, that is because we have an
7379 // array section with a single element.
7380 if (!OAE->getLength() && OAE->getColonLoc().isInvalid())
7381 return ElemSize;
7382
7383 if (const Expr *LenExpr = OAE->getLength()) {
7384 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7385 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7386 CGF.getContext().getSizeType(),
7387 LenExpr->getExprLoc());
7388 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7389 }
7390 assert(!OAE->getLength() && OAE->getColonLoc().isValid() &&((!OAE->getLength() && OAE->getColonLoc().isValid
() && OAE->getLowerBound() && "expected array_section[lb:]."
) ? static_cast<void> (0) : __assert_fail ("!OAE->getLength() && OAE->getColonLoc().isValid() && OAE->getLowerBound() && \"expected array_section[lb:].\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7391, __PRETTY_FUNCTION__))
7391 OAE->getLowerBound() && "expected array_section[lb:].")((!OAE->getLength() && OAE->getColonLoc().isValid
() && OAE->getLowerBound() && "expected array_section[lb:]."
) ? static_cast<void> (0) : __assert_fail ("!OAE->getLength() && OAE->getColonLoc().isValid() && OAE->getLowerBound() && \"expected array_section[lb:].\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7391, __PRETTY_FUNCTION__))
;
7392 // Size = sizetype - lb * elemtype;
7393 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7394 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7395 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7396 CGF.getContext().getSizeType(),
7397 OAE->getLowerBound()->getExprLoc());
7398 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7399 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7400 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7401 LengthVal = CGF.Builder.CreateSelect(
7402 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7403 return LengthVal;
7404 }
7405 return CGF.getTypeSize(ExprTy);
7406 }
7407
7408 /// Return the corresponding bits for a given map clause modifier. Add
7409 /// a flag marking the map as a pointer if requested. Add a flag marking the
7410 /// map as the first one of a series of maps that relate to the same map
7411 /// expression.
7412 OpenMPOffloadMappingFlags getMapTypeBits(
7413 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7414 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
7415 OpenMPOffloadMappingFlags Bits =
7416 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
7417 switch (MapType) {
7418 case OMPC_MAP_alloc:
7419 case OMPC_MAP_release:
7420 // alloc and release is the default behavior in the runtime library, i.e.
7421 // if we don't pass any bits alloc/release that is what the runtime is
7422 // going to do. Therefore, we don't need to signal anything for these two
7423 // type modifiers.
7424 break;
7425 case OMPC_MAP_to:
7426 Bits |= OMP_MAP_TO;
7427 break;
7428 case OMPC_MAP_from:
7429 Bits |= OMP_MAP_FROM;
7430 break;
7431 case OMPC_MAP_tofrom:
7432 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
7433 break;
7434 case OMPC_MAP_delete:
7435 Bits |= OMP_MAP_DELETE;
7436 break;
7437 case OMPC_MAP_unknown:
7438 llvm_unreachable("Unexpected map type!")::llvm::llvm_unreachable_internal("Unexpected map type!", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7438)
;
7439 }
7440 if (AddPtrFlag)
7441 Bits |= OMP_MAP_PTR_AND_OBJ;
7442 if (AddIsTargetParamFlag)
7443 Bits |= OMP_MAP_TARGET_PARAM;
7444 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7445 != MapModifiers.end())
7446 Bits |= OMP_MAP_ALWAYS;
7447 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7448 != MapModifiers.end())
7449 Bits |= OMP_MAP_CLOSE;
7450 return Bits;
7451 }
7452
7453 /// Return true if the provided expression is a final array section. A
7454 /// final array section, is one whose length can't be proved to be one.
7455 bool isFinalArraySectionExpression(const Expr *E) const {
7456 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
7457
7458 // It is not an array section and therefore not a unity-size one.
7459 if (!OASE)
7460 return false;
7461
7462 // An array section with no colon always refer to a single element.
7463 if (OASE->getColonLoc().isInvalid())
7464 return false;
7465
7466 const Expr *Length = OASE->getLength();
7467
7468 // If we don't have a length we have to check if the array has size 1
7469 // for this dimension. Also, we should always expect a length if the
7470 // base type is pointer.
7471 if (!Length) {
7472 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7473 OASE->getBase()->IgnoreParenImpCasts())
7474 .getCanonicalType();
7475 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
7476 return ATy->getSize().getSExtValue() != 1;
7477 // If we don't have a constant dimension length, we have to consider
7478 // the current section as having any size, so it is not necessarily
7479 // unitary. If it happen to be unity size, that's user fault.
7480 return true;
7481 }
7482
7483 // Check if the length evaluates to 1.
7484 Expr::EvalResult Result;
7485 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
7486 return true; // Can have more that size 1.
7487
7488 llvm::APSInt ConstLength = Result.Val.getInt();
7489 return ConstLength.getSExtValue() != 1;
7490 }
7491
7492 /// Generate the base pointers, section pointers, sizes and map type
7493 /// bits for the provided map type, map modifier, and expression components.
7494 /// \a IsFirstComponent should be set to true if the provided set of
7495 /// components is the first associated with a capture.
7496 void generateInfoForComponentList(
7497 OpenMPMapClauseKind MapType,
7498 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7499 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
7500 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
7501 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
7502 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
7503 bool IsImplicit,
7504 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7505 OverlappedElements = llvm::None) const {
7506 // The following summarizes what has to be generated for each map and the
7507 // types below. The generated information is expressed in this order:
7508 // base pointer, section pointer, size, flags
7509 // (to add to the ones that come from the map type and modifier).
7510 //
7511 // double d;
7512 // int i[100];
7513 // float *p;
7514 //
7515 // struct S1 {
7516 // int i;
7517 // float f[50];
7518 // }
7519 // struct S2 {
7520 // int i;
7521 // float f[50];
7522 // S1 s;
7523 // double *p;
7524 // struct S2 *ps;
7525 // }
7526 // S2 s;
7527 // S2 *ps;
7528 //
7529 // map(d)
7530 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
7531 //
7532 // map(i)
7533 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
7534 //
7535 // map(i[1:23])
7536 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
7537 //
7538 // map(p)
7539 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
7540 //
7541 // map(p[1:24])
7542 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
7543 //
7544 // map(s)
7545 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
7546 //
7547 // map(s.i)
7548 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
7549 //
7550 // map(s.s.f)
7551 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
7552 //
7553 // map(s.p)
7554 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
7555 //
7556 // map(to: s.p[:22])
7557 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7558 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7559 // &(s.p), &(s.p[0]), 22*sizeof(double),
7560 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7561 // (*) alloc space for struct members, only this is a target parameter
7562 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7563 // optimizes this entry out, same in the examples below)
7564 // (***) map the pointee (map: to)
7565 //
7566 // map(s.ps)
7567 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
7568 //
7569 // map(from: s.ps->s.i)
7570 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7571 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7572 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7573 //
7574 // map(to: s.ps->ps)
7575 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7576 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7577 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
7578 //
7579 // map(s.ps->ps->ps)
7580 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7581 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7582 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7583 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
7584 //
7585 // map(to: s.ps->ps->s.f[:22])
7586 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7587 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7588 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7589 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7590 //
7591 // map(ps)
7592 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
7593 //
7594 // map(ps->i)
7595 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
7596 //
7597 // map(ps->s.f)
7598 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
7599 //
7600 // map(from: ps->p)
7601 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
7602 //
7603 // map(to: ps->p[:22])
7604 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7605 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7606 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
7607 //
7608 // map(ps->ps)
7609 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
7610 //
7611 // map(from: ps->ps->s.i)
7612 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7613 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7614 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7615 //
7616 // map(from: ps->ps->ps)
7617 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7618 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7619 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7620 //
7621 // map(ps->ps->ps->ps)
7622 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7623 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7624 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7625 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
7626 //
7627 // map(to: ps->ps->ps->s.f[:22])
7628 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7629 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7630 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7631 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7632 //
7633 // map(to: s.f[:22]) map(from: s.p[:33])
7634 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7635 // sizeof(double*) (**), TARGET_PARAM
7636 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7637 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7638 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7639 // (*) allocate contiguous space needed to fit all mapped members even if
7640 // we allocate space for members not mapped (in this example,
7641 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7642 // them as well because they fall between &s.f[0] and &s.p)
7643 //
7644 // map(from: s.f[:22]) map(to: ps->p[:33])
7645 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7646 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7647 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7648 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7649 // (*) the struct this entry pertains to is the 2nd element in the list of
7650 // arguments, hence MEMBER_OF(2)
7651 //
7652 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7653 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7654 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7655 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7656 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7657 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7658 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7659 // (*) the struct this entry pertains to is the 4th element in the list
7660 // of arguments, hence MEMBER_OF(4)
7661
7662 // Track if the map information being generated is the first for a capture.
7663 bool IsCaptureFirstInfo = IsFirstComponentList;
7664 // When the variable is on a declare target link or in a to clause with
7665 // unified memory, a reference is needed to hold the host/device address
7666 // of the variable.
7667 bool RequiresReference = false;
7668
7669 // Scan the components from the base to the complete expression.
7670 auto CI = Components.rbegin();
7671 auto CE = Components.rend();
7672 auto I = CI;
7673
7674 // Track if the map information being generated is the first for a list of
7675 // components.
7676 bool IsExpressionFirstInfo = true;
7677 Address BP = Address::invalid();
7678 const Expr *AssocExpr = I->getAssociatedExpression();
7679 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7680 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
7681
7682 if (isa<MemberExpr>(AssocExpr)) {
7683 // The base is the 'this' pointer. The content of the pointer is going
7684 // to be the base of the field being mapped.
7685 BP = CGF.LoadCXXThisAddress();
7686 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7687 (OASE &&
7688 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7689 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
7690 } else {
7691 // The base is the reference to the variable.
7692 // BP = &Var.
7693 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
7694 if (const auto *VD =
7695 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7696 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7697 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7698 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7699 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7700 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7701 RequiresReference = true;
7702 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
7703 }
7704 }
7705 }
7706
7707 // If the variable is a pointer and is being dereferenced (i.e. is not
7708 // the last component), the base has to be the pointer itself, not its
7709 // reference. References are ignored for mapping purposes.
7710 QualType Ty =
7711 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7712 if (Ty->isAnyPointerType() && std::next(I) != CE) {
7713 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
7714
7715 // We do not need to generate individual map information for the
7716 // pointer, it can be associated with the combined storage.
7717 ++I;
7718 }
7719 }
7720
7721 // Track whether a component of the list should be marked as MEMBER_OF some
7722 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7723 // in a component list should be marked as MEMBER_OF, all subsequent entries
7724 // do not belong to the base struct. E.g.
7725 // struct S2 s;
7726 // s.ps->ps->ps->f[:]
7727 // (1) (2) (3) (4)
7728 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7729 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7730 // is the pointee of ps(2) which is not member of struct s, so it should not
7731 // be marked as such (it is still PTR_AND_OBJ).
7732 // The variable is initialized to false so that PTR_AND_OBJ entries which
7733 // are not struct members are not considered (e.g. array of pointers to
7734 // data).
7735 bool ShouldBeMemberOf = false;
7736
7737 // Variable keeping track of whether or not we have encountered a component
7738 // in the component list which is a member expression. Useful when we have a
7739 // pointer or a final array section, in which case it is the previous
7740 // component in the list which tells us whether we have a member expression.
7741 // E.g. X.f[:]
7742 // While processing the final array section "[:]" it is "f" which tells us
7743 // whether we are dealing with a member of a declared struct.
7744 const MemberExpr *EncounteredME = nullptr;
7745
7746 for (; I != CE; ++I) {
7747 // If the current component is member of a struct (parent struct) mark it.
7748 if (!EncounteredME) {
7749 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7750 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7751 // as MEMBER_OF the parent struct.
7752 if (EncounteredME)
7753 ShouldBeMemberOf = true;
7754 }
7755
7756 auto Next = std::next(I);
7757
7758 // We need to generate the addresses and sizes if this is the last
7759 // component, if the component is a pointer or if it is an array section
7760 // whose length can't be proved to be one. If this is a pointer, it
7761 // becomes the base address for the following components.
7762
7763 // A final array section, is one whose length can't be proved to be one.
7764 bool IsFinalArraySection =
7765 isFinalArraySectionExpression(I->getAssociatedExpression());
7766
7767 // Get information on whether the element is a pointer. Have to do a
7768 // special treatment for array sections given that they are built-in
7769 // types.
7770 const auto *OASE =
7771 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7772 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
7773 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7774 bool IsPointer =
7775 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7776 .getCanonicalType()
7777 ->isAnyPointerType()) ||
7778 I->getAssociatedExpression()->getType()->isAnyPointerType();
7779 bool IsNonDerefPointer = IsPointer && !UO && !BO;
7780
7781 if (Next == CE || IsNonDerefPointer || IsFinalArraySection) {
7782 // If this is not the last component, we expect the pointer to be
7783 // associated with an array expression or member expression.
7784 assert((Next == CE ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(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<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7790, __PRETTY_FUNCTION__))
7785 isa<MemberExpr>(Next->getAssociatedExpression()) ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(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<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7790, __PRETTY_FUNCTION__))
7786 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(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<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7790, __PRETTY_FUNCTION__))
7787 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(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<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7790, __PRETTY_FUNCTION__))
7788 isa<UnaryOperator>(Next->getAssociatedExpression()) ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(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<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7790, __PRETTY_FUNCTION__))
7789 isa<BinaryOperator>(Next->getAssociatedExpression())) &&(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(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<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7790, __PRETTY_FUNCTION__))
7790 "Unexpected expression")(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(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<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7790, __PRETTY_FUNCTION__))
;
7791
7792 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
7793 .getAddress(CGF);
7794
7795 // If this component is a pointer inside the base struct then we don't
7796 // need to create any entry for it - it will be combined with the object
7797 // it is pointing to into a single PTR_AND_OBJ entry.
7798 bool IsMemberPointer =
7799 IsPointer && EncounteredME &&
7800 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7801 EncounteredME);
7802 if (!OverlappedElements.empty()) {
7803 // Handle base element with the info for overlapped elements.
7804 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7804, __PRETTY_FUNCTION__))
;
7805 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7806, __PRETTY_FUNCTION__))
7806 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7806, __PRETTY_FUNCTION__))
;
7807 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7808, __PRETTY_FUNCTION__))
7808 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7808, __PRETTY_FUNCTION__))
;
7809 // Mark the whole struct as the struct that requires allocation on the
7810 // device.
7811 PartialStruct.LowestElem = {0, LB};
7812 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7813 I->getAssociatedExpression()->getType());
7814 Address HB = CGF.Builder.CreateConstGEP(
7815 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7816 CGF.VoidPtrTy),
7817 TypeSize.getQuantity() - 1);
7818 PartialStruct.HighestElem = {
7819 std::numeric_limits<decltype(
7820 PartialStruct.HighestElem.first)>::max(),
7821 HB};
7822 PartialStruct.Base = BP;
7823 // Emit data for non-overlapped data.
7824 OpenMPOffloadMappingFlags Flags =
7825 OMP_MAP_MEMBER_OF |
7826 getMapTypeBits(MapType, MapModifiers, IsImplicit,
7827 /*AddPtrFlag=*/false,
7828 /*AddIsTargetParamFlag=*/false);
7829 LB = BP;
7830 llvm::Value *Size = nullptr;
7831 // Do bitcopy of all non-overlapped structure elements.
7832 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7833 Component : OverlappedElements) {
7834 Address ComponentLB = Address::invalid();
7835 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7836 Component) {
7837 if (MC.getAssociatedDeclaration()) {
7838 ComponentLB =
7839 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7840 .getAddress(CGF);
7841 Size = CGF.Builder.CreatePtrDiff(
7842 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7843 CGF.EmitCastToVoidPtr(LB.getPointer()));
7844 break;
7845 }
7846 }
7847 BasePointers.push_back(BP.getPointer());
7848 Pointers.push_back(LB.getPointer());
7849 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7850 /*isSigned=*/true));
7851 Types.push_back(Flags);
7852 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
7853 }
7854 BasePointers.push_back(BP.getPointer());
7855 Pointers.push_back(LB.getPointer());
7856 Size = CGF.Builder.CreatePtrDiff(
7857 CGF.EmitCastToVoidPtr(
7858 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
7859 CGF.EmitCastToVoidPtr(LB.getPointer()));
7860 Sizes.push_back(
7861 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
7862 Types.push_back(Flags);
7863 break;
7864 }
7865 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
7866 if (!IsMemberPointer) {
7867 BasePointers.push_back(BP.getPointer());
7868 Pointers.push_back(LB.getPointer());
7869 Sizes.push_back(
7870 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
7871
7872 // We need to add a pointer flag for each map that comes from the
7873 // same expression except for the first one. We also need to signal
7874 // this map is the first one that relates with the current capture
7875 // (there is a set of entries for each capture).
7876 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
7877 MapType, MapModifiers, IsImplicit,
7878 !IsExpressionFirstInfo || RequiresReference,
7879 IsCaptureFirstInfo && !RequiresReference);
7880
7881 if (!IsExpressionFirstInfo) {
7882 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
7883 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
7884 if (IsPointer)
7885 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
7886 OMP_MAP_DELETE | OMP_MAP_CLOSE);
7887
7888 if (ShouldBeMemberOf) {
7889 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7890 // should be later updated with the correct value of MEMBER_OF.
7891 Flags |= OMP_MAP_MEMBER_OF;
7892 // From now on, all subsequent PTR_AND_OBJ entries should not be
7893 // marked as MEMBER_OF.
7894 ShouldBeMemberOf = false;
7895 }
7896 }
7897
7898 Types.push_back(Flags);
7899 }
7900
7901 // If we have encountered a member expression so far, keep track of the
7902 // mapped member. If the parent is "*this", then the value declaration
7903 // is nullptr.
7904 if (EncounteredME) {
7905 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl());
7906 unsigned FieldIndex = FD->getFieldIndex();
7907
7908 // Update info about the lowest and highest elements for this struct
7909 if (!PartialStruct.Base.isValid()) {
7910 PartialStruct.LowestElem = {FieldIndex, LB};
7911 PartialStruct.HighestElem = {FieldIndex, LB};
7912 PartialStruct.Base = BP;
7913 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7914 PartialStruct.LowestElem = {FieldIndex, LB};
7915 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7916 PartialStruct.HighestElem = {FieldIndex, LB};
7917 }
7918 }
7919
7920 // If we have a final array section, we are done with this expression.
7921 if (IsFinalArraySection)
7922 break;
7923
7924 // The pointer becomes the base for the next element.
7925 if (Next != CE)
7926 BP = LB;
7927
7928 IsExpressionFirstInfo = false;
7929 IsCaptureFirstInfo = false;
7930 }
7931 }
7932 }
7933
7934 /// Return the adjusted map modifiers if the declaration a capture refers to
7935 /// appears in a first-private clause. This is expected to be used only with
7936 /// directives that start with 'target'.
7937 MappableExprsHandler::OpenMPOffloadMappingFlags
7938 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7939 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7939, __PRETTY_FUNCTION__))
;
7940
7941 // A first private variable captured by reference will use only the
7942 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7943 // declaration is known as first-private in this handler.
7944 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7945 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7946 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7947 return MappableExprsHandler::OMP_MAP_ALWAYS |
7948 MappableExprsHandler::OMP_MAP_TO;
7949 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7950 return MappableExprsHandler::OMP_MAP_TO |
7951 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
7952 return MappableExprsHandler::OMP_MAP_PRIVATE |
7953 MappableExprsHandler::OMP_MAP_TO;
7954 }
7955 return MappableExprsHandler::OMP_MAP_TO |
7956 MappableExprsHandler::OMP_MAP_FROM;
7957 }
7958
7959 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
7960 // Rotate by getFlagMemberOffset() bits.
7961 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
7962 << getFlagMemberOffset());
7963 }
7964
7965 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7966 OpenMPOffloadMappingFlags MemberOfFlag) {
7967 // If the entry is PTR_AND_OBJ but has not been marked with the special
7968 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7969 // marked as MEMBER_OF.
7970 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7971 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7972 return;
7973
7974 // Reset the placeholder value to prepare the flag for the assignment of the
7975 // proper MEMBER_OF value.
7976 Flags &= ~OMP_MAP_MEMBER_OF;
7977 Flags |= MemberOfFlag;
7978 }
7979
7980 void getPlainLayout(const CXXRecordDecl *RD,
7981 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7982 bool AsBase) const {
7983 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7984
7985 llvm::StructType *St =
7986 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7987
7988 unsigned NumElements = St->getNumElements();
7989 llvm::SmallVector<
7990 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7991 RecordLayout(NumElements);
7992
7993 // Fill bases.
7994 for (const auto &I : RD->bases()) {
7995 if (I.isVirtual())
7996 continue;
7997 const auto *Base = I.getType()->getAsCXXRecordDecl();
7998 // Ignore empty bases.
7999 if (Base->isEmpty() || CGF.getContext()
8000 .getASTRecordLayout(Base)
8001 .getNonVirtualSize()
8002 .isZero())
8003 continue;
8004
8005 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
8006 RecordLayout[FieldIndex] = Base;
8007 }
8008 // Fill in virtual bases.
8009 for (const auto &I : RD->vbases()) {
8010 const auto *Base = I.getType()->getAsCXXRecordDecl();
8011 // Ignore empty bases.
8012 if (Base->isEmpty())
8013 continue;
8014 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
8015 if (RecordLayout[FieldIndex])
8016 continue;
8017 RecordLayout[FieldIndex] = Base;
8018 }
8019 // Fill in all the fields.
8020 assert(!RD->isUnion() && "Unexpected union.")((!RD->isUnion() && "Unexpected union.") ? static_cast
<void> (0) : __assert_fail ("!RD->isUnion() && \"Unexpected union.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8020, __PRETTY_FUNCTION__))
;
8021 for (const auto *Field : RD->fields()) {
8022 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
8023 // will fill in later.)
8024 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
8025 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
8026 RecordLayout[FieldIndex] = Field;
8027 }
8028 }
8029 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8030 &Data : RecordLayout) {
8031 if (Data.isNull())
8032 continue;
8033 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
8034 getPlainLayout(Base, Layout, /*AsBase=*/true);
8035 else
8036 Layout.push_back(Data.get<const FieldDecl *>());
8037 }
8038 }
8039
8040public:
8041 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
8042 : CurDir(&Dir), CGF(CGF) {
8043 // Extract firstprivate clause information.
8044 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
8045 for (const auto *D : C->varlists())
8046 FirstPrivateDecls.try_emplace(
8047 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
8048 // Extract device pointer clause information.
8049 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
8050 for (auto L : C->component_lists())
8051 DevPointersMap[L.first].push_back(L.second);
8052 }
8053
8054 /// Constructor for the declare mapper directive.
8055 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
8056 : CurDir(&Dir), CGF(CGF) {}
8057
8058 /// Generate code for the combined entry if we have a partially mapped struct
8059 /// and take care of the mapping flags of the arguments corresponding to
8060 /// individual struct members.
8061 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
8062 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8063 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
8064 const StructRangeInfoTy &PartialStruct) const {
8065 // Base is the base of the struct
8066 BasePointers.push_back(PartialStruct.Base.getPointer());
8067 // Pointer is the address of the lowest element
8068 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
8069 Pointers.push_back(LB);
8070 // Size is (addr of {highest+1} element) - (addr of lowest element)
8071 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
8072 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
8073 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
8074 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
8075 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
8076 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
8077 /*isSigned=*/false);
8078 Sizes.push_back(Size);
8079 // Map type is always TARGET_PARAM
8080 Types.push_back(OMP_MAP_TARGET_PARAM);
8081 // Remove TARGET_PARAM flag from the first element
8082 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
8083
8084 // All other current entries will be MEMBER_OF the combined entry
8085 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8086 // 0xFFFF in the MEMBER_OF field).
8087 OpenMPOffloadMappingFlags MemberOfFlag =
8088 getMemberOfFlag(BasePointers.size() - 1);
8089 for (auto &M : CurTypes)
8090 setCorrectMemberOfFlag(M, MemberOfFlag);
8091 }
8092
8093 /// Generate all the base pointers, section pointers, sizes and map
8094 /// types for the extracted mappable expressions. Also, for each item that
8095 /// relates with a device pointer, a pair of the relevant declaration and
8096 /// index where it occurs is appended to the device pointers info array.
8097 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
8098 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8099 MapFlagsArrayTy &Types) const {
8100 // We have to process the component lists that relate with the same
8101 // declaration in a single chunk so that we can generate the map flags
8102 // correctly. Therefore, we organize all lists in a map.
8103 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8104
8105 // Helper function to fill the information map for the different supported
8106 // clauses.
8107 auto &&InfoGen = [&Info](
8108 const ValueDecl *D,
8109 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8110 OpenMPMapClauseKind MapType,
8111 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8112 bool ReturnDevicePointer, bool IsImplicit) {
8113 const ValueDecl *VD =
8114 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8115 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8116 IsImplicit);
8117 };
8118
8119 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8120, __PRETTY_FUNCTION__))
8120 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8120, __PRETTY_FUNCTION__))
;
8121 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8122 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
8123 for (const auto L : C->component_lists()) {
8124 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
8125 /*ReturnDevicePointer=*/false, C->isImplicit());
8126 }
8127 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
8128 for (const auto L : C->component_lists()) {
8129 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
8130 /*ReturnDevicePointer=*/false, C->isImplicit());
8131 }
8132 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
8133 for (const auto L : C->component_lists()) {
8134 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
8135 /*ReturnDevicePointer=*/false, C->isImplicit());
8136 }
8137
8138 // Look at the use_device_ptr clause information and mark the existing map
8139 // entries as such. If there is no map information for an entry in the
8140 // use_device_ptr list, we create one with map type 'alloc' and zero size
8141 // section. It is the user fault if that was not mapped before. If there is
8142 // no map information and the pointer is a struct member, then we defer the
8143 // emission of that entry until the whole struct has been processed.
8144 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
8145 DeferredInfo;
8146
8147 for (const auto *C :
8148 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
8149 for (const auto L : C->component_lists()) {
8150 assert(!L.second.empty() && "Not expecting empty list of components!")((!L.second.empty() && "Not expecting empty list of components!"
) ? static_cast<void> (0) : __assert_fail ("!L.second.empty() && \"Not expecting empty list of components!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8150, __PRETTY_FUNCTION__))
;
8151 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
8152 VD = cast<ValueDecl>(VD->getCanonicalDecl());
8153 const Expr *IE = L.second.back().getAssociatedExpression();
8154 // If the first component is a member expression, we have to look into
8155 // 'this', which maps to null in the map of map information. Otherwise
8156 // look directly for the information.
8157 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8158
8159 // We potentially have map information for this declaration already.
8160 // Look for the first set of components that refer to it.
8161 if (It != Info.end()) {
8162 auto CI = std::find_if(
8163 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
8164 return MI.Components.back().getAssociatedDeclaration() == VD;
8165 });
8166 // If we found a map entry, signal that the pointer has to be returned
8167 // and move on to the next declaration.
8168 if (CI != It->second.end()) {
8169 CI->ReturnDevicePointer = true;
8170 continue;
8171 }
8172 }
8173
8174 // We didn't find any match in our map information - generate a zero
8175 // size array section - if the pointer is a struct member we defer this
8176 // action until the whole struct has been processed.
8177 if (isa<MemberExpr>(IE)) {
8178 // Insert the pointer into Info to be processed by
8179 // generateInfoForComponentList. Because it is a member pointer
8180 // without a pointee, no entry will be generated for it, therefore
8181 // we need to generate one after the whole struct has been processed.
8182 // Nonetheless, generateInfoForComponentList must be called to take
8183 // the pointer into account for the calculation of the range of the
8184 // partial struct.
8185 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
8186 /*ReturnDevicePointer=*/false, C->isImplicit());
8187 DeferredInfo[nullptr].emplace_back(IE, VD);
8188 } else {
8189 llvm::Value *Ptr =
8190 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
8191 BasePointers.emplace_back(Ptr, VD);
8192 Pointers.push_back(Ptr);
8193 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
8194 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8195 }
8196 }
8197 }
8198
8199 for (const auto &M : Info) {
8200 // We need to know when we generate information for the first component
8201 // associated with a capture, because the mapping flags depend on it.
8202 bool IsFirstComponentList = true;
8203
8204 // Temporary versions of arrays
8205 MapBaseValuesArrayTy CurBasePointers;
8206 MapValuesArrayTy CurPointers;
8207 MapValuesArrayTy CurSizes;
8208 MapFlagsArrayTy CurTypes;
8209 StructRangeInfoTy PartialStruct;
8210
8211 for (const MapInfo &L : M.second) {
8212 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8213, __PRETTY_FUNCTION__))
8213 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8213, __PRETTY_FUNCTION__))
;
8214
8215 // Remember the current base pointer index.
8216 unsigned CurrentBasePointersIdx = CurBasePointers.size();
8217 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8218 CurBasePointers, CurPointers, CurSizes,
8219 CurTypes, PartialStruct,
8220 IsFirstComponentList, L.IsImplicit);
8221
8222 // If this entry relates with a device pointer, set the relevant
8223 // declaration and add the 'return pointer' flag.
8224 if (L.ReturnDevicePointer) {
8225 assert(CurBasePointers.size() > CurrentBasePointersIdx &&((CurBasePointers.size() > CurrentBasePointersIdx &&
"Unexpected number of mapped base pointers.") ? static_cast<
void> (0) : __assert_fail ("CurBasePointers.size() > CurrentBasePointersIdx && \"Unexpected number of mapped base pointers.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8226, __PRETTY_FUNCTION__))
8226 "Unexpected number of mapped base pointers.")((CurBasePointers.size() > CurrentBasePointersIdx &&
"Unexpected number of mapped base pointers.") ? static_cast<
void> (0) : __assert_fail ("CurBasePointers.size() > CurrentBasePointersIdx && \"Unexpected number of mapped base pointers.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8226, __PRETTY_FUNCTION__))
;
8227
8228 const ValueDecl *RelevantVD =
8229 L.Components.back().getAssociatedDeclaration();
8230 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8231, __PRETTY_FUNCTION__))
8231 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8231, __PRETTY_FUNCTION__))
;
8232
8233 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8234 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
8235 }
8236 IsFirstComponentList = false;
8237 }
8238
8239 // Append any pending zero-length pointers which are struct members and
8240 // used with use_device_ptr.
8241 auto CI = DeferredInfo.find(M.first);
8242 if (CI != DeferredInfo.end()) {
8243 for (const DeferredDevicePtrEntryTy &L : CI->second) {
8244 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
8245 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8246 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8247 CurBasePointers.emplace_back(BasePtr, L.VD);
8248 CurPointers.push_back(Ptr);
8249 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
8250 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8251 // value MEMBER_OF=FFFF so that the entry is later updated with the
8252 // correct value of MEMBER_OF.
8253 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8254 OMP_MAP_MEMBER_OF);
8255 }
8256 }
8257
8258 // If there is an entry in PartialStruct it means we have a struct with
8259 // individual members mapped. Emit an extra combined entry.
8260 if (PartialStruct.Base.isValid())
8261 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8262 PartialStruct);
8263
8264 // We need to append the results of this capture to what we already have.
8265 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8266 Pointers.append(CurPointers.begin(), CurPointers.end());
8267 Sizes.append(CurSizes.begin(), CurSizes.end());
8268 Types.append(CurTypes.begin(), CurTypes.end());
8269 }
8270 }
8271
8272 /// Generate all the base pointers, section pointers, sizes and map types for
8273 /// the extracted map clauses of user-defined mapper.
8274 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8275 MapValuesArrayTy &Pointers,
8276 MapValuesArrayTy &Sizes,
8277 MapFlagsArrayTy &Types) const {
8278 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8279, __PRETTY_FUNCTION__))
8279 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8279, __PRETTY_FUNCTION__))
;
8280 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8281 // We have to process the component lists that relate with the same
8282 // declaration in a single chunk so that we can generate the map flags
8283 // correctly. Therefore, we organize all lists in a map.
8284 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8285
8286 // Helper function to fill the information map for the different supported
8287 // clauses.
8288 auto &&InfoGen = [&Info](
8289 const ValueDecl *D,
8290 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8291 OpenMPMapClauseKind MapType,
8292 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8293 bool ReturnDevicePointer, bool IsImplicit) {
8294 const ValueDecl *VD =
8295 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8296 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8297 IsImplicit);
8298 };
8299
8300 for (const auto *C : CurMapperDir->clauselists()) {
8301 const auto *MC = cast<OMPMapClause>(C);
8302 for (const auto L : MC->component_lists()) {
8303 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8304 /*ReturnDevicePointer=*/false, MC->isImplicit());
8305 }
8306 }
8307
8308 for (const auto &M : Info) {
8309 // We need to know when we generate information for the first component
8310 // associated with a capture, because the mapping flags depend on it.
8311 bool IsFirstComponentList = true;
8312
8313 // Temporary versions of arrays
8314 MapBaseValuesArrayTy CurBasePointers;
8315 MapValuesArrayTy CurPointers;
8316 MapValuesArrayTy CurSizes;
8317 MapFlagsArrayTy CurTypes;
8318 StructRangeInfoTy PartialStruct;
8319
8320 for (const MapInfo &L : M.second) {
8321 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8322, __PRETTY_FUNCTION__))
8322 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8322, __PRETTY_FUNCTION__))
;
8323 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8324 CurBasePointers, CurPointers, CurSizes,
8325 CurTypes, PartialStruct,
8326 IsFirstComponentList, L.IsImplicit);
8327 IsFirstComponentList = false;
8328 }
8329
8330 // If there is an entry in PartialStruct it means we have a struct with
8331 // individual members mapped. Emit an extra combined entry.
8332 if (PartialStruct.Base.isValid())
8333 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8334 PartialStruct);
8335
8336 // We need to append the results of this capture to what we already have.
8337 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8338 Pointers.append(CurPointers.begin(), CurPointers.end());
8339 Sizes.append(CurSizes.begin(), CurSizes.end());
8340 Types.append(CurTypes.begin(), CurTypes.end());
8341 }
8342 }
8343
8344 /// Emit capture info for lambdas for variables captured by reference.
8345 void generateInfoForLambdaCaptures(
8346 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8347 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8348 MapFlagsArrayTy &Types,
8349 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
8350 const auto *RD = VD->getType()
8351 .getCanonicalType()
8352 .getNonReferenceType()
8353 ->getAsCXXRecordDecl();
8354 if (!RD || !RD->isLambda())
8355 return;
8356 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8357 LValue VDLVal = CGF.MakeAddrLValue(
8358 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8359 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8360 FieldDecl *ThisCapture = nullptr;
8361 RD->getCaptureFields(Captures, ThisCapture);
8362 if (ThisCapture) {
8363 LValue ThisLVal =
8364 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
8365 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
8366 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
8367 VDLVal.getPointer(CGF));
8368 BasePointers.push_back(ThisLVal.getPointer(CGF));
8369 Pointers.push_back(ThisLValVal.getPointer(CGF));
8370 Sizes.push_back(
8371 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8372 CGF.Int64Ty, /*isSigned=*/true));
8373 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
8374 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8375 }
8376 for (const LambdaCapture &LC : RD->captures()) {
8377 if (!LC.capturesVariable())
8378 continue;
8379 const VarDecl *VD = LC.getCapturedVar();
8380 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8381 continue;
8382 auto It = Captures.find(VD);
8383 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8383, __PRETTY_FUNCTION__))
;
8384 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
8385 if (LC.getCaptureKind() == LCK_ByRef) {
8386 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8387 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8388 VDLVal.getPointer(CGF));
8389 BasePointers.push_back(VarLVal.getPointer(CGF));
8390 Pointers.push_back(VarLValVal.getPointer(CGF));
8391 Sizes.push_back(CGF.Builder.CreateIntCast(
8392 CGF.getTypeSize(
8393 VD->getType().getCanonicalType().getNonReferenceType()),
8394 CGF.Int64Ty, /*isSigned=*/true));
8395 } else {
8396 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
8397 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8398 VDLVal.getPointer(CGF));
8399 BasePointers.push_back(VarLVal.getPointer(CGF));
8400 Pointers.push_back(VarRVal.getScalarVal());
8401 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8402 }
8403 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
8404 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8405 }
8406 }
8407
8408 /// Set correct indices for lambdas captures.
8409 void adjustMemberOfForLambdaCaptures(
8410 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8411 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8412 MapFlagsArrayTy &Types) const {
8413 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8414 // Set correct member_of idx for all implicit lambda captures.
8415 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
8416 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8417 continue;
8418 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8419 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8419, __PRETTY_FUNCTION__))
;
8420 int TgtIdx = -1;
8421 for (unsigned J = I; J > 0; --J) {
8422 unsigned Idx = J - 1;
8423 if (Pointers[Idx] != BasePtr)
8424 continue;
8425 TgtIdx = Idx;
8426 break;
8427 }
8428 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8428, __PRETTY_FUNCTION__))
;
8429 // All other current entries will be MEMBER_OF the combined entry
8430 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8431 // 0xFFFF in the MEMBER_OF field).
8432 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8433 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8434 }
8435 }
8436
8437 /// Generate the base pointers, section pointers, sizes and map types
8438 /// associated to a given capture.
8439 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
8440 llvm::Value *Arg,
8441 MapBaseValuesArrayTy &BasePointers,
8442 MapValuesArrayTy &Pointers,
8443 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8444 StructRangeInfoTy &PartialStruct) const {
8445 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8446, __PRETTY_FUNCTION__))
8446 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8446, __PRETTY_FUNCTION__))
;
8447
8448 // We need to know when we generating information for the first component
8449 const ValueDecl *VD = Cap->capturesThis()
8450 ? nullptr
8451 : Cap->getCapturedVar()->getCanonicalDecl();
8452
8453 // If this declaration appears in a is_device_ptr clause we just have to
8454 // pass the pointer by value. If it is a reference to a declaration, we just
8455 // pass its value.
8456 if (DevPointersMap.count(VD)) {
8457 BasePointers.emplace_back(Arg, VD);
8458 Pointers.push_back(Arg);
8459 Sizes.push_back(
8460 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8461 CGF.Int64Ty, /*isSigned=*/true));
8462 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
8463 return;
8464 }
8465
8466 using MapData =
8467 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
8468 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
8469 SmallVector<MapData, 4> DeclComponentLists;
8470 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8471, __PRETTY_FUNCTION__))
8471 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8471, __PRETTY_FUNCTION__))
;
8472 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8473 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
8474 for (const auto L : C->decl_component_lists(VD)) {
8475 assert(L.first == VD &&((L.first == VD && "We got information for the wrong declaration??"
) ? static_cast<void> (0) : __assert_fail ("L.first == VD && \"We got information for the wrong declaration??\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8476, __PRETTY_FUNCTION__))
8476 "We got information for the wrong declaration??")((L.first == VD && "We got information for the wrong declaration??"
) ? static_cast<void> (0) : __assert_fail ("L.first == VD && \"We got information for the wrong declaration??\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8476, __PRETTY_FUNCTION__))
;
8477 assert(!L.second.empty() &&((!L.second.empty() && "Not expecting declaration with no component lists."
) ? static_cast<void> (0) : __assert_fail ("!L.second.empty() && \"Not expecting declaration with no component lists.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8478, __PRETTY_FUNCTION__))
8478 "Not expecting declaration with no component lists.")((!L.second.empty() && "Not expecting declaration with no component lists."
) ? static_cast<void> (0) : __assert_fail ("!L.second.empty() && \"Not expecting declaration with no component lists.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8478, __PRETTY_FUNCTION__))
;
8479 DeclComponentLists.emplace_back(L.second, C->getMapType(),
8480 C->getMapTypeModifiers(),
8481 C->isImplicit());
8482 }
8483 }
8484
8485 // Find overlapping elements (including the offset from the base element).
8486 llvm::SmallDenseMap<
8487 const MapData *,
8488 llvm::SmallVector<
8489 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8490 4>
8491 OverlappedData;
8492 size_t Count = 0;
8493 for (const MapData &L : DeclComponentLists) {
8494 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8495 OpenMPMapClauseKind MapType;
8496 ArrayRef<OpenMPMapModifierKind> MapModifiers;
8497 bool IsImplicit;
8498 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
8499 ++Count;
8500 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8501 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
8502 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
8503 auto CI = Components.rbegin();
8504 auto CE = Components.rend();
8505 auto SI = Components1.rbegin();
8506 auto SE = Components1.rend();
8507 for (; CI != CE && SI != SE; ++CI, ++SI) {
8508 if (CI->getAssociatedExpression()->getStmtClass() !=
8509 SI->getAssociatedExpression()->getStmtClass())
8510 break;
8511 // Are we dealing with different variables/fields?
8512 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8513 break;
8514 }
8515 // Found overlapping if, at least for one component, reached the head of
8516 // the components list.
8517 if (CI == CE || SI == SE) {
8518 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8519, __PRETTY_FUNCTION__))
8519 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8519, __PRETTY_FUNCTION__))
;
8520 const MapData &BaseData = CI == CE ? L : L1;
8521 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8522 SI == SE ? Components : Components1;
8523 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8524 OverlappedElements.getSecond().push_back(SubData);
8525 }
8526 }
8527 }
8528 // Sort the overlapped elements for each item.
8529 llvm::SmallVector<const FieldDecl *, 4> Layout;
8530 if (!OverlappedData.empty()) {
8531 if (const auto *CRD =
8532 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8533 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8534 else {
8535 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8536 Layout.append(RD->field_begin(), RD->field_end());
8537 }
8538 }
8539 for (auto &Pair : OverlappedData) {
8540 llvm::sort(
8541 Pair.getSecond(),
8542 [&Layout](
8543 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8544 OMPClauseMappableExprCommon::MappableExprComponentListRef
8545 Second) {
8546 auto CI = First.rbegin();
8547 auto CE = First.rend();
8548 auto SI = Second.rbegin();
8549 auto SE = Second.rend();
8550 for (; CI != CE && SI != SE; ++CI, ++SI) {
8551 if (CI->getAssociatedExpression()->getStmtClass() !=
8552 SI->getAssociatedExpression()->getStmtClass())
8553 break;
8554 // Are we dealing with different variables/fields?
8555 if (CI->getAssociatedDeclaration() !=
8556 SI->getAssociatedDeclaration())
8557 break;
8558 }
8559
8560 // Lists contain the same elements.
8561 if (CI == CE && SI == SE)
8562 return false;
8563
8564 // List with less elements is less than list with more elements.
8565 if (CI == CE || SI == SE)
8566 return CI == CE;
8567
8568 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8569 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8570 if (FD1->getParent() == FD2->getParent())
8571 return FD1->getFieldIndex() < FD2->getFieldIndex();
8572 const auto It =
8573 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8574 return FD == FD1 || FD == FD2;
8575 });
8576 return *It == FD1;
8577 });
8578 }
8579
8580 // Associated with a capture, because the mapping flags depend on it.
8581 // Go through all of the elements with the overlapped elements.
8582 for (const auto &Pair : OverlappedData) {
8583 const MapData &L = *Pair.getFirst();
8584 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8585 OpenMPMapClauseKind MapType;
8586 ArrayRef<OpenMPMapModifierKind> MapModifiers;
8587 bool IsImplicit;
8588 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
8589 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8590 OverlappedComponents = Pair.getSecond();
8591 bool IsFirstComponentList = true;
8592 generateInfoForComponentList(MapType, MapModifiers, Components,
8593 BasePointers, Pointers, Sizes, Types,
8594 PartialStruct, IsFirstComponentList,
8595 IsImplicit, OverlappedComponents);
8596 }
8597 // Go through other elements without overlapped elements.
8598 bool IsFirstComponentList = OverlappedData.empty();
8599 for (const MapData &L : DeclComponentLists) {
8600 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8601 OpenMPMapClauseKind MapType;
8602 ArrayRef<OpenMPMapModifierKind> MapModifiers;
8603 bool IsImplicit;
8604 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
8605 auto It = OverlappedData.find(&L);
8606 if (It == OverlappedData.end())
8607 generateInfoForComponentList(MapType, MapModifiers, Components,
8608 BasePointers, Pointers, Sizes, Types,
8609 PartialStruct, IsFirstComponentList,
8610 IsImplicit);
8611 IsFirstComponentList = false;
8612 }
8613 }
8614
8615 /// Generate the base pointers, section pointers, sizes and map types
8616 /// associated with the declare target link variables.
8617 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8618 MapValuesArrayTy &Pointers,
8619 MapValuesArrayTy &Sizes,
8620 MapFlagsArrayTy &Types) const {
8621 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8622, __PRETTY_FUNCTION__))
8622 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8622, __PRETTY_FUNCTION__))
;
8623 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8624 // Map other list items in the map clause which are not captured variables
8625 // but "declare target link" global variables.
8626 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
8627 for (const auto L : C->component_lists()) {
8628 if (!L.first)
8629 continue;
8630 const auto *VD = dyn_cast<VarDecl>(L.first);
8631 if (!VD)
8632 continue;
8633 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
8634 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
8635 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8636 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
8637 continue;
8638 StructRangeInfoTy PartialStruct;
8639 generateInfoForComponentList(
8640 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
8641 Pointers, Sizes, Types, PartialStruct,
8642 /*IsFirstComponentList=*/true, C->isImplicit());
8643 assert(!PartialStruct.Base.isValid() &&((!PartialStruct.Base.isValid() && "No partial structs for declare target link expected."
) ? static_cast<void> (0) : __assert_fail ("!PartialStruct.Base.isValid() && \"No partial structs for declare target link expected.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8644, __PRETTY_FUNCTION__))
8644 "No partial structs for declare target link expected.")((!PartialStruct.Base.isValid() && "No partial structs for declare target link expected."
) ? static_cast<void> (0) : __assert_fail ("!PartialStruct.Base.isValid() && \"No partial structs for declare target link expected.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8644, __PRETTY_FUNCTION__))
;
8645 }
8646 }
8647 }
8648
8649 /// Generate the default map information for a given capture \a CI,
8650 /// record field declaration \a RI and captured value \a CV.
8651 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8652 const FieldDecl &RI, llvm::Value *CV,
8653 MapBaseValuesArrayTy &CurBasePointers,
8654 MapValuesArrayTy &CurPointers,
8655 MapValuesArrayTy &CurSizes,
8656 MapFlagsArrayTy &CurMapTypes) const {
8657 bool IsImplicit = true;
8658 // Do the default mapping.
8659 if (CI.capturesThis()) {
8660 CurBasePointers.push_back(CV);
8661 CurPointers.push_back(CV);
8662 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
8663 CurSizes.push_back(
8664 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8665 CGF.Int64Ty, /*isSigned=*/true));
8666 // Default map type.
8667 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
8668 } else if (CI.capturesVariableByCopy()) {
8669 CurBasePointers.push_back(CV);
8670 CurPointers.push_back(CV);
8671 if (!RI.getType()->isAnyPointerType()) {
8672 // We have to signal to the runtime captures passed by value that are
8673 // not pointers.
8674 CurMapTypes.push_back(OMP_MAP_LITERAL);
8675 CurSizes.push_back(CGF.Builder.CreateIntCast(
8676 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
8677 } else {
8678 // Pointers are implicitly mapped with a zero size and no flags
8679 // (other than first map that is added for all implicit maps).
8680 CurMapTypes.push_back(OMP_MAP_NONE);
8681 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
8682 }
8683 const VarDecl *VD = CI.getCapturedVar();
8684 auto I = FirstPrivateDecls.find(VD);
8685 if (I != FirstPrivateDecls.end())
8686 IsImplicit = I->getSecond();
8687 } else {
8688 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8688, __PRETTY_FUNCTION__))
;
8689 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
8690 QualType ElementType = PtrTy->getPointeeType();
8691 CurSizes.push_back(CGF.Builder.CreateIntCast(
8692 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
8693 // The default map type for a scalar/complex type is 'to' because by
8694 // default the value doesn't have to be retrieved. For an aggregate
8695 // type, the default is 'tofrom'.
8696 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
8697 const VarDecl *VD = CI.getCapturedVar();
8698 auto I = FirstPrivateDecls.find(VD);
8699 if (I != FirstPrivateDecls.end() &&
8700 VD->getType().isConstant(CGF.getContext())) {
8701 llvm::Constant *Addr =
8702 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8703 // Copy the value of the original variable to the new global copy.
8704 CGF.Builder.CreateMemCpy(
8705 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF),
8706 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
8707 CurSizes.back(), /*IsVolatile=*/false);
8708 // Use new global variable as the base pointers.
8709 CurBasePointers.push_back(Addr);
8710 CurPointers.push_back(Addr);
8711 } else {
8712 CurBasePointers.push_back(CV);
8713 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
8714 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8715 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8716 AlignmentSource::Decl));
8717 CurPointers.push_back(PtrAddr.getPointer());
8718 } else {
8719 CurPointers.push_back(CV);
8720 }
8721 }
8722 if (I != FirstPrivateDecls.end())
8723 IsImplicit = I->getSecond();
8724 }
8725 // Every default map produces a single argument which is a target parameter.
8726 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
8727
8728 // Add flag stating this is an implicit map.
8729 if (IsImplicit)
8730 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
8731 }
8732};
8733} // anonymous namespace
8734
8735/// Emit the arrays used to pass the captures and map information to the
8736/// offloading runtime library. If there is no map or capture information,
8737/// return nullptr by reference.
8738static void
8739emitOffloadingArrays(CodeGenFunction &CGF,
8740 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
8741 MappableExprsHandler::MapValuesArrayTy &Pointers,
8742 MappableExprsHandler::MapValuesArrayTy &Sizes,
8743 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8744 CGOpenMPRuntime::TargetDataInfo &Info) {
8745 CodeGenModule &CGM = CGF.CGM;
8746 ASTContext &Ctx = CGF.getContext();
8747
8748 // Reset the array information.
8749 Info.clearArrayInfo();
8750 Info.NumberOfPtrs = BasePointers.size();
8751
8752 if (Info.NumberOfPtrs) {
8753 // Detect if we have any capture size requiring runtime evaluation of the
8754 // size so that a constant array could be eventually used.
8755 bool hasRuntimeEvaluationCaptureSize = false;
8756 for (llvm::Value *S : Sizes)
8757 if (!isa<llvm::Constant>(S)) {
8758 hasRuntimeEvaluationCaptureSize = true;
8759 break;
8760 }
8761
8762 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
8763 QualType PointerArrayType = Ctx.getConstantArrayType(
8764 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
8765 /*IndexTypeQuals=*/0);
8766
8767 Info.BasePointersArray =
8768 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
8769 Info.PointersArray =
8770 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8771
8772 // If we don't have any VLA types or other types that require runtime
8773 // evaluation, we can use a constant array for the map sizes, otherwise we
8774 // need to fill up the arrays as we do for the pointers.
8775 QualType Int64Ty =
8776 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
8777 if (hasRuntimeEvaluationCaptureSize) {
8778 QualType SizeArrayType = Ctx.getConstantArrayType(
8779 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
8780 /*IndexTypeQuals=*/0);
8781 Info.SizesArray =
8782 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8783 } else {
8784 // We expect all the sizes to be constant, so we collect them to create
8785 // a constant array.
8786 SmallVector<llvm::Constant *, 16> ConstSizes;
8787 for (llvm::Value *S : Sizes)
8788 ConstSizes.push_back(cast<llvm::Constant>(S));
8789
8790 auto *SizesArrayInit = llvm::ConstantArray::get(
8791 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
8792 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
8793 auto *SizesArrayGbl = new llvm::GlobalVariable(
8794 CGM.getModule(), SizesArrayInit->getType(),
8795 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
8796 SizesArrayInit, Name);
8797 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
8798 Info.SizesArray = SizesArrayGbl;
8799 }
8800
8801 // The map types are always constant so we don't need to generate code to
8802 // fill arrays. Instead, we create an array constant.
8803 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8804 llvm::copy(MapTypes, Mapping.begin());
8805 llvm::Constant *MapTypesArrayInit =
8806 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
8807 std::string MaptypesName =
8808 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
8809 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8810 CGM.getModule(), MapTypesArrayInit->getType(),
8811 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
8812 MapTypesArrayInit, MaptypesName);
8813 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
8814 Info.MapTypesArray = MapTypesArrayGbl;
8815
8816 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8817 llvm::Value *BPVal = *BasePointers[I];
8818 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
8819 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8820 Info.BasePointersArray, 0, I);
8821 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8822 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
8823 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8824 CGF.Builder.CreateStore(BPVal, BPAddr);
8825
8826 if (Info.requiresDevicePointerInfo())
8827 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
8828 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
8829
8830 llvm::Value *PVal = Pointers[I];
8831 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
8832 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8833 Info.PointersArray, 0, I);
8834 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8835 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
8836 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8837 CGF.Builder.CreateStore(PVal, PAddr);
8838
8839 if (hasRuntimeEvaluationCaptureSize) {
8840 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
8841 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
8842 Info.SizesArray,
8843 /*Idx0=*/0,
8844 /*Idx1=*/I);
8845 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
8846 CGF.Builder.CreateStore(
8847 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
8848 SAddr);
8849 }
8850 }
8851 }
8852}
8853
8854/// Emit the arguments to be passed to the runtime library based on the
8855/// arrays of pointers, sizes and map types.
8856static void emitOffloadingArraysArgument(
8857 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8858 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
8859 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
8860 CodeGenModule &CGM = CGF.CGM;
8861 if (Info.NumberOfPtrs) {
8862 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
8863 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8864 Info.BasePointersArray,
8865 /*Idx0=*/0, /*Idx1=*/0);
8866 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
8867 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8868 Info.PointersArray,
8869 /*Idx0=*/0,
8870 /*Idx1=*/0);
8871 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
8872 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
8873 /*Idx0=*/0, /*Idx1=*/0);
8874 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
8875 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
8876 Info.MapTypesArray,
8877 /*Idx0=*/0,
8878 /*Idx1=*/0);
8879 } else {
8880 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8881 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8882 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
8883 MapTypesArrayArg =
8884 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
8885 }
8886}
8887
8888/// Check for inner distribute directive.
8889static const OMPExecutableDirective *
8890getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8891 const auto *CS = D.getInnermostCapturedStmt();
8892 const auto *Body =
8893 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
8894 const Stmt *ChildStmt =
8895 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8896
8897 if (const auto *NestedDir =
8898 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
8899 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8900 switch (D.getDirectiveKind()) {
8901 case OMPD_target:
8902 if (isOpenMPDistributeDirective(DKind))
8903 return NestedDir;
8904 if (DKind == OMPD_teams) {
8905 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8906 /*IgnoreCaptured=*/true);
8907 if (!Body)
8908 return nullptr;
8909 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8910 if (const auto *NND =
8911 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
8912 DKind = NND->getDirectiveKind();
8913 if (isOpenMPDistributeDirective(DKind))
8914 return NND;
8915 }
8916 }
8917 return nullptr;
8918 case OMPD_target_teams:
8919 if (isOpenMPDistributeDirective(DKind))
8920 return NestedDir;
8921 return nullptr;
8922 case OMPD_target_parallel:
8923 case OMPD_target_simd:
8924 case OMPD_target_parallel_for:
8925 case OMPD_target_parallel_for_simd:
8926 return nullptr;
8927 case OMPD_target_teams_distribute:
8928 case OMPD_target_teams_distribute_simd:
8929 case OMPD_target_teams_distribute_parallel_for:
8930 case OMPD_target_teams_distribute_parallel_for_simd:
8931 case OMPD_parallel:
8932 case OMPD_for:
8933 case OMPD_parallel_for:
8934 case OMPD_parallel_master:
8935 case OMPD_parallel_sections:
8936 case OMPD_for_simd:
8937 case OMPD_parallel_for_simd:
8938 case OMPD_cancel:
8939 case OMPD_cancellation_point:
8940 case OMPD_ordered:
8941 case OMPD_threadprivate:
8942 case OMPD_allocate:
8943 case OMPD_task:
8944 case OMPD_simd:
8945 case OMPD_sections:
8946 case OMPD_section:
8947 case OMPD_single:
8948 case OMPD_master:
8949 case OMPD_critical:
8950 case OMPD_taskyield:
8951 case OMPD_barrier:
8952 case OMPD_taskwait:
8953 case OMPD_taskgroup:
8954 case OMPD_atomic:
8955 case OMPD_flush:
8956 case OMPD_depobj:
8957 case OMPD_teams:
8958 case OMPD_target_data:
8959 case OMPD_target_exit_data:
8960 case OMPD_target_enter_data:
8961 case OMPD_distribute:
8962 case OMPD_distribute_simd:
8963 case OMPD_distribute_parallel_for:
8964 case OMPD_distribute_parallel_for_simd:
8965 case OMPD_teams_distribute:
8966 case OMPD_teams_distribute_simd:
8967 case OMPD_teams_distribute_parallel_for:
8968 case OMPD_teams_distribute_parallel_for_simd:
8969 case OMPD_target_update:
8970 case OMPD_declare_simd:
8971 case OMPD_declare_variant:
8972 case OMPD_declare_target:
8973 case OMPD_end_declare_target:
8974 case OMPD_declare_reduction:
8975 case OMPD_declare_mapper:
8976 case OMPD_taskloop:
8977 case OMPD_taskloop_simd:
8978 case OMPD_master_taskloop:
8979 case OMPD_master_taskloop_simd:
8980 case OMPD_parallel_master_taskloop:
8981 case OMPD_parallel_master_taskloop_simd:
8982 case OMPD_requires:
8983 case OMPD_unknown:
8984 llvm_unreachable("Unexpected directive.")::llvm::llvm_unreachable_internal("Unexpected directive.", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8984)
;
8985 }
8986 }
8987
8988 return nullptr;
8989}
8990
8991/// Emit the user-defined mapper function. The code generation follows the
8992/// pattern in the example below.
8993/// \code
8994/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8995/// void *base, void *begin,
8996/// int64_t size, int64_t type) {
8997/// // Allocate space for an array section first.
8998/// if (size > 1 && !maptype.IsDelete)
8999/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
9000/// size*sizeof(Ty), clearToFrom(type));
9001/// // Map members.
9002/// for (unsigned i = 0; i < size; i++) {
9003/// // For each component specified by this mapper:
9004/// for (auto c : all_components) {
9005/// if (c.hasMapper())
9006/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
9007/// c.arg_type);
9008/// else
9009/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
9010/// c.arg_begin, c.arg_size, c.arg_type);
9011/// }
9012/// }
9013/// // Delete the array section.
9014/// if (size > 1 && maptype.IsDelete)
9015/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
9016/// size*sizeof(Ty), clearToFrom(type));
9017/// }
9018/// \endcode
9019void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
9020 CodeGenFunction *CGF) {
9021 if (UDMMap.count(D) > 0)
9022 return;
9023 ASTContext &C = CGM.getContext();
9024 QualType Ty = D->getType();
9025 QualType PtrTy = C.getPointerType(Ty).withRestrict();
9026 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
9027 auto *MapperVarDecl =
9028 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
9029 SourceLocation Loc = D->getLocation();
9030 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
9031
9032 // Prepare mapper function arguments and attributes.
9033 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
9034 C.VoidPtrTy, ImplicitParamDecl::Other);
9035 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
9036 ImplicitParamDecl::Other);
9037 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
9038 C.VoidPtrTy, ImplicitParamDecl::Other);
9039 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
9040 ImplicitParamDecl::Other);
9041 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
9042 ImplicitParamDecl::Other);
9043 FunctionArgList Args;
9044 Args.push_back(&HandleArg);
9045 Args.push_back(&BaseArg);
9046 Args.push_back(&BeginArg);
9047 Args.push_back(&SizeArg);
9048 Args.push_back(&TypeArg);
9049 const CGFunctionInfo &FnInfo =
9050 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
9051 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
9052 SmallString<64> TyStr;
9053 llvm::raw_svector_ostream Out(TyStr);
9054 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
9055 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
9056 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
9057 Name, &CGM.getModule());
9058 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
9059 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
9060 // Start the mapper function code generation.
9061 CodeGenFunction MapperCGF(CGM);
9062 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
9063 // Compute the starting and end addreses of array elements.
9064 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
9065 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
9066 C.getPointerType(Int64Ty), Loc);
9067 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
9068 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
9069 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
9070 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
9071 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
9072 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
9073 C.getPointerType(Int64Ty), Loc);
9074 // Prepare common arguments for array initiation and deletion.
9075 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
9076 MapperCGF.GetAddrOfLocalVar(&HandleArg),
9077 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9078 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
9079 MapperCGF.GetAddrOfLocalVar(&BaseArg),
9080 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9081 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
9082 MapperCGF.GetAddrOfLocalVar(&BeginArg),
9083 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9084
9085 // Emit array initiation if this is an array section and \p MapType indicates
9086 // that memory allocation is required.
9087 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
9088 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9089 ElementSize, HeadBB, /*IsInit=*/true);
9090
9091 // Emit a for loop to iterate through SizeArg of elements and map all of them.
9092
9093 // Emit the loop header block.
9094 MapperCGF.EmitBlock(HeadBB);
9095 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
9096 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
9097 // Evaluate whether the initial condition is satisfied.
9098 llvm::Value *IsEmpty =
9099 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
9100 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
9101 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
9102
9103 // Emit the loop body block.
9104 MapperCGF.EmitBlock(BodyBB);
9105 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
9106 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
9107 PtrPHI->addIncoming(PtrBegin, EntryBB);
9108 Address PtrCurrent =
9109 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
9110 .getAlignment()
9111 .alignmentOfArrayElement(ElementSize));
9112 // Privatize the declared variable of mapper to be the current array element.
9113 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
9114 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
9115 return MapperCGF
9116 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
9117 .getAddress(MapperCGF);
9118 });
9119 (void)Scope.Privatize();
9120
9121 // Get map clause information. Fill up the arrays with all mapped variables.
9122 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9123 MappableExprsHandler::MapValuesArrayTy Pointers;
9124 MappableExprsHandler::MapValuesArrayTy Sizes;
9125 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9126 MappableExprsHandler MEHandler(*D, MapperCGF);
9127 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
9128
9129 // Call the runtime API __tgt_mapper_num_components to get the number of
9130 // pre-existing components.
9131 llvm::Value *OffloadingArgs[] = {Handle};
9132 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
9133 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
9134 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
9135 PreviousSize,
9136 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
9137
9138 // Fill up the runtime mapper handle for all components.
9139 for (unsigned I = 0; I < BasePointers.size(); ++I) {
9140 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
9141 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9142 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
9143 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9144 llvm::Value *CurSizeArg = Sizes[I];
9145
9146 // Extract the MEMBER_OF field from the map type.
9147 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
9148 MapperCGF.EmitBlock(MemberBB);
9149 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
9150 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
9151 OriMapType,
9152 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
9153 llvm::BasicBlock *MemberCombineBB =
9154 MapperCGF.createBasicBlock("omp.member.combine");
9155 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
9156 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
9157 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
9158 // Add the number of pre-existing components to the MEMBER_OF field if it
9159 // is valid.
9160 MapperCGF.EmitBlock(MemberCombineBB);
9161 llvm::Value *CombinedMember =
9162 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
9163 // Do nothing if it is not a member of previous components.
9164 MapperCGF.EmitBlock(TypeBB);
9165 llvm::PHINode *MemberMapType =
9166 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
9167 MemberMapType->addIncoming(OriMapType, MemberBB);
9168 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
9169
9170 // Combine the map type inherited from user-defined mapper with that
9171 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
9172 // bits of the \a MapType, which is the input argument of the mapper
9173 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
9174 // bits of MemberMapType.
9175 // [OpenMP 5.0], 1.2.6. map-type decay.
9176 // | alloc | to | from | tofrom | release | delete
9177 // ----------------------------------------------------------
9178 // alloc | alloc | alloc | alloc | alloc | release | delete
9179 // to | alloc | to | alloc | to | release | delete
9180 // from | alloc | alloc | from | from | release | delete
9181 // tofrom | alloc | to | from | tofrom | release | delete
9182 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9183 MapType,
9184 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9185 MappableExprsHandler::OMP_MAP_FROM));
9186 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9187 llvm::BasicBlock *AllocElseBB =
9188 MapperCGF.createBasicBlock("omp.type.alloc.else");
9189 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9190 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9191 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9192 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9193 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9194 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9195 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9196 MapperCGF.EmitBlock(AllocBB);
9197 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9198 MemberMapType,
9199 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9200 MappableExprsHandler::OMP_MAP_FROM)));
9201 MapperCGF.Builder.CreateBr(EndBB);
9202 MapperCGF.EmitBlock(AllocElseBB);
9203 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9204 LeftToFrom,
9205 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9206 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9207 // In case of to, clear OMP_MAP_FROM.
9208 MapperCGF.EmitBlock(ToBB);
9209 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9210 MemberMapType,
9211 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9212 MapperCGF.Builder.CreateBr(EndBB);
9213 MapperCGF.EmitBlock(ToElseBB);
9214 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9215 LeftToFrom,
9216 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9217 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9218 // In case of from, clear OMP_MAP_TO.
9219 MapperCGF.EmitBlock(FromBB);
9220 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9221 MemberMapType,
9222 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9223 // In case of tofrom, do nothing.
9224 MapperCGF.EmitBlock(EndBB);
9225 llvm::PHINode *CurMapType =
9226 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9227 CurMapType->addIncoming(AllocMapType, AllocBB);
9228 CurMapType->addIncoming(ToMapType, ToBB);
9229 CurMapType->addIncoming(FromMapType, FromBB);
9230 CurMapType->addIncoming(MemberMapType, ToElseBB);
9231
9232 // TODO: call the corresponding mapper function if a user-defined mapper is
9233 // associated with this map clause.
9234 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9235 // data structure.
9236 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9237 CurSizeArg, CurMapType};
9238 MapperCGF.EmitRuntimeCall(
9239 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9240 OffloadingArgs);
9241 }
9242
9243 // Update the pointer to point to the next element that needs to be mapped,
9244 // and check whether we have mapped all elements.
9245 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9246 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9247 PtrPHI->addIncoming(PtrNext, BodyBB);
9248 llvm::Value *IsDone =
9249 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9250 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9251 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9252
9253 MapperCGF.EmitBlock(ExitBB);
9254 // Emit array deletion if this is an array section and \p MapType indicates
9255 // that deletion is required.
9256 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9257 ElementSize, DoneBB, /*IsInit=*/false);
9258
9259 // Emit the function exit block.
9260 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9261 MapperCGF.FinishFunction();
9262 UDMMap.try_emplace(D, Fn);
9263 if (CGF) {
9264 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9265 Decls.second.push_back(D);
9266 }
9267}
9268
9269/// Emit the array initialization or deletion portion for user-defined mapper
9270/// code generation. First, it evaluates whether an array section is mapped and
9271/// whether the \a MapType instructs to delete this section. If \a IsInit is
9272/// true, and \a MapType indicates to not delete this array, array
9273/// initialization code is generated. If \a IsInit is false, and \a MapType
9274/// indicates to not this array, array deletion code is generated.
9275void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9276 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9277 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9278 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9279 StringRef Prefix = IsInit ? ".init" : ".del";
9280
9281 // Evaluate if this is an array section.
9282 llvm::BasicBlock *IsDeleteBB =
9283 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"}));
9284 llvm::BasicBlock *BodyBB =
9285 MapperCGF.createBasicBlock(getName({"omp.array", Prefix}));
9286 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9287 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9288 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9289
9290 // Evaluate if we are going to delete this section.
9291 MapperCGF.EmitBlock(IsDeleteBB);
9292 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9293 MapType,
9294 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9295 llvm::Value *DeleteCond;
9296 if (IsInit) {
9297 DeleteCond = MapperCGF.Builder.CreateIsNull(
9298 DeleteBit, getName({"omp.array", Prefix, ".delete"}));
9299 } else {
9300 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9301 DeleteBit, getName({"omp.array", Prefix, ".delete"}));
9302 }
9303 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9304
9305 MapperCGF.EmitBlock(BodyBB);
9306 // Get the array size by multiplying element size and element number (i.e., \p
9307 // Size).
9308 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9309 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9310 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9311 // memory allocation/deletion purpose only.
9312 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9313 MapType,
9314 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9315 MappableExprsHandler::OMP_MAP_FROM)));
9316 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9317 // data structure.
9318 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9319 MapperCGF.EmitRuntimeCall(
9320 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9321}
9322
9323void CGOpenMPRuntime::emitTargetNumIterationsCall(
9324 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9325 llvm::Value *DeviceID,
9326 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9327 const OMPLoopDirective &D)>
9328 SizeEmitter) {
9329 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9330 const OMPExecutableDirective *TD = &D;
9331 // Get nested teams distribute kind directive, if any.
9332 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9333 TD = getNestedDistributeDirective(CGM.getContext(), D);
9334 if (!TD)
9335 return;
9336 const auto *LD = cast<OMPLoopDirective>(TD);
9337 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
9338 PrePostActionTy &) {
9339 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9340 llvm::Value *Args[] = {DeviceID, NumIterations};
9341 CGF.EmitRuntimeCall(
9342 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9343 }
9344 };
9345 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9346}
9347
9348void CGOpenMPRuntime::emitTargetCall(
9349 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9350 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9351 const Expr *Device,
9352 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9353 const OMPLoopDirective &D)>
9354 SizeEmitter) {
9355 if (!CGF.HaveInsertPoint())
9356 return;
9357
9358 assert(OutlinedFn && "Invalid outlined function!")((OutlinedFn && "Invalid outlined function!") ? static_cast
<void> (0) : __assert_fail ("OutlinedFn && \"Invalid outlined function!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9358, __PRETTY_FUNCTION__))
;
9359
9360 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9361 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
9362 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
9363 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9364 PrePostActionTy &) {
9365 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9366 };
9367 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
9368
9369 CodeGenFunction::OMPTargetDataInfo InputInfo;
9370 llvm::Value *MapTypesArray = nullptr;
9371 // Fill up the pointer arrays and transfer execution to the device.
9372 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
9373 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9374 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
9375 // On top of the arrays that were filled up, the target offloading call
9376 // takes as arguments the device id as well as the host pointer. The host
9377 // pointer is used by the runtime library to identify the current target
9378 // region, so it only has to be unique and not necessarily point to
9379 // anything. It could be the pointer to the outlined function that
9380 // implements the target region, but we aren't using that so that the
9381 // compiler doesn't need to keep that, and could therefore inline the host
9382 // function if proven worthwhile during optimization.
9383
9384 // From this point on, we need to have an ID of the target region defined.
9385 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9385, __PRETTY_FUNCTION__))
;
9386
9387 // Emit device ID if any.
9388 llvm::Value *DeviceID;
9389 if (Device) {
9390 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
9391 CGF.Int64Ty, /*isSigned=*/true);
9392 } else {
9393 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9394 }
9395
9396 // Emit the number of elements in the offloading arrays.
9397 llvm::Value *PointerNum =
9398 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
9399
9400 // Return value of the runtime offloading call.
9401 llvm::Value *Return;
9402
9403 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9404 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
9405
9406 // Emit tripcount for the target loop-based directive.
9407 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9408
9409 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
9410 // The target region is an outlined function launched by the runtime
9411 // via calls __tgt_target() or __tgt_target_teams().
9412 //
9413 // __tgt_target() launches a target region with one team and one thread,
9414 // executing a serial region. This master thread may in turn launch
9415 // more threads within its team upon encountering a parallel region,
9416 // however, no additional teams can be launched on the device.
9417 //
9418 // __tgt_target_teams() launches a target region with one or more teams,
9419 // each with one or more threads. This call is required for target
9420 // constructs such as:
9421 // 'target teams'
9422 // 'target' / 'teams'
9423 // 'target teams distribute parallel for'
9424 // 'target parallel'
9425 // and so on.
9426 //
9427 // Note that on the host and CPU targets, the runtime implementation of
9428 // these calls simply call the outlined function without forking threads.
9429 // The outlined functions themselves have runtime calls to
9430 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9431 // the compiler in emitTeamsCall() and emitParallelCall().
9432 //
9433 // In contrast, on the NVPTX target, the implementation of
9434 // __tgt_target_teams() launches a GPU kernel with the requested number
9435 // of teams and threads so no additional calls to the runtime are required.
9436 if (NumTeams) {
9437 // If we have NumTeams defined this means that we have an enclosed teams
9438 // region. Therefore we also expect to have NumThreads defined. These two
9439 // values should be defined in the presence of a teams directive,
9440 // regardless of having any clauses associated. If the user is using teams
9441 // but no clauses, these two values will be the default that should be
9442 // passed to the runtime library - a 32-bit integer with the value zero.
9443 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9444, __PRETTY_FUNCTION__))
9444 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9444, __PRETTY_FUNCTION__))
;
9445 llvm::Value *OffloadingArgs[] = {DeviceID,
9446 OutlinedFnID,
9447 PointerNum,
9448 InputInfo.BasePointersArray.getPointer(),
9449 InputInfo.PointersArray.getPointer(),
9450 InputInfo.SizesArray.getPointer(),
9451 MapTypesArray,
9452 NumTeams,
9453 NumThreads};
9454 Return = CGF.EmitRuntimeCall(
9455 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9456 : OMPRTL__tgt_target_teams),
9457 OffloadingArgs);
9458 } else {
9459 llvm::Value *OffloadingArgs[] = {DeviceID,
9460 OutlinedFnID,
9461 PointerNum,
9462 InputInfo.BasePointersArray.getPointer(),
9463 InputInfo.PointersArray.getPointer(),
9464 InputInfo.SizesArray.getPointer(),
9465 MapTypesArray};
9466 Return = CGF.EmitRuntimeCall(
9467 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9468 : OMPRTL__tgt_target),
9469 OffloadingArgs);
9470 }
9471
9472 // Check the error code and execute the host version if required.
9473 llvm::BasicBlock *OffloadFailedBlock =
9474 CGF.createBasicBlock("omp_offload.failed");
9475 llvm::BasicBlock *OffloadContBlock =
9476 CGF.createBasicBlock("omp_offload.cont");
9477 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9478 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9479
9480 CGF.EmitBlock(OffloadFailedBlock);
9481 if (RequiresOuterTask) {
9482 CapturedVars.clear();
9483 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9484 }
9485 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
9486 CGF.EmitBranch(OffloadContBlock);
9487
9488 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
9489 };
9490
9491 // Notify that the host version must be executed.
9492 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9493 RequiresOuterTask](CodeGenFunction &CGF,
9494 PrePostActionTy &) {
9495 if (RequiresOuterTask) {
9496 CapturedVars.clear();
9497 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9498 }
9499 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
9500 };
9501
9502 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9503 &CapturedVars, RequiresOuterTask,
9504 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9505 // Fill up the arrays with all the captured variables.
9506 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9507 MappableExprsHandler::MapValuesArrayTy Pointers;
9508 MappableExprsHandler::MapValuesArrayTy Sizes;
9509 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9510
9511 // Get mappable expression information.
9512 MappableExprsHandler MEHandler(D, CGF);
9513 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
9514
9515 auto RI = CS.getCapturedRecordDecl()->field_begin();
9516 auto CV = CapturedVars.begin();
9517 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9518 CE = CS.capture_end();
9519 CI != CE; ++CI, ++RI, ++CV) {
9520 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9521 MappableExprsHandler::MapValuesArrayTy CurPointers;
9522 MappableExprsHandler::MapValuesArrayTy CurSizes;
9523 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9524 MappableExprsHandler::StructRangeInfoTy PartialStruct;
9525
9526 // VLA sizes are passed to the outlined region by copy and do not have map
9527 // information associated.
9528 if (CI->capturesVariableArrayType()) {
9529 CurBasePointers.push_back(*CV);
9530 CurPointers.push_back(*CV);
9531 CurSizes.push_back(CGF.Builder.CreateIntCast(
9532 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
9533 // Copy to the device as an argument. No need to retrieve it.
9534 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
9535 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9536 MappableExprsHandler::OMP_MAP_IMPLICIT);
9537 } else {
9538 // If we have any information in the map clause, we use it, otherwise we
9539 // just do a default mapping.
9540 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
9541 CurSizes, CurMapTypes, PartialStruct);
9542 if (CurBasePointers.empty())
9543 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9544 CurPointers, CurSizes, CurMapTypes);
9545 // Generate correct mapping for variables captured by reference in
9546 // lambdas.
9547 if (CI->capturesVariable())
9548 MEHandler.generateInfoForLambdaCaptures(
9549 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9550 CurMapTypes, LambdaPointers);
9551 }
9552 // We expect to have at least an element of information for this capture.
9553 assert(!CurBasePointers.empty() &&((!CurBasePointers.empty() && "Non-existing map pointer for capture!"
) ? static_cast<void> (0) : __assert_fail ("!CurBasePointers.empty() && \"Non-existing map pointer for capture!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9554, __PRETTY_FUNCTION__))
9554 "Non-existing map pointer for capture!")((!CurBasePointers.empty() && "Non-existing map pointer for capture!"
) ? static_cast<void> (0) : __assert_fail ("!CurBasePointers.empty() && \"Non-existing map pointer for capture!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9554, __PRETTY_FUNCTION__))
;
9555 assert(CurBasePointers.size() == CurPointers.size() &&((CurBasePointers.size() == CurPointers.size() && CurBasePointers
.size() == CurSizes.size() && CurBasePointers.size() ==
CurMapTypes.size() && "Inconsistent map information sizes!"
) ? static_cast<void> (0) : __assert_fail ("CurBasePointers.size() == CurPointers.size() && CurBasePointers.size() == CurSizes.size() && CurBasePointers.size() == CurMapTypes.size() && \"Inconsistent map information sizes!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9558, __PRETTY_FUNCTION__))
9556 CurBasePointers.size() == CurSizes.size() &&((CurBasePointers.size() == CurPointers.size() && CurBasePointers
.size() == CurSizes.size() && CurBasePointers.size() ==
CurMapTypes.size() && "Inconsistent map information sizes!"
) ? static_cast<void> (0) : __assert_fail ("CurBasePointers.size() == CurPointers.size() && CurBasePointers.size() == CurSizes.size() && CurBasePointers.size() == CurMapTypes.size() && \"Inconsistent map information sizes!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9558, __PRETTY_FUNCTION__))
9557 CurBasePointers.size() == CurMapTypes.size() &&((CurBasePointers.size() == CurPointers.size() && CurBasePointers
.size() == CurSizes.size() && CurBasePointers.size() ==
CurMapTypes.size() && "Inconsistent map information sizes!"
) ? static_cast<void> (0) : __assert_fail ("CurBasePointers.size() == CurPointers.size() && CurBasePointers.size() == CurSizes.size() && CurBasePointers.size() == CurMapTypes.size() && \"Inconsistent map information sizes!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9558, __PRETTY_FUNCTION__))
9558 "Inconsistent map information sizes!")((CurBasePointers.size() == CurPointers.size() && CurBasePointers
.size() == CurSizes.size() && CurBasePointers.size() ==
CurMapTypes.size() && "Inconsistent map information sizes!"
) ? static_cast<void> (0) : __assert_fail ("CurBasePointers.size() == CurPointers.size() && CurBasePointers.size() == CurSizes.size() && CurBasePointers.size() == CurMapTypes.size() && \"Inconsistent map information sizes!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9558, __PRETTY_FUNCTION__))
;
9559
9560 // If there is an entry in PartialStruct it means we have a struct with
9561 // individual members mapped. Emit an extra combined entry.
9562 if (PartialStruct.Base.isValid())
9563 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9564 CurMapTypes, PartialStruct);
9565
9566 // We need to append the results of this capture to what we already have.
9567 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9568 Pointers.append(CurPointers.begin(), CurPointers.end());
9569 Sizes.append(CurSizes.begin(), CurSizes.end());
9570 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9571 }
9572 // Adjust MEMBER_OF flags for the lambdas captures.
9573 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9574 Pointers, MapTypes);
9575 // Map other list items in the map clause which are not captured variables
9576 // but "declare target link" global variables.
9577 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9578 MapTypes);
9579
9580 TargetDataInfo Info;
9581 // Fill up the arrays and create the arguments.
9582 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9583 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9584 Info.PointersArray, Info.SizesArray,
9585 Info.MapTypesArray, Info);
9586 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9587 InputInfo.BasePointersArray =
9588 Address(Info.BasePointersArray, CGM.getPointerAlign());
9589 InputInfo.PointersArray =
9590 Address(Info.PointersArray, CGM.getPointerAlign());
9591 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9592 MapTypesArray = Info.MapTypesArray;
9593 if (RequiresOuterTask)
9594 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9595 else
9596 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9597 };
9598
9599 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9600 CodeGenFunction &CGF, PrePostActionTy &) {
9601 if (RequiresOuterTask) {
9602 CodeGenFunction::OMPTargetDataInfo InputInfo;
9603 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9604 } else {
9605 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9606 }
9607 };
9608
9609 // If we have a target function ID it means that we need to support
9610 // offloading, otherwise, just execute on the host. We need to execute on host
9611 // regardless of the conditional in the if clause if, e.g., the user do not
9612 // specify target triples.
9613 if (OutlinedFnID) {
9614 if (IfCond) {
9615 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
9616 } else {
9617 RegionCodeGenTy ThenRCG(TargetThenGen);
9618 ThenRCG(CGF);
9619 }
9620 } else {
9621 RegionCodeGenTy ElseRCG(TargetElseGen);
9622 ElseRCG(CGF);
9623 }
9624}
9625
9626void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9627 StringRef ParentName) {
9628 if (!S)
9629 return;
9630
9631 // Codegen OMP target directives that offload compute to the device.
9632 bool RequiresDeviceCodegen =
9633 isa<OMPExecutableDirective>(S) &&
9634 isOpenMPTargetExecutionDirective(
9635 cast<OMPExecutableDirective>(S)->getDirectiveKind());
9636
9637 if (RequiresDeviceCodegen) {
9638 const auto &E = *cast<OMPExecutableDirective>(S);
9639 unsigned DeviceID;
9640 unsigned FileID;
9641 unsigned Line;
9642 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
9643 FileID, Line);
9644
9645 // Is this a target region that should not be emitted as an entry point? If
9646 // so just signal we are done with this target region.
9647 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9648 ParentName, Line))
9649 return;
9650
9651 switch (E.getDirectiveKind()) {
9652 case OMPD_target:
9653 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9654 cast<OMPTargetDirective>(E));
9655 break;
9656 case OMPD_target_parallel:
9657 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
9658 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
9659 break;
9660 case OMPD_target_teams:
9661 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
9662 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
9663 break;
9664 case OMPD_target_teams_distribute:
9665 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
9666 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
9667 break;
9668 case OMPD_target_teams_distribute_simd:
9669 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
9670 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
9671 break;
9672 case OMPD_target_parallel_for:
9673 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
9674 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
9675 break;
9676 case OMPD_target_parallel_for_simd:
9677 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
9678 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
9679 break;
9680 case OMPD_target_simd:
9681 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
9682 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
9683 break;
9684 case OMPD_target_teams_distribute_parallel_for:
9685 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9686 CGM, ParentName,
9687 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
9688 break;
9689 case OMPD_target_teams_distribute_parallel_for_simd:
9690 CodeGenFunction::
9691 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9692 CGM, ParentName,
9693 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
9694 break;
9695 case OMPD_parallel:
9696 case OMPD_for:
9697 case OMPD_parallel_for:
9698 case OMPD_parallel_master:
9699 case OMPD_parallel_sections:
9700 case OMPD_for_simd:
9701 case OMPD_parallel_for_simd:
9702 case OMPD_cancel:
9703 case OMPD_cancellation_point:
9704 case OMPD_ordered:
9705 case OMPD_threadprivate:
9706 case OMPD_allocate:
9707 case OMPD_task:
9708 case OMPD_simd:
9709 case OMPD_sections:
9710 case OMPD_section:
9711 case OMPD_single:
9712 case OMPD_master:
9713 case OMPD_critical:
9714 case OMPD_taskyield:
9715 case OMPD_barrier:
9716 case OMPD_taskwait:
9717 case OMPD_taskgroup:
9718 case OMPD_atomic:
9719 case OMPD_flush:
9720 case OMPD_depobj:
9721 case OMPD_teams:
9722 case OMPD_target_data:
9723 case OMPD_target_exit_data:
9724 case OMPD_target_enter_data:
9725 case OMPD_distribute:
9726 case OMPD_distribute_simd:
9727 case OMPD_distribute_parallel_for:
9728 case OMPD_distribute_parallel_for_simd:
9729 case OMPD_teams_distribute:
9730 case OMPD_teams_distribute_simd:
9731 case OMPD_teams_distribute_parallel_for:
9732 case OMPD_teams_distribute_parallel_for_simd:
9733 case OMPD_target_update:
9734 case OMPD_declare_simd:
9735 case OMPD_declare_variant:
9736 case OMPD_declare_target:
9737 case OMPD_end_declare_target:
9738 case OMPD_declare_reduction:
9739 case OMPD_declare_mapper:
9740 case OMPD_taskloop:
9741 case OMPD_taskloop_simd:
9742 case OMPD_master_taskloop:
9743 case OMPD_master_taskloop_simd:
9744 case OMPD_parallel_master_taskloop:
9745 case OMPD_parallel_master_taskloop_simd:
9746 case OMPD_requires:
9747 case OMPD_unknown:
9748 llvm_unreachable("Unknown target directive for OpenMP device codegen.")::llvm::llvm_unreachable_internal("Unknown target directive for OpenMP device codegen."
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9748)
;
9749 }
9750 return;
9751 }
9752
9753 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
9754 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
9755 return;
9756
9757 scanForTargetRegionsFunctions(
9758 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
9759 return;
9760 }
9761
9762 // If this is a lambda function, look into its body.
9763 if (const auto *L = dyn_cast<LambdaExpr>(S))
9764 S = L->getBody();
9765
9766 // Keep looking for target regions recursively.
9767 for (const Stmt *II : S->children())
9768 scanForTargetRegionsFunctions(II, ParentName);
9769}
9770
9771bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
9772 // If emitting code for the host, we do not process FD here. Instead we do
9773 // the normal code generation.
9774 if (!CGM.getLangOpts().OpenMPIsDevice) {
9775 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9776 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9777 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9778 // Do not emit device_type(nohost) functions for the host.
9779 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9780 return true;
9781 }
9782 return false;
9783 }
9784
9785 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
9786 // Try to detect target regions in the function.
9787 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
9788 StringRef Name = CGM.getMangledName(GD);
9789 scanForTargetRegionsFunctions(FD->getBody(), Name);
9790 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9791 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9792 // Do not emit device_type(nohost) functions for the host.
9793 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9794 return true;
9795 }
9796
9797 // Do not to emit function if it is not marked as declare target.
9798 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
9799 AlreadyEmittedTargetDecls.count(VD) == 0;
9800}
9801
9802bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9803 if (!CGM.getLangOpts().OpenMPIsDevice)
9804 return false;
9805
9806 // Check if there are Ctors/Dtors in this declaration and look for target
9807 // regions in it. We use the complete variant to produce the kernel name
9808 // mangling.
9809 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
9810 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9811 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
9812 StringRef ParentName =
9813 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9814 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9815 }
9816 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
9817 StringRef ParentName =
9818 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9819 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9820 }
9821 }
9822
9823 // Do not to emit variable if it is not marked as declare target.
9824 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9825 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9826 cast<VarDecl>(GD.getDecl()));
9827 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9828 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9829 HasRequiresUnifiedSharedMemory)) {
9830 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
9831 return true;
9832 }
9833 return false;
9834}
9835
9836llvm::Constant *
9837CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9838 const VarDecl *VD) {
9839 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9840, __PRETTY_FUNCTION__))
9840 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9840, __PRETTY_FUNCTION__))
;
9841 StringRef VarName;
9842 llvm::Constant *Addr;
9843 llvm::GlobalValue::LinkageTypes Linkage;
9844 QualType Ty = VD->getType();
9845 SmallString<128> Buffer;
9846 {
9847 unsigned DeviceID;
9848 unsigned FileID;
9849 unsigned Line;
9850 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9851 FileID, Line);
9852 llvm::raw_svector_ostream OS(Buffer);
9853 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9854 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9855 VarName = OS.str();
9856 }
9857 Linkage = llvm::GlobalValue::InternalLinkage;
9858 Addr =
9859 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9860 getDefaultFirstprivateAddressSpace());
9861 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9862 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9863 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9864 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9865 VarName, Addr, VarSize,
9866 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9867 return Addr;
9868}
9869
9870void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9871 llvm::Constant *Addr) {
9872 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
9873 !CGM.getLangOpts().OpenMPIsDevice)
9874 return;
9875 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9876 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9877 if (!Res) {
9878 if (CGM.getLangOpts().OpenMPIsDevice) {
9879 // Register non-target variables being emitted in device code (debug info
9880 // may cause this).
9881 StringRef VarName = CGM.getMangledName(VD);
9882 EmittedNonTargetVariables.try_emplace(VarName, Addr);
9883 }
9884 return;
9885 }
9886 // Register declare target variables.
9887 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9888 StringRef VarName;
9889 CharUnits VarSize;
9890 llvm::GlobalValue::LinkageTypes Linkage;
9891
9892 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9893 !HasRequiresUnifiedSharedMemory) {
9894 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9895 VarName = CGM.getMangledName(VD);
9896 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9897 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9898 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9898, __PRETTY_FUNCTION__))
;
9899 } else {
9900 VarSize = CharUnits::Zero();
9901 }
9902 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9903 // Temp solution to prevent optimizations of the internal variables.
9904 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9905 std::string RefName = getName({VarName, "ref"});
9906 if (!CGM.GetGlobalValue(RefName)) {
9907 llvm::Constant *AddrRef =
9908 getOrCreateInternalVariable(Addr->getType(), RefName);
9909 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9910 GVAddrRef->setConstant(/*Val=*/true);
9911 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9912 GVAddrRef->setInitializer(Addr);
9913 CGM.addCompilerUsedGlobal(GVAddrRef);
9914 }
9915 }
9916 } else {
9917 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9920, __PRETTY_FUNCTION__))
9918 (*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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9920, __PRETTY_FUNCTION__))
9919 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9920, __PRETTY_FUNCTION__))
9920 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9920, __PRETTY_FUNCTION__))
;
9921 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9922 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9923 else
9924 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9925
9926 if (CGM.getLangOpts().OpenMPIsDevice) {
9927 VarName = Addr->getName();
9928 Addr = nullptr;
9929 } else {
9930 VarName = getAddrOfDeclareTargetVar(VD).getName();
9931 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
9932 }
9933 VarSize = CGM.getPointerSize();
9934 Linkage = llvm::GlobalValue::WeakAnyLinkage;
9935 }
9936
9937 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9938 VarName, Addr, VarSize, Flags, Linkage);
9939}
9940
9941bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
9942 if (isa<FunctionDecl>(GD.getDecl()) ||
9943 isa<OMPDeclareReductionDecl>(GD.getDecl()))
9944 return emitTargetFunctions(GD);
9945
9946 return emitTargetGlobalVariable(GD);
9947}
9948
9949void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9950 for (const VarDecl *VD : DeferredGlobalVariables) {
9951 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9952 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9953 if (!Res)
9954 continue;
9955 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9956 !HasRequiresUnifiedSharedMemory) {
9957 CGM.EmitGlobal(VD);
9958 } else {
9959 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9962, __PRETTY_FUNCTION__))
9960 (*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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9962, __PRETTY_FUNCTION__))
9961 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9962, __PRETTY_FUNCTION__))
9962 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9962, __PRETTY_FUNCTION__))
;
9963 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
9964 }
9965 }
9966}
9967
9968void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9969 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9970 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9971, __PRETTY_FUNCTION__))
9971 " 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9971, __PRETTY_FUNCTION__))
;
9972}
9973
9974void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) {
9975 for (const OMPClause *Clause : D->clauselists()) {
9976 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9977 HasRequiresUnifiedSharedMemory = true;
9978 } else if (const auto *AC =
9979 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
9980 switch (AC->getAtomicDefaultMemOrderKind()) {
9981 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
9982 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease;
9983 break;
9984 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
9985 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent;
9986 break;
9987 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
9988 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic;
9989 break;
9990 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown:
9991 break;
9992 }
9993 }
9994 }
9995}
9996
9997llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const {
9998 return RequiresAtomicOrdering;
9999}
10000
10001bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
10002 LangAS &AS) {
10003 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
10004 return false;
10005 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
10006 switch(A->getAllocatorType()) {
10007 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
10008 // Not supported, fallback to the default mem space.
10009 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
10010 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
10011 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
10012 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
10013 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
10014 case OMPAllocateDeclAttr::OMPConstMemAlloc:
10015 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
10016 AS = LangAS::Default;
10017 return true;
10018 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
10019 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10020)
10020 "static storage.")::llvm::llvm_unreachable_internal("Expected predefined allocator for the variables with the "
"static storage.", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10020)
;
10021 }
10022 return false;
10023}
10024
10025bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
10026 return HasRequiresUnifiedSharedMemory;
10027}
10028
10029CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
10030 CodeGenModule &CGM)
10031 : CGM(CGM) {
10032 if (CGM.getLangOpts().OpenMPIsDevice) {
10033 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
10034 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
10035 }
10036}
10037
10038CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
10039 if (CGM.getLangOpts().OpenMPIsDevice)
10040 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
10041}
10042
10043bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
10044 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
10045 return true;
10046
10047 const auto *D = cast<FunctionDecl>(GD.getDecl());
10048 // Do not to emit function if it is marked as declare target as it was already
10049 // emitted.
10050 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
10051 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) {
10052 if (auto *F = dyn_cast_or_null<llvm::Function>(
10053 CGM.GetGlobalValue(CGM.getMangledName(GD))))
10054 return !F->isDeclaration();
10055 return false;
10056 }
10057 return true;
10058 }
10059
10060 return !AlreadyEmittedTargetDecls.insert(D).second;
10061}
10062
10063llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
10064 // If we don't have entries or if we are emitting code for the device, we
10065 // don't need to do anything.
10066 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
10067 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
10068 (OffloadEntriesInfoManager.empty() &&
10069 !HasEmittedDeclareTargetRegion &&
10070 !HasEmittedTargetRegion))
10071 return nullptr;
10072
10073 // Create and register the function that handles the requires directives.
10074 ASTContext &C = CGM.getContext();
10075
10076 llvm::Function *RequiresRegFn;
10077 {
10078 CodeGenFunction CGF(CGM);
10079 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
10080 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
10081 std::string ReqName = getName({"omp_offloading", "requires_reg"});
10082 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
10083 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
10084 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
10085 // TODO: check for other requires clauses.
10086 // The requires directive takes effect only when a target region is
10087 // present in the compilation unit. Otherwise it is ignored and not
10088 // passed to the runtime. This avoids the runtime from throwing an error
10089 // for mismatching requires clauses across compilation units that don't
10090 // contain at least 1 target region.
10091 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10094, __PRETTY_FUNCTION__))
10092 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10094, __PRETTY_FUNCTION__))
10093 !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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10094, __PRETTY_FUNCTION__))
10094 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10094, __PRETTY_FUNCTION__))
;
10095 if (HasRequiresUnifiedSharedMemory)
10096 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
10097 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
10098 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
10099 CGF.FinishFunction();
10100 }
10101 return RequiresRegFn;
10102}
10103
10104void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
10105 const OMPExecutableDirective &D,
10106 SourceLocation Loc,
10107 llvm::Function *OutlinedFn,
10108 ArrayRef<llvm::Value *> CapturedVars) {
10109 if (!CGF.HaveInsertPoint())
10110 return;
10111
10112 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
10113 CodeGenFunction::RunCleanupsScope Scope(CGF);
10114
10115 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
10116 llvm::Value *Args[] = {
10117 RTLoc,
10118 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
10119 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
10120 llvm::SmallVector<llvm::Value *, 16> RealArgs;
10121 RealArgs.append(std::begin(Args), std::end(Args));
10122 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
10123
10124 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
10125 CGF.EmitRuntimeCall(RTLFn, RealArgs);
10126}
10127
10128void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
10129 const Expr *NumTeams,
10130 const Expr *ThreadLimit,
10131 SourceLocation Loc) {
10132 if (!CGF.HaveInsertPoint())
10133 return;
10134
10135 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
10136
10137 llvm::Value *NumTeamsVal =
10138 NumTeams
10139 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
10140 CGF.CGM.Int32Ty, /* isSigned = */ true)
10141 : CGF.Builder.getInt32(0);
10142
10143 llvm::Value *ThreadLimitVal =
10144 ThreadLimit
10145 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
10146 CGF.CGM.Int32Ty, /* isSigned = */ true)
10147 : CGF.Builder.getInt32(0);
10148
10149 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
10150 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
10151 ThreadLimitVal};
10152 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
10153 PushNumTeamsArgs);
10154}
10155
10156void CGOpenMPRuntime::emitTargetDataCalls(
10157 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10158 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
10159 if (!CGF.HaveInsertPoint())
10160 return;
10161
10162 // Action used to replace the default codegen action and turn privatization
10163 // off.
10164 PrePostActionTy NoPrivAction;
10165
10166 // Generate the code for the opening of the data environment. Capture all the
10167 // arguments of the runtime call by reference because they are used in the
10168 // closing of the region.
10169 auto &&BeginThenGen = [this, &D, Device, &Info,
10170 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
10171 // Fill up the arrays with all the mapped variables.
10172 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10173 MappableExprsHandler::MapValuesArrayTy Pointers;
10174 MappableExprsHandler::MapValuesArrayTy Sizes;
10175 MappableExprsHandler::MapFlagsArrayTy MapTypes;
10176
10177 // Get map clause information.
10178 MappableExprsHandler MCHandler(D, CGF);
10179 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10180
10181 // Fill up the arrays and create the arguments.
10182 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10183
10184 llvm::Value *BasePointersArrayArg = nullptr;
10185 llvm::Value *PointersArrayArg = nullptr;
10186 llvm::Value *SizesArrayArg = nullptr;
10187 llvm::Value *MapTypesArrayArg = nullptr;
10188 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
10189 SizesArrayArg, MapTypesArrayArg, Info);
10190
10191 // Emit device ID if any.
10192 llvm::Value *DeviceID = nullptr;
10193 if (Device) {
10194 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10195 CGF.Int64Ty, /*isSigned=*/true);
10196 } else {
10197 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10198 }
10199
10200 // Emit the number of elements in the offloading arrays.
10201 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
10202
10203 llvm::Value *OffloadingArgs[] = {
10204 DeviceID, PointerNum, BasePointersArrayArg,
10205 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
10206 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
10207 OffloadingArgs);
10208
10209 // If device pointer privatization is required, emit the body of the region
10210 // here. It will have to be duplicated: with and without privatization.
10211 if (!Info.CaptureDeviceAddrMap.empty())
10212 CodeGen(CGF);
10213 };
10214
10215 // Generate code for the closing of the data region.
10216 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10217 PrePostActionTy &) {
10218 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10218, __PRETTY_FUNCTION__))
;
10219
10220 llvm::Value *BasePointersArrayArg = nullptr;
10221 llvm::Value *PointersArrayArg = nullptr;
10222 llvm::Value *SizesArrayArg = nullptr;
10223 llvm::Value *MapTypesArrayArg = nullptr;
10224 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
10225 SizesArrayArg, MapTypesArrayArg, Info);
10226
10227 // Emit device ID if any.
10228 llvm::Value *DeviceID = nullptr;
10229 if (Device) {
10230 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10231 CGF.Int64Ty, /*isSigned=*/true);
10232 } else {
10233 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10234 }
10235
10236 // Emit the number of elements in the offloading arrays.
10237 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
10238
10239 llvm::Value *OffloadingArgs[] = {
10240 DeviceID, PointerNum, BasePointersArrayArg,
10241 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
10242 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
10243 OffloadingArgs);
10244 };
10245
10246 // If we need device pointer privatization, we need to emit the body of the
10247 // region with no privatization in the 'else' branch of the conditional.
10248 // Otherwise, we don't have to do anything.
10249 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10250 PrePostActionTy &) {
10251 if (!Info.CaptureDeviceAddrMap.empty()) {
10252 CodeGen.setAction(NoPrivAction);
10253 CodeGen(CGF);
10254 }
10255 };
10256
10257 // We don't have to do anything to close the region if the if clause evaluates
10258 // to false.
10259 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
10260
10261 if (IfCond) {
10262 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
10263 } else {
10264 RegionCodeGenTy RCG(BeginThenGen);
10265 RCG(CGF);
10266 }
10267
10268 // If we don't require privatization of device pointers, we emit the body in
10269 // between the runtime calls. This avoids duplicating the body code.
10270 if (Info.CaptureDeviceAddrMap.empty()) {
10271 CodeGen.setAction(NoPrivAction);
10272 CodeGen(CGF);
10273 }
10274
10275 if (IfCond) {
10276 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen);
10277 } else {
10278 RegionCodeGenTy RCG(EndThenGen);
10279 RCG(CGF);
10280 }
10281}
10282
10283void CGOpenMPRuntime::emitTargetDataStandAloneCall(
10284 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10285 const Expr *Device) {
10286 if (!CGF.HaveInsertPoint())
10287 return;
10288
10289 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10292, __PRETTY_FUNCTION__))
10290 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10292, __PRETTY_FUNCTION__))
10291 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10292, __PRETTY_FUNCTION__))
10292 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10292, __PRETTY_FUNCTION__))
;
10293
10294 CodeGenFunction::OMPTargetDataInfo InputInfo;
10295 llvm::Value *MapTypesArray = nullptr;
10296 // Generate the code for the opening of the data environment.
10297 auto &&ThenGen = [this, &D, Device, &InputInfo,
10298 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
10299 // Emit device ID if any.
10300 llvm::Value *DeviceID = nullptr;
10301 if (Device) {
10302 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10303 CGF.Int64Ty, /*isSigned=*/true);
10304 } else {
10305 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10306 }
10307
10308 // Emit the number of elements in the offloading arrays.
10309 llvm::Constant *PointerNum =
10310 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
10311
10312 llvm::Value *OffloadingArgs[] = {DeviceID,
10313 PointerNum,
10314 InputInfo.BasePointersArray.getPointer(),
10315 InputInfo.PointersArray.getPointer(),
10316 InputInfo.SizesArray.getPointer(),
10317 MapTypesArray};
10318
10319 // Select the right runtime function call for each expected standalone
10320 // directive.
10321 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
10322 OpenMPRTLFunction RTLFn;
10323 switch (D.getDirectiveKind()) {
10324 case OMPD_target_enter_data:
10325 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10326 : OMPRTL__tgt_target_data_begin;
10327 break;
10328 case OMPD_target_exit_data:
10329 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10330 : OMPRTL__tgt_target_data_end;
10331 break;
10332 case OMPD_target_update:
10333 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10334 : OMPRTL__tgt_target_data_update;
10335 break;
10336 case OMPD_parallel:
10337 case OMPD_for:
10338 case OMPD_parallel_for:
10339 case OMPD_parallel_master:
10340 case OMPD_parallel_sections:
10341 case OMPD_for_simd:
10342 case OMPD_parallel_for_simd:
10343 case OMPD_cancel:
10344 case OMPD_cancellation_point:
10345 case OMPD_ordered:
10346 case OMPD_threadprivate:
10347 case OMPD_allocate:
10348 case OMPD_task:
10349 case OMPD_simd:
10350 case OMPD_sections:
10351 case OMPD_section:
10352 case OMPD_single:
10353 case OMPD_master:
10354 case OMPD_critical:
10355 case OMPD_taskyield:
10356 case OMPD_barrier:
10357 case OMPD_taskwait:
10358 case OMPD_taskgroup:
10359 case OMPD_atomic:
10360 case OMPD_flush:
10361 case OMPD_depobj:
10362 case OMPD_teams:
10363 case OMPD_target_data:
10364 case OMPD_distribute:
10365 case OMPD_distribute_simd:
10366 case OMPD_distribute_parallel_for:
10367 case OMPD_distribute_parallel_for_simd:
10368 case OMPD_teams_distribute:
10369 case OMPD_teams_distribute_simd:
10370 case OMPD_teams_distribute_parallel_for:
10371 case OMPD_teams_distribute_parallel_for_simd:
10372 case OMPD_declare_simd:
10373 case OMPD_declare_variant:
10374 case OMPD_declare_target:
10375 case OMPD_end_declare_target:
10376 case OMPD_declare_reduction:
10377 case OMPD_declare_mapper:
10378 case OMPD_taskloop:
10379 case OMPD_taskloop_simd:
10380 case OMPD_master_taskloop:
10381 case OMPD_master_taskloop_simd:
10382 case OMPD_parallel_master_taskloop:
10383 case OMPD_parallel_master_taskloop_simd:
10384 case OMPD_target:
10385 case OMPD_target_simd:
10386 case OMPD_target_teams_distribute:
10387 case OMPD_target_teams_distribute_simd:
10388 case OMPD_target_teams_distribute_parallel_for:
10389 case OMPD_target_teams_distribute_parallel_for_simd:
10390 case OMPD_target_teams:
10391 case OMPD_target_parallel:
10392 case OMPD_target_parallel_for:
10393 case OMPD_target_parallel_for_simd:
10394 case OMPD_requires:
10395 case OMPD_unknown:
10396 llvm_unreachable("Unexpected standalone target data directive.")::llvm::llvm_unreachable_internal("Unexpected standalone target data directive."
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10396)
;
10397 break;
10398 }
10399 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
10400 };
10401
10402 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10403 CodeGenFunction &CGF, PrePostActionTy &) {
10404 // Fill up the arrays with all the mapped variables.
10405 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10406 MappableExprsHandler::MapValuesArrayTy Pointers;
10407 MappableExprsHandler::MapValuesArrayTy Sizes;
10408 MappableExprsHandler::MapFlagsArrayTy MapTypes;
10409
10410 // Get map clause information.
10411 MappableExprsHandler MEHandler(D, CGF);
10412 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10413
10414 TargetDataInfo Info;
10415 // Fill up the arrays and create the arguments.
10416 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10417 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10418 Info.PointersArray, Info.SizesArray,
10419 Info.MapTypesArray, Info);
10420 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10421 InputInfo.BasePointersArray =
10422 Address(Info.BasePointersArray, CGM.getPointerAlign());
10423 InputInfo.PointersArray =
10424 Address(Info.PointersArray, CGM.getPointerAlign());
10425 InputInfo.SizesArray =
10426 Address(Info.SizesArray, CGM.getPointerAlign());
10427 MapTypesArray = Info.MapTypesArray;
10428 if (D.hasClausesOfKind<OMPDependClause>())
10429 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10430 else
10431 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
10432 };
10433
10434 if (IfCond) {
10435 emitIfClause(CGF, IfCond, TargetThenGen,
10436 [](CodeGenFunction &CGF, PrePostActionTy &) {});
10437 } else {
10438 RegionCodeGenTy ThenRCG(TargetThenGen);
10439 ThenRCG(CGF);
10440 }
10441}
10442
10443namespace {
10444 /// Kind of parameter in a function with 'declare simd' directive.
10445 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10446 /// Attribute set of the parameter.
10447 struct ParamAttrTy {
10448 ParamKindTy Kind = Vector;
10449 llvm::APSInt StrideOrArg;
10450 llvm::APSInt Alignment;
10451 };
10452} // namespace
10453
10454static unsigned evaluateCDTSize(const FunctionDecl *FD,
10455 ArrayRef<ParamAttrTy> ParamAttrs) {
10456 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10457 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10458 // of that clause. The VLEN value must be power of 2.
10459 // In other case the notion of the function`s "characteristic data type" (CDT)
10460 // is used to compute the vector length.
10461 // CDT is defined in the following order:
10462 // a) For non-void function, the CDT is the return type.
10463 // b) If the function has any non-uniform, non-linear parameters, then the
10464 // CDT is the type of the first such parameter.
10465 // c) If the CDT determined by a) or b) above is struct, union, or class
10466 // type which is pass-by-value (except for the type that maps to the
10467 // built-in complex data type), the characteristic data type is int.
10468 // d) If none of the above three cases is applicable, the CDT is int.
10469 // The VLEN is then determined based on the CDT and the size of vector
10470 // register of that ISA for which current vector version is generated. The
10471 // VLEN is computed using the formula below:
10472 // VLEN = sizeof(vector_register) / sizeof(CDT),
10473 // where vector register size specified in section 3.2.1 Registers and the
10474 // Stack Frame of original AMD64 ABI document.
10475 QualType RetType = FD->getReturnType();
10476 if (RetType.isNull())
10477 return 0;
10478 ASTContext &C = FD->getASTContext();
10479 QualType CDT;
10480 if (!RetType.isNull() && !RetType->isVoidType()) {
10481 CDT = RetType;
10482 } else {
10483 unsigned Offset = 0;
10484 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
10485 if (ParamAttrs[Offset].Kind == Vector)
10486 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10487 ++Offset;
10488 }
10489 if (CDT.isNull()) {
10490 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10491 if (ParamAttrs[I + Offset].Kind == Vector) {
10492 CDT = FD->getParamDecl(I)->getType();
10493 break;
10494 }
10495 }
10496 }
10497 }
10498 if (CDT.isNull())
10499 CDT = C.IntTy;
10500 CDT = CDT->getCanonicalTypeUnqualified();
10501 if (CDT->isRecordType() || CDT->isUnionType())
10502 CDT = C.IntTy;
10503 return C.getTypeSize(CDT);
10504}
10505
10506static void
10507emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
10508 const llvm::APSInt &VLENVal,
10509 ArrayRef<ParamAttrTy> ParamAttrs,
10510 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10511 struct ISADataTy {
10512 char ISA;
10513 unsigned VecRegSize;
10514 };
10515 ISADataTy ISAData[] = {
10516 {
10517 'b', 128
10518 }, // SSE
10519 {
10520 'c', 256
10521 }, // AVX
10522 {
10523 'd', 256
10524 }, // AVX2
10525 {
10526 'e', 512
10527 }, // AVX512
10528 };
10529 llvm::SmallVector<char, 2> Masked;
10530 switch (State) {
10531 case OMPDeclareSimdDeclAttr::BS_Undefined:
10532 Masked.push_back('N');
10533 Masked.push_back('M');
10534 break;
10535 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10536 Masked.push_back('N');
10537 break;
10538 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10539 Masked.push_back('M');
10540 break;
10541 }
10542 for (char Mask : Masked) {
10543 for (const ISADataTy &Data : ISAData) {
10544 SmallString<256> Buffer;
10545 llvm::raw_svector_ostream Out(Buffer);
10546 Out << "_ZGV" << Data.ISA << Mask;
10547 if (!VLENVal) {
10548 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10549 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10549, __PRETTY_FUNCTION__))
;
10550 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
10551 } else {
10552 Out << VLENVal;
10553 }
10554 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
10555 switch (ParamAttr.Kind){
10556 case LinearWithVarStride:
10557 Out << 's' << ParamAttr.StrideOrArg;
10558 break;
10559 case Linear:
10560 Out << 'l';
10561 if (!!ParamAttr.StrideOrArg)
10562 Out << ParamAttr.StrideOrArg;
10563 break;
10564 case Uniform:
10565 Out << 'u';
10566 break;
10567 case Vector:
10568 Out << 'v';
10569 break;
10570 }
10571 if (!!ParamAttr.Alignment)
10572 Out << 'a' << ParamAttr.Alignment;
10573 }
10574 Out << '_' << Fn->getName();
10575 Fn->addFnAttr(Out.str());
10576 }
10577 }
10578}
10579
10580// This are the Functions that are needed to mangle the name of the
10581// vector functions generated by the compiler, according to the rules
10582// defined in the "Vector Function ABI specifications for AArch64",
10583// available at
10584// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10585
10586/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10587///
10588/// TODO: Need to implement the behavior for reference marked with a
10589/// var or no linear modifiers (1.b in the section). For this, we
10590/// need to extend ParamKindTy to support the linear modifiers.
10591static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10592 QT = QT.getCanonicalType();
10593
10594 if (QT->isVoidType())
10595 return false;
10596
10597 if (Kind == ParamKindTy::Uniform)
10598 return false;
10599
10600 if (Kind == ParamKindTy::Linear)
10601 return false;
10602
10603 // TODO: Handle linear references with modifiers
10604
10605 if (Kind == ParamKindTy::LinearWithVarStride)
10606 return false;
10607
10608 return true;
10609}
10610
10611/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10612static bool getAArch64PBV(QualType QT, ASTContext &C) {
10613 QT = QT.getCanonicalType();
10614 unsigned Size = C.getTypeSize(QT);
10615
10616 // Only scalars and complex within 16 bytes wide set PVB to true.
10617 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10618 return false;
10619
10620 if (QT->isFloatingType())
10621 return true;
10622
10623 if (QT->isIntegerType())
10624 return true;
10625
10626 if (QT->isPointerType())
10627 return true;
10628
10629 // TODO: Add support for complex types (section 3.1.2, item 2).
10630
10631 return false;
10632}
10633
10634/// Computes the lane size (LS) of a return type or of an input parameter,
10635/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10636/// TODO: Add support for references, section 3.2.1, item 1.
10637static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10638 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10639 QualType PTy = QT.getCanonicalType()->getPointeeType();
10640 if (getAArch64PBV(PTy, C))
10641 return C.getTypeSize(PTy);
10642 }
10643 if (getAArch64PBV(QT, C))
10644 return C.getTypeSize(QT);
10645
10646 return C.getTypeSize(C.getUIntPtrType());
10647}
10648
10649// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10650// signature of the scalar function, as defined in 3.2.2 of the
10651// AAVFABI.
10652static std::tuple<unsigned, unsigned, bool>
10653getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10654 QualType RetType = FD->getReturnType().getCanonicalType();
10655
10656 ASTContext &C = FD->getASTContext();
10657
10658 bool OutputBecomesInput = false;
10659
10660 llvm::SmallVector<unsigned, 8> Sizes;
10661 if (!RetType->isVoidType()) {
10662 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10663 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10664 OutputBecomesInput = true;
10665 }
10666 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10667 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10668 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10669 }
10670
10671 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10671, __PRETTY_FUNCTION__))
;
10672 // The LS of a function parameter / return value can only be a power
10673 // of 2, starting from 8 bits, up to 128.
10674 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10679, __PRETTY_FUNCTION__))
10675 [](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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10679, __PRETTY_FUNCTION__))
10676 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10679, __PRETTY_FUNCTION__))
10677 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10679, __PRETTY_FUNCTION__))
10678 }) &&((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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10679, __PRETTY_FUNCTION__))
10679 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10679, __PRETTY_FUNCTION__))
;
10680
10681 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10682 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10683 OutputBecomesInput);
10684}
10685
10686/// Mangle the parameter part of the vector function name according to
10687/// their OpenMP classification. The mangling function is defined in
10688/// section 3.5 of the AAVFABI.
10689static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10690 SmallString<256> Buffer;
10691 llvm::raw_svector_ostream Out(Buffer);
10692 for (const auto &ParamAttr : ParamAttrs) {
10693 switch (ParamAttr.Kind) {
10694 case LinearWithVarStride:
10695 Out << "ls" << ParamAttr.StrideOrArg;
10696 break;
10697 case Linear:
10698 Out << 'l';
10699 // Don't print the step value if it is not present or if it is
10700 // equal to 1.
10701 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10702 Out << ParamAttr.StrideOrArg;
10703 break;
10704 case Uniform:
10705 Out << 'u';
10706 break;
10707 case Vector:
10708 Out << 'v';
10709 break;
10710 }
10711
10712 if (!!ParamAttr.Alignment)
10713 Out << 'a' << ParamAttr.Alignment;
10714 }
10715
10716 return std::string(Out.str());
10717}
10718
10719// Function used to add the attribute. The parameter `VLEN` is
10720// templated to allow the use of "x" when targeting scalable functions
10721// for SVE.
10722template <typename T>
10723static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10724 char ISA, StringRef ParSeq,
10725 StringRef MangledName, bool OutputBecomesInput,
10726 llvm::Function *Fn) {
10727 SmallString<256> Buffer;
10728 llvm::raw_svector_ostream Out(Buffer);
10729 Out << Prefix << ISA << LMask << VLEN;
10730 if (OutputBecomesInput)
10731 Out << "v";
10732 Out << ParSeq << "_" << MangledName;
10733 Fn->addFnAttr(Out.str());
10734}
10735
10736// Helper function to generate the Advanced SIMD names depending on
10737// the value of the NDS when simdlen is not present.
10738static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10739 StringRef Prefix, char ISA,
10740 StringRef ParSeq, StringRef MangledName,
10741 bool OutputBecomesInput,
10742 llvm::Function *Fn) {
10743 switch (NDS) {
10744 case 8:
10745 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10746 OutputBecomesInput, Fn);
10747 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10748 OutputBecomesInput, Fn);
10749 break;
10750 case 16:
10751 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10752 OutputBecomesInput, Fn);
10753 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10754 OutputBecomesInput, Fn);
10755 break;
10756 case 32:
10757 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10758 OutputBecomesInput, Fn);
10759 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10760 OutputBecomesInput, Fn);
10761 break;
10762 case 64:
10763 case 128:
10764 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10765 OutputBecomesInput, Fn);
10766 break;
10767 default:
10768 llvm_unreachable("Scalar type is too wide.")::llvm::llvm_unreachable_internal("Scalar type is too wide.",
"/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10768)
;
10769 }
10770}
10771
10772/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10773static void emitAArch64DeclareSimdFunction(
10774 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10775 ArrayRef<ParamAttrTy> ParamAttrs,
10776 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10777 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10778
10779 // Get basic data for building the vector signature.
10780 const auto Data = getNDSWDS(FD, ParamAttrs);
10781 const unsigned NDS = std::get<0>(Data);
10782 const unsigned WDS = std::get<1>(Data);
10783 const bool OutputBecomesInput = std::get<2>(Data);
10784
10785 // Check the values provided via `simdlen` by the user.
10786 // 1. A `simdlen(1)` doesn't produce vector signatures,
10787 if (UserVLEN == 1) {
10788 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10789 DiagnosticsEngine::Warning,
10790 "The clause simdlen(1) has no effect when targeting aarch64.");
10791 CGM.getDiags().Report(SLoc, DiagID);
10792 return;
10793 }
10794
10795 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10796 // Advanced SIMD output.
10797 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10798 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10799 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10800 "power of 2 when targeting Advanced SIMD.");
10801 CGM.getDiags().Report(SLoc, DiagID);
10802 return;
10803 }
10804
10805 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10806 // limits.
10807 if (ISA == 's' && UserVLEN != 0) {
10808 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10809 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10810 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10811 "lanes in the architectural constraints "
10812 "for SVE (min is 128-bit, max is "
10813 "2048-bit, by steps of 128-bit)");
10814 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10815 return;
10816 }
10817 }
10818
10819 // Sort out parameter sequence.
10820 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10821 StringRef Prefix = "_ZGV";
10822 // Generate simdlen from user input (if any).
10823 if (UserVLEN) {
10824 if (ISA == 's') {
10825 // SVE generates only a masked function.
10826 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10827 OutputBecomesInput, Fn);
10828 } else {
10829 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10829, __PRETTY_FUNCTION__))
;
10830 // Advanced SIMD generates one or two functions, depending on
10831 // the `[not]inbranch` clause.
10832 switch (State) {
10833 case OMPDeclareSimdDeclAttr::BS_Undefined:
10834 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10835 OutputBecomesInput, Fn);
10836 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10837 OutputBecomesInput, Fn);
10838 break;
10839 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10840 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10841 OutputBecomesInput, Fn);
10842 break;
10843 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10844 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10845 OutputBecomesInput, Fn);
10846 break;
10847 }
10848 }
10849 } else {
10850 // If no user simdlen is provided, follow the AAVFABI rules for
10851 // generating the vector length.
10852 if (ISA == 's') {
10853 // SVE, section 3.4.1, item 1.
10854 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10855 OutputBecomesInput, Fn);
10856 } else {
10857 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10857, __PRETTY_FUNCTION__))
;
10858 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10859 // two vector names depending on the use of the clause
10860 // `[not]inbranch`.
10861 switch (State) {
10862 case OMPDeclareSimdDeclAttr::BS_Undefined:
10863 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10864 OutputBecomesInput, Fn);
10865 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10866 OutputBecomesInput, Fn);
10867 break;
10868 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10869 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10870 OutputBecomesInput, Fn);
10871 break;
10872 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10873 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10874 OutputBecomesInput, Fn);
10875 break;
10876 }
10877 }
10878 }
10879}
10880
10881void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10882 llvm::Function *Fn) {
10883 ASTContext &C = CGM.getContext();
10884 FD = FD->getMostRecentDecl();
10885 // Map params to their positions in function decl.
10886 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10887 if (isa<CXXMethodDecl>(FD))
10888 ParamPositions.try_emplace(FD, 0);
10889 unsigned ParamPos = ParamPositions.size();
10890 for (const ParmVarDecl *P : FD->parameters()) {
10891 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
10892 ++ParamPos;
10893 }
10894 while (FD) {
10895 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
10896 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10897 // Mark uniform parameters.
10898 for (const Expr *E : Attr->uniforms()) {
10899 E = E->IgnoreParenImpCasts();
10900 unsigned Pos;
10901 if (isa<CXXThisExpr>(E)) {
10902 Pos = ParamPositions[FD];
10903 } else {
10904 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10905 ->getCanonicalDecl();
10906 Pos = ParamPositions[PVD];
10907 }
10908 ParamAttrs[Pos].Kind = Uniform;
10909 }
10910 // Get alignment info.
10911 auto NI = Attr->alignments_begin();
10912 for (const Expr *E : Attr->aligneds()) {
10913 E = E->IgnoreParenImpCasts();
10914 unsigned Pos;
10915 QualType ParmTy;
10916 if (isa<CXXThisExpr>(E)) {
10917 Pos = ParamPositions[FD];
10918 ParmTy = E->getType();
10919 } else {
10920 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10921 ->getCanonicalDecl();
10922 Pos = ParamPositions[PVD];
10923 ParmTy = PVD->getType();
10924 }
10925 ParamAttrs[Pos].Alignment =
10926 (*NI)
10927 ? (*NI)->EvaluateKnownConstInt(C)
10928 : llvm::APSInt::getUnsigned(
10929 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10930 .getQuantity());
10931 ++NI;
10932 }
10933 // Mark linear parameters.
10934 auto SI = Attr->steps_begin();
10935 auto MI = Attr->modifiers_begin();
10936 for (const Expr *E : Attr->linears()) {
10937 E = E->IgnoreParenImpCasts();
10938 unsigned Pos;
10939 if (isa<CXXThisExpr>(E)) {
10940 Pos = ParamPositions[FD];
10941 } else {
10942 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10943 ->getCanonicalDecl();
10944 Pos = ParamPositions[PVD];
10945 }
10946 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
10947 ParamAttr.Kind = Linear;
10948 if (*SI) {
10949 Expr::EvalResult Result;
10950 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
10951 if (const auto *DRE =
10952 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10953 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
10954 ParamAttr.Kind = LinearWithVarStride;
10955 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10956 ParamPositions[StridePVD->getCanonicalDecl()]);
10957 }
10958 }
10959 } else {
10960 ParamAttr.StrideOrArg = Result.Val.getInt();
10961 }
10962 }
10963 ++SI;
10964 ++MI;
10965 }
10966 llvm::APSInt VLENVal;
10967 SourceLocation ExprLoc;
10968 const Expr *VLENExpr = Attr->getSimdlen();
10969 if (VLENExpr) {
10970 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10971 ExprLoc = VLENExpr->getExprLoc();
10972 }
10973 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10974 if (CGM.getTriple().isX86()) {
10975 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
10976 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10977 unsigned VLEN = VLENVal.getExtValue();
10978 StringRef MangledName = Fn->getName();
10979 if (CGM.getTarget().hasFeature("sve"))
10980 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10981 MangledName, 's', 128, Fn, ExprLoc);
10982 if (CGM.getTarget().hasFeature("neon"))
10983 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10984 MangledName, 'n', 128, Fn, ExprLoc);
10985 }
10986 }
10987 FD = FD->getPreviousDecl();
10988 }
10989}
10990
10991namespace {
10992/// Cleanup action for doacross support.
10993class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10994public:
10995 static const int DoacrossFinArgs = 2;
10996
10997private:
10998 llvm::FunctionCallee RTLFn;
10999 llvm::Value *Args[DoacrossFinArgs];
11000
11001public:
11002 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
11003 ArrayRef<llvm::Value *> CallArgs)
11004 : RTLFn(RTLFn) {
11005 assert(CallArgs.size() == DoacrossFinArgs)((CallArgs.size() == DoacrossFinArgs) ? static_cast<void>
(0) : __assert_fail ("CallArgs.size() == DoacrossFinArgs", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11005, __PRETTY_FUNCTION__))
;
11006 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11007 }
11008 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
11009 if (!CGF.HaveInsertPoint())
11010 return;
11011 CGF.EmitRuntimeCall(RTLFn, Args);
11012 }
11013};
11014} // namespace
11015
11016void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
11017 const OMPLoopDirective &D,
11018 ArrayRef<Expr *> NumIterations) {
11019 if (!CGF.HaveInsertPoint())
11020 return;
11021
11022 ASTContext &C = CGM.getContext();
11023 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
11024 RecordDecl *RD;
11025 if (KmpDimTy.isNull()) {
11026 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
11027 // kmp_int64 lo; // lower
11028 // kmp_int64 up; // upper
11029 // kmp_int64 st; // stride
11030 // };
11031 RD = C.buildImplicitRecord("kmp_dim");
11032 RD->startDefinition();
11033 addFieldToRecordDecl(C, RD, Int64Ty);
11034 addFieldToRecordDecl(C, RD, Int64Ty);
11035 addFieldToRecordDecl(C, RD, Int64Ty);
11036 RD->completeDefinition();
11037 KmpDimTy = C.getRecordType(RD);
11038 } else {
11039 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
11040 }
11041 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
11042 QualType ArrayTy =
11043 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
11044
11045 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
11046 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
11047 enum { LowerFD = 0, UpperFD, StrideFD };
11048 // Fill dims with data.
11049 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
11050 LValue DimsLVal = CGF.MakeAddrLValue(
11051 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
11052 // dims.upper = num_iterations;
11053 LValue UpperLVal = CGF.EmitLValueForField(
11054 DimsLVal, *std::next(RD->field_begin(), UpperFD));
11055 llvm::Value *NumIterVal =
11056 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
11057 D.getNumIterations()->getType(), Int64Ty,
11058 D.getNumIterations()->getExprLoc());
11059 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
11060 // dims.stride = 1;
11061 LValue StrideLVal = CGF.EmitLValueForField(
11062 DimsLVal, *std::next(RD->field_begin(), StrideFD));
11063 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
11064 StrideLVal);
11065 }
11066
11067 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
11068 // kmp_int32 num_dims, struct kmp_dim * dims);
11069 llvm::Value *Args[] = {
11070 emitUpdateLocation(CGF, D.getBeginLoc()),
11071 getThreadID(CGF, D.getBeginLoc()),
11072 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
11073 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11074 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
11075 CGM.VoidPtrTy)};
11076
11077 llvm::FunctionCallee RTLFn =
11078 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
11079 CGF.EmitRuntimeCall(RTLFn, Args);
11080 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
11081 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
11082 llvm::FunctionCallee FiniRTLFn =
11083 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
11084 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11085 llvm::makeArrayRef(FiniArgs));
11086}
11087
11088void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11089 const OMPDependClause *C) {
11090 QualType Int64Ty =
11091 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
11092 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
11093 QualType ArrayTy = CGM.getContext().getConstantArrayType(
11094 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
11095 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
11096 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
11097 const Expr *CounterVal = C->getLoopData(I);
11098 assert(CounterVal)((CounterVal) ? static_cast<void> (0) : __assert_fail (
"CounterVal", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11098, __PRETTY_FUNCTION__))
;
11099 llvm::Value *CntVal = CGF.EmitScalarConversion(
11100 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
11101 CounterVal->getExprLoc());
11102 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
11103 /*Volatile=*/false, Int64Ty);
11104 }
11105 llvm::Value *Args[] = {
11106 emitUpdateLocation(CGF, C->getBeginLoc()),
11107 getThreadID(CGF, C->getBeginLoc()),
11108 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
11109 llvm::FunctionCallee RTLFn;
11110 if (C->getDependencyKind() == OMPC_DEPEND_source) {
11111 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
11112 } else {
11113 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11113, __PRETTY_FUNCTION__))
;
11114 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
11115 }
11116 CGF.EmitRuntimeCall(RTLFn, Args);
11117}
11118
11119void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
11120 llvm::FunctionCallee Callee,
11121 ArrayRef<llvm::Value *> Args) const {
11122 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11122, __PRETTY_FUNCTION__))
;
11123 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
11124
11125 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
11126 if (Fn->doesNotThrow()) {
11127 CGF.EmitNounwindRuntimeCall(Fn, Args);
11128 return;
11129 }
11130 }
11131 CGF.EmitRuntimeCall(Callee, Args);
11132}
11133
11134void CGOpenMPRuntime::emitOutlinedFunctionCall(
11135 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
11136 ArrayRef<llvm::Value *> Args) const {
11137 emitCall(CGF, Loc, OutlinedFn, Args);
11138}
11139
11140void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
11141 if (const auto *FD = dyn_cast<FunctionDecl>(D))
11142 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
11143 HasEmittedDeclareTargetRegion = true;
11144}
11145
11146Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
11147 const VarDecl *NativeParam,
11148 const VarDecl *TargetParam) const {
11149 return CGF.GetAddrOfLocalVar(NativeParam);
11150}
11151
11152namespace {
11153/// Cleanup action for allocate support.
11154class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
11155public:
11156 static const int CleanupArgs = 3;
11157
11158private:
11159 llvm::FunctionCallee RTLFn;
11160 llvm::Value *Args[CleanupArgs];
11161
11162public:
11163 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
11164 ArrayRef<llvm::Value *> CallArgs)
11165 : RTLFn(RTLFn) {
11166 assert(CallArgs.size() == CleanupArgs &&((CallArgs.size() == CleanupArgs && "Size of arguments does not match."
) ? static_cast<void> (0) : __assert_fail ("CallArgs.size() == CleanupArgs && \"Size of arguments does not match.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11167, __PRETTY_FUNCTION__))
11167 "Size of arguments does not match.")((CallArgs.size() == CleanupArgs && "Size of arguments does not match."
) ? static_cast<void> (0) : __assert_fail ("CallArgs.size() == CleanupArgs && \"Size of arguments does not match.\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11167, __PRETTY_FUNCTION__))
;
11168 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11169 }
11170 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
11171 if (!CGF.HaveInsertPoint())
11172 return;
11173 CGF.EmitRuntimeCall(RTLFn, Args);
11174 }
11175};
11176} // namespace
11177
11178Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
11179 const VarDecl *VD) {
11180 if (!VD)
11181 return Address::invalid();
11182 const VarDecl *CVD = VD->getCanonicalDecl();
11183 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
11184 return Address::invalid();
11185 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
11186 // Use the default allocation.
11187 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
11188 !AA->getAllocator())
11189 return Address::invalid();
11190 llvm::Value *Size;
11191 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
11192 if (CVD->getType()->isVariablyModifiedType()) {
11193 Size = CGF.getTypeSize(CVD->getType());
11194 // Align the size: ((size + align - 1) / align) * align
11195 Size = CGF.Builder.CreateNUWAdd(
11196 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
11197 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
11198 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
11199 } else {
11200 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
11201 Size = CGM.getSize(Sz.alignTo(Align));
11202 }
11203 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11204 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11205, __PRETTY_FUNCTION__))
11205 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11205, __PRETTY_FUNCTION__))
;
11206 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
11207 // According to the standard, the original allocator type is a enum (integer).
11208 // Convert to pointer type, if required.
11209 if (Allocator->getType()->isIntegerTy())
11210 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11211 else if (Allocator->getType()->isPointerTy())
11212 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11213 CGM.VoidPtrTy);
11214 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11215
11216 llvm::Value *Addr =
11217 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
11218 getName({CVD->getName(), ".void.addr"}));
11219 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11220 Allocator};
11221 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11222
11223 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11224 llvm::makeArrayRef(FiniArgs));
11225 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11226 Addr,
11227 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
11228 getName({CVD->getName(), ".addr"}));
11229 return Address(Addr, Align);
11230}
11231
11232/// Finds the variant function that matches current context with its context
11233/// selector.
11234static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM,
11235 const FunctionDecl *FD) {
11236 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
11237 return FD;
11238
11239 SmallVector<Expr *, 8> VariantExprs;
11240 SmallVector<VariantMatchInfo, 8> VMIs;
11241 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
11242 const OMPTraitInfo &TI = A->getTraitInfos();
11243 VMIs.push_back(VariantMatchInfo());
11244 TI.getAsVariantMatchInfo(CGM.getContext(), VMIs.back());
11245 VariantExprs.push_back(A->getVariantFuncRef());
11246 }
11247
11248 OMPContext Ctx(CGM.getLangOpts().OpenMPIsDevice, CGM.getTriple());
11249 // FIXME: Keep the context in the OMPIRBuilder so we can add constructs as we
11250 // build them.
11251
11252 int BestMatchIdx = getBestVariantMatchForContext(VMIs, Ctx);
11253 if (BestMatchIdx < 0)
11254 return FD;
11255
11256 return cast<FunctionDecl>(
11257 cast<DeclRefExpr>(VariantExprs[BestMatchIdx]->IgnoreParenImpCasts())
11258 ->getDecl());
11259}
11260
11261bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
11262 const auto *D = cast<FunctionDecl>(GD.getDecl());
11263 // If the original function is defined already, use its definition.
11264 StringRef MangledName = CGM.getMangledName(GD);
11265 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
11266 if (Orig && !Orig->isDeclaration())
11267 return false;
11268 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D);
11269 // Emit original function if it does not have declare variant attribute or the
11270 // context does not match.
11271 if (NewFD == D)
11272 return false;
11273 GlobalDecl NewGD = GD.getWithDecl(NewFD);
11274 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) {
11275 DeferredVariantFunction.erase(D);
11276 return true;
11277 }
11278 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
11279 return true;
11280}
11281
11282CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII(
11283 CodeGenModule &CGM, const OMPLoopDirective &S)
11284 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) {
11285 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11285, __PRETTY_FUNCTION__))
;
11286 if (!NeedToPush)
11287 return;
11288 NontemporalDeclsSet &DS =
11289 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
11290 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) {
11291 for (const Stmt *Ref : C->private_refs()) {
11292 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts();
11293 const ValueDecl *VD;
11294 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
11295 VD = DRE->getDecl();
11296 } else {
11297 const auto *ME = cast<MemberExpr>(SimpleRefExpr);
11298 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11300, __PRETTY_FUNCTION__))
11299 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11300, __PRETTY_FUNCTION__))
11300 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11300, __PRETTY_FUNCTION__))
;
11301 VD = ME->getMemberDecl();
11302 }
11303 DS.insert(VD);
11304 }
11305 }
11306}
11307
11308CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() {
11309 if (!NeedToPush)
11310 return;
11311 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
11312}
11313
11314bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const {
11315 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11315, __PRETTY_FUNCTION__))
;
11316
11317 return llvm::any_of(
11318 CGM.getOpenMPRuntime().NontemporalDeclsStack,
11319 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; });
11320}
11321
11322void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
11323 const OMPExecutableDirective &S,
11324 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled)
11325 const {
11326 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
11327 // Vars in target/task regions must be excluded completely.
11328 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) ||
11329 isOpenMPTaskingDirective(S.getDirectiveKind())) {
11330 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
11331 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind());
11332 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
11333 for (const CapturedStmt::Capture &Cap : CS->captures()) {
11334 if (Cap.capturesVariable() || Cap.capturesVariableByCopy())
11335 NeedToCheckForLPCs.insert(Cap.getCapturedVar());
11336 }
11337 }
11338 // Exclude vars in private clauses.
11339 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
11340 for (const Expr *Ref : C->varlists()) {
11341 if (!Ref->getType()->isScalarType())
11342 continue;
11343 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11344 if (!DRE)
11345 continue;
11346 NeedToCheckForLPCs.insert(DRE->getDecl());
11347 }
11348 }
11349 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
11350 for (const Expr *Ref : C->varlists()) {
11351 if (!Ref->getType()->isScalarType())
11352 continue;
11353 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11354 if (!DRE)
11355 continue;
11356 NeedToCheckForLPCs.insert(DRE->getDecl());
11357 }
11358 }
11359 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
11360 for (const Expr *Ref : C->varlists()) {
11361 if (!Ref->getType()->isScalarType())
11362 continue;
11363 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11364 if (!DRE)
11365 continue;
11366 NeedToCheckForLPCs.insert(DRE->getDecl());
11367 }
11368 }
11369 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
11370 for (const Expr *Ref : C->varlists()) {
11371 if (!Ref->getType()->isScalarType())
11372 continue;
11373 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11374 if (!DRE)
11375 continue;
11376 NeedToCheckForLPCs.insert(DRE->getDecl());
11377 }
11378 }
11379 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
11380 for (const Expr *Ref : C->varlists()) {
11381 if (!Ref->getType()->isScalarType())
11382 continue;
11383 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11384 if (!DRE)
11385 continue;
11386 NeedToCheckForLPCs.insert(DRE->getDecl());
11387 }
11388 }
11389 for (const Decl *VD : NeedToCheckForLPCs) {
11390 for (const LastprivateConditionalData &Data :
11391 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
11392 if (Data.DeclToUniqueName.count(VD) > 0) {
11393 if (!Data.Disabled)
11394 NeedToAddForLPCsAsDisabled.insert(VD);
11395 break;
11396 }
11397 }
11398 }
11399}
11400
11401CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11402 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal)
11403 : CGM(CGF.CGM),
11404 Action((CGM.getLangOpts().OpenMP >= 50 &&
11405 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
11406 [](const OMPLastprivateClause *C) {
11407 return C->getKind() ==
11408 OMPC_LASTPRIVATE_conditional;
11409 }))
11410 ? ActionToDo::PushAsLastprivateConditional
11411 : ActionToDo::DoNotPush) {
11412 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11412, __PRETTY_FUNCTION__))
;
11413 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
11414 return;
11415 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11416, __PRETTY_FUNCTION__))
11416 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11416, __PRETTY_FUNCTION__))
;
11417 LastprivateConditionalData &Data =
11418 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
11419 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
11420 if (C->getKind() != OMPC_LASTPRIVATE_conditional)
11421 continue;
11422
11423 for (const Expr *Ref : C->varlists()) {
11424 Data.DeclToUniqueName.insert(std::make_pair(
11425 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(),
11426 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref))));
11427 }
11428 }
11429 Data.IVLVal = IVLVal;
11430 Data.Fn = CGF.CurFn;
11431}
11432
11433CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11434 CodeGenFunction &CGF, const OMPExecutableDirective &S)
11435 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) {
11436 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11436, __PRETTY_FUNCTION__))
;
11437 if (CGM.getLangOpts().OpenMP < 50)
11438 return;
11439 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
11440 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
11441 if (!NeedToAddForLPCsAsDisabled.empty()) {
11442 Action = ActionToDo::DisableLastprivateConditional;
11443 LastprivateConditionalData &Data =
11444 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
11445 for (const Decl *VD : NeedToAddForLPCsAsDisabled)
11446 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>()));
11447 Data.Fn = CGF.CurFn;
11448 Data.Disabled = true;
11449 }
11450}
11451
11452CGOpenMPRuntime::LastprivateConditionalRAII
11453CGOpenMPRuntime::LastprivateConditionalRAII::disable(
11454 CodeGenFunction &CGF, const OMPExecutableDirective &S) {
11455 return LastprivateConditionalRAII(CGF, S);
11456}
11457
11458CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() {
11459 if (CGM.getLangOpts().OpenMP < 50)
11460 return;
11461 if (Action == ActionToDo::DisableLastprivateConditional) {
11462 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11463, __PRETTY_FUNCTION__))
11463 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11463, __PRETTY_FUNCTION__))
;
11464 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
11465 }
11466 if (Action == ActionToDo::PushAsLastprivateConditional) {
11467 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11469, __PRETTY_FUNCTION__))
11468 !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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11469, __PRETTY_FUNCTION__))
11469 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11469, __PRETTY_FUNCTION__))
;
11470 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
11471 }
11472}
11473
11474Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF,
11475 const VarDecl *VD) {
11476 ASTContext &C = CGM.getContext();
11477 auto I = LastprivateConditionalToTypes.find(CGF.CurFn);
11478 if (I == LastprivateConditionalToTypes.end())
11479 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first;
11480 QualType NewType;
11481 const FieldDecl *VDField;
11482 const FieldDecl *FiredField;
11483 LValue BaseLVal;
11484 auto VI = I->getSecond().find(VD);
11485 if (VI == I->getSecond().end()) {
11486 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional");
11487 RD->startDefinition();
11488 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType());
11489 FiredField = addFieldToRecordDecl(C, RD, C.CharTy);
11490 RD->completeDefinition();
11491 NewType = C.getRecordType(RD);
11492 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName());
11493 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl);
11494 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
11495 } else {
11496 NewType = std::get<0>(VI->getSecond());
11497 VDField = std::get<1>(VI->getSecond());
11498 FiredField = std::get<2>(VI->getSecond());
11499 BaseLVal = std::get<3>(VI->getSecond());
11500 }
11501 LValue FiredLVal =
11502 CGF.EmitLValueForField(BaseLVal, FiredField);
11503 CGF.EmitStoreOfScalar(
11504 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)),
11505 FiredLVal);
11506 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF);
11507}
11508
11509namespace {
11510/// Checks if the lastprivate conditional variable is referenced in LHS.
11511class LastprivateConditionalRefChecker final
11512 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> {
11513 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM;
11514 const Expr *FoundE = nullptr;
11515 const Decl *FoundD = nullptr;
11516 StringRef UniqueDeclName;
11517 LValue IVLVal;
11518 llvm::Function *FoundFn = nullptr;
11519 SourceLocation Loc;
11520
11521public:
11522 bool VisitDeclRefExpr(const DeclRefExpr *E) {
11523 for (const CGOpenMPRuntime::LastprivateConditionalData &D :
11524 llvm::reverse(LPM)) {
11525 auto It = D.DeclToUniqueName.find(E->getDecl());
11526 if (It == D.DeclToUniqueName.end())
11527 continue;
11528 if (D.Disabled)
11529 return false;
11530 FoundE = E;
11531 FoundD = E->getDecl()->getCanonicalDecl();
11532 UniqueDeclName = It->second;
11533 IVLVal = D.IVLVal;
11534 FoundFn = D.Fn;
11535 break;
11536 }
11537 return FoundE == E;
11538 }
11539 bool VisitMemberExpr(const MemberExpr *E) {
11540 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase()))
11541 return false;
11542 for (const CGOpenMPRuntime::LastprivateConditionalData &D :
11543 llvm::reverse(LPM)) {
11544 auto It = D.DeclToUniqueName.find(E->getMemberDecl());
11545 if (It == D.DeclToUniqueName.end())
11546 continue;
11547 if (D.Disabled)
11548 return false;
11549 FoundE = E;
11550 FoundD = E->getMemberDecl()->getCanonicalDecl();
11551 UniqueDeclName = It->second;
11552 IVLVal = D.IVLVal;
11553 FoundFn = D.Fn;
11554 break;
11555 }
11556 return FoundE == E;
11557 }
11558 bool VisitStmt(const Stmt *S) {
11559 for (const Stmt *Child : S->children()) {
11560 if (!Child)
11561 continue;
11562 if (const auto *E = dyn_cast<Expr>(Child))
11563 if (!E->isGLValue())
11564 continue;
11565 if (Visit(Child))
11566 return true;
11567 }
11568 return false;
11569 }
11570 explicit LastprivateConditionalRefChecker(
11571 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
11572 : LPM(LPM) {}
11573 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
11574 getFoundData() const {
11575 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
11576 }
11577};
11578} // namespace
11579
11580void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF,
11581 LValue IVLVal,
11582 StringRef UniqueDeclName,
11583 LValue LVal,
11584 SourceLocation Loc) {
11585 // Last updated loop counter for the lastprivate conditional var.
11586 // int<xx> last_iv = 0;
11587 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType());
11588 llvm::Constant *LastIV =
11589 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"}));
11590 cast<llvm::GlobalVariable>(LastIV)->setAlignment(
11591 IVLVal.getAlignment().getAsAlign());
11592 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType());
11593
11594 // Last value of the lastprivate conditional.
11595 // decltype(priv_a) last_a;
11596 llvm::Constant *Last = getOrCreateInternalVariable(
11597 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName);
11598 cast<llvm::GlobalVariable>(Last)->setAlignment(
11599 LVal.getAlignment().getAsAlign());
11600 LValue LastLVal =
11601 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment());
11602
11603 // Global loop counter. Required to handle inner parallel-for regions.
11604 // iv
11605 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc);
11606
11607 // #pragma omp critical(a)
11608 // if (last_iv <= iv) {
11609 // last_iv = iv;
11610 // last_a = priv_a;
11611 // }
11612 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
11613 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
11614 Action.Enter(CGF);
11615 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc);
11616 // (last_iv <= iv) ? Check if the variable is updated and store new
11617 // value in global var.
11618 llvm::Value *CmpRes;
11619 if (IVLVal.getType()->isSignedIntegerType()) {
11620 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal);
11621 } else {
11622 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11623, __PRETTY_FUNCTION__))
11623 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11623, __PRETTY_FUNCTION__))
;
11624 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal);
11625 }
11626 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then");
11627 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit");
11628 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
11629 // {
11630 CGF.EmitBlock(ThenBB);
11631
11632 // last_iv = iv;
11633 CGF.EmitStoreOfScalar(IVVal, LastIVLVal);
11634
11635 // last_a = priv_a;
11636 switch (CGF.getEvaluationKind(LVal.getType())) {
11637 case TEK_Scalar: {
11638 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc);
11639 CGF.EmitStoreOfScalar(PrivVal, LastLVal);
11640 break;
11641 }
11642 case TEK_Complex: {
11643 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc);
11644 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false);
11645 break;
11646 }
11647 case TEK_Aggregate:
11648 llvm_unreachable(::llvm::llvm_unreachable_internal("Aggregates are not supported in lastprivate conditional."
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11649)
11649 "Aggregates are not supported in lastprivate conditional.")::llvm::llvm_unreachable_internal("Aggregates are not supported in lastprivate conditional."
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11649)
;
11650 }
11651 // }
11652 CGF.EmitBranch(ExitBB);
11653 // There is no need to emit line number for unconditional branch.
11654 (void)ApplyDebugLocation::CreateEmpty(CGF);
11655 CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
11656 };
11657
11658 if (CGM.getLangOpts().OpenMPSimd) {
11659 // Do not emit as a critical region as no parallel region could be emitted.
11660 RegionCodeGenTy ThenRCG(CodeGen);
11661 ThenRCG(CGF);
11662 } else {
11663 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc);
11664 }
11665}
11666
11667void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF,
11668 const Expr *LHS) {
11669 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
11670 return;
11671 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack);
11672 if (!Checker.Visit(LHS))
11673 return;
11674 const Expr *FoundE;
11675 const Decl *FoundD;
11676 StringRef UniqueDeclName;
11677 LValue IVLVal;
11678 llvm::Function *FoundFn;
11679 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
11680 Checker.getFoundData();
11681 if (FoundFn != CGF.CurFn) {
11682 // Special codegen for inner parallel regions.
11683 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1;
11684 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD);
11685 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11686, __PRETTY_FUNCTION__))
11686 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11686, __PRETTY_FUNCTION__))
;
11687 QualType StructTy = std::get<0>(It->getSecond());
11688 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
11689 LValue PrivLVal = CGF.EmitLValue(FoundE);
11690 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11691 PrivLVal.getAddress(CGF),
11692 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy)));
11693 LValue BaseLVal =
11694 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl);
11695 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl);
11696 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get(
11697 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)),
11698 FiredLVal, llvm::AtomicOrdering::Unordered,
11699 /*IsVolatile=*/true, /*isInit=*/false);
11700 return;
11701 }
11702
11703 // Private address of the lastprivate conditional in the current context.
11704 // priv_a
11705 LValue LVal = CGF.EmitLValue(FoundE);
11706 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal,
11707 FoundE->getExprLoc());
11708}
11709
11710void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional(
11711 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11712 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) {
11713 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
11714 return;
11715 auto Range = llvm::reverse(LastprivateConditionalStack);
11716 auto It = llvm::find_if(
11717 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; });
11718 if (It == Range.end() || It->Fn != CGF.CurFn)
11719 return;
11720 auto LPCI = LastprivateConditionalToTypes.find(It->Fn);
11721 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11722, __PRETTY_FUNCTION__))
11722 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11722, __PRETTY_FUNCTION__))
;
11723 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
11724 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind());
11725 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
11726 for (const auto &Pair : It->DeclToUniqueName) {
11727 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl());
11728 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0)
11729 continue;
11730 auto I = LPCI->getSecond().find(Pair.first);
11731 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11732, __PRETTY_FUNCTION__))
11732 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11732, __PRETTY_FUNCTION__))
;
11733 // bool Cmp = priv_a.Fired != 0;
11734 LValue BaseLVal = std::get<3>(I->getSecond());
11735 LValue FiredLVal =
11736 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond()));
11737 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc());
11738 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res);
11739 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then");
11740 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done");
11741 // if (Cmp) {
11742 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
11743 CGF.EmitBlock(ThenBB);
11744 Address Addr = CGF.GetAddrOfLocalVar(VD);
11745 LValue LVal;
11746 if (VD->getType()->isReferenceType())
11747 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
11748 AlignmentSource::Decl);
11749 else
11750 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(),
11751 AlignmentSource::Decl);
11752 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal,
11753 D.getBeginLoc());
11754 auto AL = ApplyDebugLocation::CreateArtificial(CGF);
11755 CGF.EmitBlock(DoneBB, /*IsFinal=*/true);
11756 // }
11757 }
11758}
11759
11760void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate(
11761 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD,
11762 SourceLocation Loc) {
11763 if (CGF.getLangOpts().OpenMP < 50)
11764 return;
11765 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD);
11766 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11767, __PRETTY_FUNCTION__))
11767 "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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11767, __PRETTY_FUNCTION__))
;
11768 StringRef UniqueName = It->second;
11769 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName);
11770 // The variable was not updated in the region - exit.
11771 if (!GV)
11772 return;
11773 LValue LPLVal = CGF.MakeAddrLValue(
11774 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment());
11775 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc);
11776 CGF.EmitStoreOfScalar(Res, PrivLVal);
11777}
11778
11779llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
11780 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11781 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11782 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11782)
;
11783}
11784
11785llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
11786 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11787 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11788 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11788)
;
11789}
11790
11791llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
11792 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11793 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11794 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11795 bool Tied, unsigned &NumberOfParts) {
11796 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11796)
;
11797}
11798
11799void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11800 SourceLocation Loc,
11801 llvm::Function *OutlinedFn,
11802 ArrayRef<llvm::Value *> CapturedVars,
11803 const Expr *IfCond) {
11804 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11804)
;
11805}
11806
11807void CGOpenMPSIMDRuntime::emitCriticalRegion(
11808 CodeGenFunction &CGF, StringRef CriticalName,
11809 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11810 const Expr *Hint) {
11811 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11811)
;
11812}
11813
11814void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11815 const RegionCodeGenTy &MasterOpGen,
11816 SourceLocation Loc) {
11817 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11817)
;
11818}
11819
11820void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11821 SourceLocation Loc) {
11822 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11822)
;
11823}
11824
11825void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11826 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11827 SourceLocation Loc) {
11828 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11828)
;
11829}
11830
11831void CGOpenMPSIMDRuntime::emitSingleRegion(
11832 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11833 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11834 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11835 ArrayRef<const Expr *> AssignmentOps) {
11836 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11836)
;
11837}
11838
11839void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11840 const RegionCodeGenTy &OrderedOpGen,
11841 SourceLocation Loc,
11842 bool IsThreads) {
11843 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11843)
;
11844}
11845
11846void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11847 SourceLocation Loc,
11848 OpenMPDirectiveKind Kind,
11849 bool EmitChecks,
11850 bool ForceSimpleCall) {
11851 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11851)
;
11852}
11853
11854void CGOpenMPSIMDRuntime::emitForDispatchInit(
11855 CodeGenFunction &CGF, SourceLocation Loc,
11856 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11857 bool Ordered, const DispatchRTInput &DispatchValues) {
11858 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11858)
;
11859}
11860
11861void CGOpenMPSIMDRuntime::emitForStaticInit(
11862 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11863 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11864 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11864)
;
11865}
11866
11867void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11868 CodeGenFunction &CGF, SourceLocation Loc,
11869 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11870 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11870)
;
11871}
11872
11873void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11874 SourceLocation Loc,
11875 unsigned IVSize,
11876 bool IVSigned) {
11877 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11877)
;
11878}
11879
11880void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11881 SourceLocation Loc,
11882 OpenMPDirectiveKind DKind) {
11883 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11883)
;
11884}
11885
11886llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11887 SourceLocation Loc,
11888 unsigned IVSize, bool IVSigned,
11889 Address IL, Address LB,
11890 Address UB, Address ST) {
11891 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11891)
;
11892}
11893
11894void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11895 llvm::Value *NumThreads,
11896 SourceLocation Loc) {
11897 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11897)
;
11898}
11899
11900void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
11901 ProcBindKind ProcBind,
11902 SourceLocation Loc) {
11903 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11903)
;
11904}
11905
11906Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11907 const VarDecl *VD,
11908 Address VDAddr,
11909 SourceLocation Loc) {
11910 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11910)
;
11911}
11912
11913llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11914 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11915 CodeGenFunction *CGF) {
11916 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11916)
;
11917}
11918
11919Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11920 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11921 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11921)
;
11922}
11923
11924void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11925 ArrayRef<const Expr *> Vars,
11926 SourceLocation Loc,
11927 llvm::AtomicOrdering AO) {
11928 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11928)
;
11929}
11930
11931void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11932 const OMPExecutableDirective &D,
11933 llvm::Function *TaskFunction,
11934 QualType SharedsTy, Address Shareds,
11935 const Expr *IfCond,
11936 const OMPTaskDataTy &Data) {
11937 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11937)
;
11938}
11939
11940void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11941 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
11942 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
11943 const Expr *IfCond, const OMPTaskDataTy &Data) {
11944 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11944)
;
11945}
11946
11947void CGOpenMPSIMDRuntime::emitReduction(
11948 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11949 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11950 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11951 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-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11951, __PRETTY_FUNCTION__))
;
11952 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
11953 ReductionOps, Options);
11954}
11955
11956llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
11957 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
11958 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
11959 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11959)
;
11960}
11961
11962void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
11963 SourceLocation Loc,
11964 ReductionCodeGen &RCG,
11965 unsigned N) {
11966 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11966)
;
11967}
11968
11969Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
11970 SourceLocation Loc,
11971 llvm::Value *ReductionsPtr,
11972 LValue SharedLVal) {
11973 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11973)
;
11974}
11975
11976void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
11977 SourceLocation Loc) {
11978 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11978)
;
11979}
11980
11981void CGOpenMPSIMDRuntime::emitCancellationPointCall(
11982 CodeGenFunction &CGF, SourceLocation Loc,
11983 OpenMPDirectiveKind CancelRegion) {
11984 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11984)
;
11985}
11986
11987void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
11988 SourceLocation Loc, const Expr *IfCond,
11989 OpenMPDirectiveKind CancelRegion) {
11990 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11990)
;
11991}
11992
11993void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
11994 const OMPExecutableDirective &D, StringRef ParentName,
11995 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11996 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
11997 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11997)
;
11998}
11999
12000void CGOpenMPSIMDRuntime::emitTargetCall(
12001 CodeGenFunction &CGF, const OMPExecutableDirective &D,
12002 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
12003 const Expr *Device,
12004 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
12005 const OMPLoopDirective &D)>
12006 SizeEmitter) {
12007 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12007)
;
12008}
12009
12010bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
12011 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12011)
;
12012}
12013
12014bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
12015 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12015)
;
12016}
12017
12018bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
12019 return false;
12020}
12021
12022void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
12023 const OMPExecutableDirective &D,
12024 SourceLocation Loc,
12025 llvm::Function *OutlinedFn,
12026 ArrayRef<llvm::Value *> CapturedVars) {
12027 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12027)
;
12028}
12029
12030void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
12031 const Expr *NumTeams,
12032 const Expr *ThreadLimit,
12033 SourceLocation Loc) {
12034 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12034)
;
12035}
12036
12037void CGOpenMPSIMDRuntime::emitTargetDataCalls(
12038 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
12039 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
12040 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12040)
;
12041}
12042
12043void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
12044 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
12045 const Expr *Device) {
12046 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12046)
;
12047}
12048
12049void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
12050 const OMPLoopDirective &D,
12051 ArrayRef<Expr *> NumIterations) {
12052 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12052)
;
12053}
12054
12055void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
12056 const OMPDependClause *C) {
12057 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12057)
;
12058}
12059
12060const VarDecl *
12061CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
12062 const VarDecl *NativeParam) const {
12063 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12063)
;
12064}
12065
12066Address
12067CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
12068 const VarDecl *NativeParam,
12069 const VarDecl *TargetParam) const {
12070 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12070)
;
12071}

/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ADT/Optional.h

1//===- Optional.h - Simple variant for passing optional values --*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file provides Optional, a template class modeled in the spirit of
10// OCaml's 'opt' variant. The idea is to strongly type whether or not
11// a value can be optional.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_ADT_OPTIONAL_H
16#define LLVM_ADT_OPTIONAL_H
17
18#include "llvm/ADT/None.h"
19#include "llvm/Support/Compiler.h"
20#include "llvm/Support/type_traits.h"
21#include <cassert>
22#include <memory>
23#include <new>
24#include <utility>
25
26namespace llvm {
27
28class raw_ostream;
29
30namespace optional_detail {
31
32struct in_place_t {};
33
34/// Storage for any type.
35template <typename T, bool = is_trivially_copyable<T>::value>
36class OptionalStorage {
37 union {
38 char empty;
39 T value;
40 };
41 bool hasVal;
42
43public:
44 ~OptionalStorage() { reset(); }
45
46 OptionalStorage() noexcept : empty(), hasVal(false) {}
47
48 OptionalStorage(OptionalStorage const &other) : OptionalStorage() {
49 if (other.hasValue()) {
50 emplace(other.value);
51 }
52 }
53 OptionalStorage(OptionalStorage &&other) : OptionalStorage() {
54 if (other.hasValue()) {
55 emplace(std::move(other.value));
56 }
57 }
58
59 template <class... Args>
60 explicit OptionalStorage(in_place_t, Args &&... args)
61 : value(std::forward<Args>(args)...), hasVal(true) {}
62
63 void reset() noexcept {
64 if (hasVal) {
65 value.~T();
66 hasVal = false;
67 }
68 }
69
70 bool hasValue() const noexcept { return hasVal; }
71
72 T &getValue() LLVM_LVALUE_FUNCTION& noexcept {
73 assert(hasVal)((hasVal) ? static_cast<void> (0) : __assert_fail ("hasVal"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ADT/Optional.h"
, 73, __PRETTY_FUNCTION__))
;
74 return value;
75 }
76 T const &getValue() const LLVM_LVALUE_FUNCTION& noexcept {
77 assert(hasVal)((hasVal) ? static_cast<void> (0) : __assert_fail ("hasVal"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ADT/Optional.h"
, 77, __PRETTY_FUNCTION__))
;
78 return value;
79 }
80#if LLVM_HAS_RVALUE_REFERENCE_THIS1
81 T &&getValue() && noexcept {
82 assert(hasVal)((hasVal) ? static_cast<void> (0) : __assert_fail ("hasVal"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ADT/Optional.h"
, 82, __PRETTY_FUNCTION__))
;
83 return std::move(value);
84 }
85#endif
86
87 template <class... Args> void emplace(Args &&... args) {
88 reset();
89 ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...);
90 hasVal = true;
91 }
92
93 OptionalStorage &operator=(T const &y) {
94 if (hasValue()) {
95 value = y;
96 } else {
97 ::new ((void *)std::addressof(value)) T(y);
98 hasVal = true;
99 }
100 return *this;
101 }
102 OptionalStorage &operator=(T &&y) {
103 if (hasValue()) {
104 value = std::move(y);
105 } else {
106 ::new ((void *)std::addressof(value)) T(std::move(y));
107 hasVal = true;
108 }
109 return *this;
110 }
111
112 OptionalStorage &operator=(OptionalStorage const &other) {
113 if (other.hasValue()) {
114 if (hasValue()) {
115 value = other.value;
116 } else {
117 ::new ((void *)std::addressof(value)) T(other.value);
118 hasVal = true;
119 }
120 } else {
121 reset();
122 }
123 return *this;
124 }
125
126 OptionalStorage &operator=(OptionalStorage &&other) {
127 if (other.hasValue()) {
128 if (hasValue()) {
129 value = std::move(other.value);
130 } else {
131 ::new ((void *)std::addressof(value)) T(std::move(other.value));
132 hasVal = true;
133 }
134 } else {
135 reset();
136 }
137 return *this;
138 }
139};
140
141template <typename T> class OptionalStorage<T, true> {
142 union {
143 char empty;
144 T value;
145 };
146 bool hasVal = false;
147
148public:
149 ~OptionalStorage() = default;
150
151 OptionalStorage() noexcept : empty{} {}
152
153 OptionalStorage(OptionalStorage const &other) = default;
154 OptionalStorage(OptionalStorage &&other) = default;
155
156 OptionalStorage &operator=(OptionalStorage const &other) = default;
157 OptionalStorage &operator=(OptionalStorage &&other) = default;
158
159 template <class... Args>
160 explicit OptionalStorage(in_place_t, Args &&... args)
161 : value(std::forward<Args>(args)...), hasVal(true) {}
162
163 void reset() noexcept {
164 if (hasVal) {
165 value.~T();
166 hasVal = false;
167 }
168 }
169
170 bool hasValue() const noexcept { return hasVal; }
5
Returning the value 1, which participates in a condition later
171
172 T &getValue() LLVM_LVALUE_FUNCTION& noexcept {
173 assert(hasVal)((hasVal) ? static_cast<void> (0) : __assert_fail ("hasVal"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ADT/Optional.h"
, 173, __PRETTY_FUNCTION__))
;
174 return value;
175 }
176 T const &getValue() const LLVM_LVALUE_FUNCTION& noexcept {
177 assert(hasVal)((hasVal) ? static_cast<void> (0) : __assert_fail ("hasVal"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ADT/Optional.h"
, 177, __PRETTY_FUNCTION__))
;
178 return value;
179 }
180#if LLVM_HAS_RVALUE_REFERENCE_THIS1
181 T &&getValue() && noexcept {
182 assert(hasVal)((hasVal) ? static_cast<void> (0) : __assert_fail ("hasVal"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ADT/Optional.h"
, 182, __PRETTY_FUNCTION__))
;
183 return std::move(value);
184 }
185#endif
186
187 template <class... Args> void emplace(Args &&... args) {
188 reset();
189 ::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...);
190 hasVal = true;
191 }
192
193 OptionalStorage &operator=(T const &y) {
194 if (hasValue()) {
195 value = y;
196 } else {
197 ::new ((void *)std::addressof(value)) T(y);
198 hasVal = true;
199 }
200 return *this;
201 }
202 OptionalStorage &operator=(T &&y) {
203 if (hasValue()) {
204 value = std::move(y);
205 } else {
206 ::new ((void *)std::addressof(value)) T(std::move(y));
207 hasVal = true;
208 }
209 return *this;
210 }
211};
212
213} // namespace optional_detail
214
215template <typename T> class Optional {
216 optional_detail::OptionalStorage<T> Storage;
217
218public:
219 using value_type = T;
220
221 constexpr Optional() {}
222 constexpr Optional(NoneType) {}
223
224 Optional(const T &y) : Storage(optional_detail::in_place_t{}, y) {}
225 Optional(const Optional &O) = default;
226
227 Optional(T &&y) : Storage(optional_detail::in_place_t{}, std::move(y)) {}
228 Optional(Optional &&O) = default;
229
230 Optional &operator=(T &&y) {
231 Storage = std::move(y);
232 return *this;
233 }
234 Optional &operator=(Optional &&O) = default;
235
236 /// Create a new object by constructing it in place with the given arguments.
237 template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
238 Storage.emplace(std::forward<ArgTypes>(Args)...);
239 }
240
241 static inline Optional create(const T *y) {
242 return y ? Optional(*y) : Optional();
243 }
244
245 Optional &operator=(const T &y) {
246 Storage = y;
247 return *this;
248 }
249 Optional &operator=(const Optional &O) = default;
250
251 void reset() { Storage.reset(); }
252
253 const T *getPointer() const { return &Storage.getValue(); }
254 T *getPointer() { return &Storage.getValue(); }
255 const T &getValue() const LLVM_LVALUE_FUNCTION& { return Storage.getValue(); }
256 T &getValue() LLVM_LVALUE_FUNCTION& { return Storage.getValue(); }
257
258 explicit operator bool() const { return hasValue(); }
3
Calling 'Optional::hasValue'
8
Returning from 'Optional::hasValue'
9
Returning the value 1, which participates in a condition later
259 bool hasValue() const { return Storage.hasValue(); }
4
Calling 'OptionalStorage::hasValue'
6
Returning from 'OptionalStorage::hasValue'
7
Returning the value 1, which participates in a condition later
260 const T *operator->() const { return getPointer(); }
261 T *operator->() { return getPointer(); }
262 const T &operator*() const LLVM_LVALUE_FUNCTION& { return getValue(); }
263 T &operator*() LLVM_LVALUE_FUNCTION& { return getValue(); }
264
265 template <typename U>
266 constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION& {
267 return hasValue() ? getValue() : std::forward<U>(value);
268 }
269
270 /// Apply a function to the value if present; otherwise return None.
271 template <class Function>
272 auto map(const Function &F) const LLVM_LVALUE_FUNCTION&
273 -> Optional<decltype(F(getValue()))> {
274 if (*this) return F(getValue());
275 return None;
276 }
277
278#if LLVM_HAS_RVALUE_REFERENCE_THIS1
279 T &&getValue() && { return std::move(Storage.getValue()); }
280 T &&operator*() && { return std::move(Storage.getValue()); }
281
282 template <typename U>
283 T getValueOr(U &&value) && {
284 return hasValue() ? std::move(getValue()) : std::forward<U>(value);
285 }
286
287 /// Apply a function to the value if present; otherwise return None.
288 template <class Function>
289 auto map(const Function &F) &&
290 -> Optional<decltype(F(std::move(*this).getValue()))> {
291 if (*this) return F(std::move(*this).getValue());
292 return None;
293 }
294#endif
295};
296
297template <typename T, typename U>
298bool operator==(const Optional<T> &X, const Optional<U> &Y) {
299 if (X && Y)
300 return *X == *Y;
301 return X.hasValue() == Y.hasValue();
302}
303
304template <typename T, typename U>
305bool operator!=(const Optional<T> &X, const Optional<U> &Y) {
306 return !(X == Y);
307}
308
309template <typename T, typename U>
310bool operator<(const Optional<T> &X, const Optional<U> &Y) {
311 if (X && Y)
312 return *X < *Y;
313 return X.hasValue() < Y.hasValue();
314}
315
316template <typename T, typename U>
317bool operator<=(const Optional<T> &X, const Optional<U> &Y) {
318 return !(Y < X);
319}
320
321template <typename T, typename U>
322bool operator>(const Optional<T> &X, const Optional<U> &Y) {
323 return Y < X;
324}
325
326template <typename T, typename U>
327bool operator>=(const Optional<T> &X, const Optional<U> &Y) {
328 return !(X < Y);
329}
330
331template<typename T>
332bool operator==(const Optional<T> &X, NoneType) {
333 return !X;
334}
335
336template<typename T>
337bool operator==(NoneType, const Optional<T> &X) {
338 return X == None;
339}
340
341template<typename T>
342bool operator!=(const Optional<T> &X, NoneType) {
343 return !(X == None);
344}
345
346template<typename T>
347bool operator!=(NoneType, const Optional<T> &X) {
348 return X != None;
349}
350
351template <typename T> bool operator<(const Optional<T> &X, NoneType) {
352 return false;
353}
354
355template <typename T> bool operator<(NoneType, const Optional<T> &X) {
356 return X.hasValue();
357}
358
359template <typename T> bool operator<=(const Optional<T> &X, NoneType) {
360 return !(None < X);
361}
362
363template <typename T> bool operator<=(NoneType, const Optional<T> &X) {
364 return !(X < None);
365}
366
367template <typename T> bool operator>(const Optional<T> &X, NoneType) {
368 return None < X;
369}
370
371template <typename T> bool operator>(NoneType, const Optional<T> &X) {
372 return X < None;
373}
374
375template <typename T> bool operator>=(const Optional<T> &X, NoneType) {
376 return None <= X;
377}
378
379template <typename T> bool operator>=(NoneType, const Optional<T> &X) {
380 return X <= None;
381}
382
383template <typename T> bool operator==(const Optional<T> &X, const T &Y) {
384 return X && *X == Y;
385}
386
387template <typename T> bool operator==(const T &X, const Optional<T> &Y) {
388 return Y && X == *Y;
389}
390
391template <typename T> bool operator!=(const Optional<T> &X, const T &Y) {
392 return !(X == Y);
393}
394
395template <typename T> bool operator!=(const T &X, const Optional<T> &Y) {
396 return !(X == Y);
397}
398
399template <typename T> bool operator<(const Optional<T> &X, const T &Y) {
400 return !X || *X < Y;
401}
402
403template <typename T> bool operator<(const T &X, const Optional<T> &Y) {
404 return Y && X < *Y;
405}
406
407template <typename T> bool operator<=(const Optional<T> &X, const T &Y) {
408 return !(Y < X);
409}
410
411template <typename T> bool operator<=(const T &X, const Optional<T> &Y) {
412 return !(Y < X);
413}
414
415template <typename T> bool operator>(const Optional<T> &X, const T &Y) {
416 return Y < X;
417}
418
419template <typename T> bool operator>(const T &X, const Optional<T> &Y) {
420 return Y < X;
421}
422
423template <typename T> bool operator>=(const Optional<T> &X, const T &Y) {
424 return !(X < Y);
425}
426
427template <typename T> bool operator>=(const T &X, const Optional<T> &Y) {
428 return !(X < Y);
429}
430
431raw_ostream &operator<<(raw_ostream &OS, NoneType);
432
433template <typename T, typename = decltype(std::declval<raw_ostream &>()
434 << std::declval<const T &>())>
435raw_ostream &operator<<(raw_ostream &OS, const Optional<T> &O) {
436 if (O)
437 OS << *O;
438 else
439 OS << None;
440 return OS;
441}
442
443} // end namespace llvm
444
445#endif // LLVM_ADT_OPTIONAL_H