Bug Summary

File:clang/lib/CodeGen/CGOpenMPRuntime.cpp
Warning:line 8082, column 9
2nd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name CGOpenMPRuntime.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -relaxed-aliasing -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/build-llvm/tools/clang/lib/CodeGen -resource-dir /usr/lib/llvm-13/lib/clang/13.0.0 -D CLANG_ROUND_TRIP_CC1_ARGS=ON -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/build-llvm/tools/clang/lib/CodeGen -I /build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen -I /build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/include -I /build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/build-llvm/include -I /build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/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/c++/6.3.0/backward -internal-isystem /usr/lib/llvm-13/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../x86_64-linux-gnu/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-13~++20210413100635+64c24f493e5f/build-llvm/tools/clang/lib/CodeGen -fdebug-prefix-map=/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f=. -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-04-14-063029-18377-1 -x c++ /build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp

/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp

1//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This provides a class for OpenMP runtime code generation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CGOpenMPRuntime.h"
14#include "CGCXXABI.h"
15#include "CGCleanup.h"
16#include "CGRecordLayout.h"
17#include "CodeGenFunction.h"
18#include "clang/AST/Attr.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/OpenMPClause.h"
21#include "clang/AST/StmtOpenMP.h"
22#include "clang/AST/StmtVisitor.h"
23#include "clang/Basic/BitmaskEnum.h"
24#include "clang/Basic/FileManager.h"
25#include "clang/Basic/OpenMPKinds.h"
26#include "clang/Basic/SourceManager.h"
27#include "clang/CodeGen/ConstantInitBuilder.h"
28#include "llvm/ADT/ArrayRef.h"
29#include "llvm/ADT/SetOperations.h"
30#include "llvm/ADT/StringExtras.h"
31#include "llvm/Bitcode/BitcodeReader.h"
32#include "llvm/IR/Constants.h"
33#include "llvm/IR/DerivedTypes.h"
34#include "llvm/IR/GlobalValue.h"
35#include "llvm/IR/Value.h"
36#include "llvm/Support/AtomicOrdering.h"
37#include "llvm/Support/Format.h"
38#include "llvm/Support/raw_ostream.h"
39#include <cassert>
40#include <numeric>
41
42using namespace clang;
43using namespace CodeGen;
44using namespace llvm::omp;
45
46namespace {
47/// Base class for handling code generation inside OpenMP regions.
48class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
49public:
50 /// Kinds of OpenMP regions used in codegen.
51 enum CGOpenMPRegionKind {
52 /// Region with outlined function for standalone 'parallel'
53 /// directive.
54 ParallelOutlinedRegion,
55 /// Region with outlined function for standalone 'task' directive.
56 TaskOutlinedRegion,
57 /// Region for constructs that do not require function outlining,
58 /// like 'for', 'sections', 'atomic' etc. directives.
59 InlinedRegion,
60 /// Region with outlined function for standalone 'target' directive.
61 TargetRegion,
62 };
63
64 CGOpenMPRegionInfo(const CapturedStmt &CS,
65 const CGOpenMPRegionKind RegionKind,
66 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
67 bool HasCancel)
68 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
69 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
70
71 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
72 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
73 bool HasCancel)
74 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
75 Kind(Kind), HasCancel(HasCancel) {}
76
77 /// Get a variable or parameter for storing global thread id
78 /// inside OpenMP construct.
79 virtual const VarDecl *getThreadIDVariable() const = 0;
80
81 /// Emit the captured statement body.
82 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
83
84 /// Get an LValue for the current ThreadID variable.
85 /// \return LValue for thread id variable. This LValue always has type int32*.
86 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
87
88 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
89
90 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
91
92 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
93
94 bool hasCancel() const { return HasCancel; }
95
96 static bool classof(const CGCapturedStmtInfo *Info) {
97 return Info->getKind() == CR_OpenMP;
98 }
99
100 ~CGOpenMPRegionInfo() override = default;
101
102protected:
103 CGOpenMPRegionKind RegionKind;
104 RegionCodeGenTy CodeGen;
105 OpenMPDirectiveKind Kind;
106 bool HasCancel;
107};
108
109/// API for captured statement code generation in OpenMP constructs.
110class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
111public:
112 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
113 const RegionCodeGenTy &CodeGen,
114 OpenMPDirectiveKind Kind, bool HasCancel,
115 StringRef HelperName)
116 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
117 HasCancel),
118 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
119 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.")((ThreadIDVar != nullptr && "No ThreadID in OpenMP region."
) ? static_cast<void> (0) : __assert_fail ("ThreadIDVar != nullptr && \"No ThreadID in OpenMP region.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 119, __PRETTY_FUNCTION__))
;
120 }
121
122 /// Get a variable or parameter for storing global thread id
123 /// inside OpenMP construct.
124 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
125
126 /// Get the name of the capture helper.
127 StringRef getHelperName() const override { return HelperName; }
128
129 static bool classof(const CGCapturedStmtInfo *Info) {
130 return CGOpenMPRegionInfo::classof(Info) &&
131 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
132 ParallelOutlinedRegion;
133 }
134
135private:
136 /// A variable or parameter storing global thread id for OpenMP
137 /// constructs.
138 const VarDecl *ThreadIDVar;
139 StringRef HelperName;
140};
141
142/// API for captured statement code generation in OpenMP constructs.
143class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
144public:
145 class UntiedTaskActionTy final : public PrePostActionTy {
146 bool Untied;
147 const VarDecl *PartIDVar;
148 const RegionCodeGenTy UntiedCodeGen;
149 llvm::SwitchInst *UntiedSwitch = nullptr;
150
151 public:
152 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
153 const RegionCodeGenTy &UntiedCodeGen)
154 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
155 void Enter(CodeGenFunction &CGF) override {
156 if (Untied) {
157 // Emit task switching point.
158 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
159 CGF.GetAddrOfLocalVar(PartIDVar),
160 PartIDVar->getType()->castAs<PointerType>());
161 llvm::Value *Res =
162 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation());
163 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done.");
164 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
165 CGF.EmitBlock(DoneBB);
166 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
167 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
168 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
169 CGF.Builder.GetInsertBlock());
170 emitUntiedSwitch(CGF);
171 }
172 }
173 void emitUntiedSwitch(CodeGenFunction &CGF) const {
174 if (Untied) {
175 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
176 CGF.GetAddrOfLocalVar(PartIDVar),
177 PartIDVar->getType()->castAs<PointerType>());
178 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
179 PartIdLVal);
180 UntiedCodeGen(CGF);
181 CodeGenFunction::JumpDest CurPoint =
182 CGF.getJumpDestInCurrentScope(".untied.next.");
183 CGF.EmitBranch(CGF.ReturnBlock.getBlock());
184 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
185 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
186 CGF.Builder.GetInsertBlock());
187 CGF.EmitBranchThroughCleanup(CurPoint);
188 CGF.EmitBlock(CurPoint.getBlock());
189 }
190 }
191 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
192 };
193 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
194 const VarDecl *ThreadIDVar,
195 const RegionCodeGenTy &CodeGen,
196 OpenMPDirectiveKind Kind, bool HasCancel,
197 const UntiedTaskActionTy &Action)
198 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
199 ThreadIDVar(ThreadIDVar), Action(Action) {
200 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.")((ThreadIDVar != nullptr && "No ThreadID in OpenMP region."
) ? static_cast<void> (0) : __assert_fail ("ThreadIDVar != nullptr && \"No ThreadID in OpenMP region.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 200, __PRETTY_FUNCTION__))
;
201 }
202
203 /// Get a variable or parameter for storing global thread id
204 /// inside OpenMP construct.
205 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
206
207 /// Get an LValue for the current ThreadID variable.
208 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
209
210 /// Get the name of the capture helper.
211 StringRef getHelperName() const override { return ".omp_outlined."; }
212
213 void emitUntiedSwitch(CodeGenFunction &CGF) override {
214 Action.emitUntiedSwitch(CGF);
215 }
216
217 static bool classof(const CGCapturedStmtInfo *Info) {
218 return CGOpenMPRegionInfo::classof(Info) &&
219 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
220 TaskOutlinedRegion;
221 }
222
223private:
224 /// A variable or parameter storing global thread id for OpenMP
225 /// constructs.
226 const VarDecl *ThreadIDVar;
227 /// Action for emitting code for untied tasks.
228 const UntiedTaskActionTy &Action;
229};
230
231/// API for inlined captured statement code generation in OpenMP
232/// constructs.
233class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
234public:
235 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
236 const RegionCodeGenTy &CodeGen,
237 OpenMPDirectiveKind Kind, bool HasCancel)
238 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
239 OldCSI(OldCSI),
240 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
241
242 // Retrieve the value of the context parameter.
243 llvm::Value *getContextValue() const override {
244 if (OuterRegionInfo)
245 return OuterRegionInfo->getContextValue();
246 llvm_unreachable("No context value for inlined OpenMP region")::llvm::llvm_unreachable_internal("No context value for inlined OpenMP region"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 246)
;
247 }
248
249 void setContextValue(llvm::Value *V) override {
250 if (OuterRegionInfo) {
251 OuterRegionInfo->setContextValue(V);
252 return;
253 }
254 llvm_unreachable("No context value for inlined OpenMP region")::llvm::llvm_unreachable_internal("No context value for inlined OpenMP region"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 254)
;
255 }
256
257 /// Lookup the captured field decl for a variable.
258 const FieldDecl *lookup(const VarDecl *VD) const override {
259 if (OuterRegionInfo)
260 return OuterRegionInfo->lookup(VD);
261 // If there is no outer outlined region,no need to lookup in a list of
262 // captured variables, we can use the original one.
263 return nullptr;
264 }
265
266 FieldDecl *getThisFieldDecl() const override {
267 if (OuterRegionInfo)
268 return OuterRegionInfo->getThisFieldDecl();
269 return nullptr;
270 }
271
272 /// Get a variable or parameter for storing global thread id
273 /// inside OpenMP construct.
274 const VarDecl *getThreadIDVariable() const override {
275 if (OuterRegionInfo)
276 return OuterRegionInfo->getThreadIDVariable();
277 return nullptr;
278 }
279
280 /// Get an LValue for the current ThreadID variable.
281 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override {
282 if (OuterRegionInfo)
283 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
284 llvm_unreachable("No LValue for inlined OpenMP construct")::llvm::llvm_unreachable_internal("No LValue for inlined OpenMP construct"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 284)
;
285 }
286
287 /// Get the name of the capture helper.
288 StringRef getHelperName() const override {
289 if (auto *OuterRegionInfo = getOldCSI())
290 return OuterRegionInfo->getHelperName();
291 llvm_unreachable("No helper name for inlined OpenMP construct")::llvm::llvm_unreachable_internal("No helper name for inlined OpenMP construct"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 291)
;
292 }
293
294 void emitUntiedSwitch(CodeGenFunction &CGF) override {
295 if (OuterRegionInfo)
296 OuterRegionInfo->emitUntiedSwitch(CGF);
297 }
298
299 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
300
301 static bool classof(const CGCapturedStmtInfo *Info) {
302 return CGOpenMPRegionInfo::classof(Info) &&
303 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
304 }
305
306 ~CGOpenMPInlinedRegionInfo() override = default;
307
308private:
309 /// CodeGen info about outer OpenMP region.
310 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
311 CGOpenMPRegionInfo *OuterRegionInfo;
312};
313
314/// API for captured statement code generation in OpenMP target
315/// constructs. For this captures, implicit parameters are used instead of the
316/// captured fields. The name of the target region has to be unique in a given
317/// application so it is provided by the client, because only the client has
318/// the information to generate that.
319class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
320public:
321 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
322 const RegionCodeGenTy &CodeGen, StringRef HelperName)
323 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
324 /*HasCancel=*/false),
325 HelperName(HelperName) {}
326
327 /// This is unused for target regions because each starts executing
328 /// with a single thread.
329 const VarDecl *getThreadIDVariable() const override { return nullptr; }
330
331 /// Get the name of the capture helper.
332 StringRef getHelperName() const override { return HelperName; }
333
334 static bool classof(const CGCapturedStmtInfo *Info) {
335 return CGOpenMPRegionInfo::classof(Info) &&
336 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
337 }
338
339private:
340 StringRef HelperName;
341};
342
343static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
344 llvm_unreachable("No codegen for expressions")::llvm::llvm_unreachable_internal("No codegen for expressions"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 344)
;
345}
346/// API for generation of expressions captured in a innermost OpenMP
347/// region.
348class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
349public:
350 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
351 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
352 OMPD_unknown,
353 /*HasCancel=*/false),
354 PrivScope(CGF) {
355 // Make sure the globals captured in the provided statement are local by
356 // using the privatization logic. We assume the same variable is not
357 // captured more than once.
358 for (const auto &C : CS.captures()) {
359 if (!C.capturesVariable() && !C.capturesVariableByCopy())
360 continue;
361
362 const VarDecl *VD = C.getCapturedVar();
363 if (VD->isLocalVarDeclOrParm())
364 continue;
365
366 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
367 /*RefersToEnclosingVariableOrCapture=*/false,
368 VD->getType().getNonReferenceType(), VK_LValue,
369 C.getLocation());
370 PrivScope.addPrivate(
371 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); });
372 }
373 (void)PrivScope.Privatize();
374 }
375
376 /// Lookup the captured field decl for a variable.
377 const FieldDecl *lookup(const VarDecl *VD) const override {
378 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
379 return FD;
380 return nullptr;
381 }
382
383 /// Emit the captured statement body.
384 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
385 llvm_unreachable("No body for expressions")::llvm::llvm_unreachable_internal("No body for expressions", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 385)
;
386 }
387
388 /// Get a variable or parameter for storing global thread id
389 /// inside OpenMP construct.
390 const VarDecl *getThreadIDVariable() const override {
391 llvm_unreachable("No thread id for expressions")::llvm::llvm_unreachable_internal("No thread id for expressions"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 391)
;
392 }
393
394 /// Get the name of the capture helper.
395 StringRef getHelperName() const override {
396 llvm_unreachable("No helper name for expressions")::llvm::llvm_unreachable_internal("No helper name for expressions"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 396)
;
397 }
398
399 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
400
401private:
402 /// Private scope to capture global variables.
403 CodeGenFunction::OMPPrivateScope PrivScope;
404};
405
406/// RAII for emitting code of OpenMP constructs.
407class InlinedOpenMPRegionRAII {
408 CodeGenFunction &CGF;
409 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
410 FieldDecl *LambdaThisCaptureField = nullptr;
411 const CodeGen::CGBlockInfo *BlockInfo = nullptr;
412 bool NoInheritance = false;
413
414public:
415 /// Constructs region for combined constructs.
416 /// \param CodeGen Code generation sequence for combined directives. Includes
417 /// a list of functions used for code generation of implicitly inlined
418 /// regions.
419 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
420 OpenMPDirectiveKind Kind, bool HasCancel,
421 bool NoInheritance = true)
422 : CGF(CGF), NoInheritance(NoInheritance) {
423 // Start emission for the construct.
424 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
425 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
426 if (NoInheritance) {
427 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
428 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
429 CGF.LambdaThisCaptureField = nullptr;
430 BlockInfo = CGF.BlockInfo;
431 CGF.BlockInfo = nullptr;
432 }
433 }
434
435 ~InlinedOpenMPRegionRAII() {
436 // Restore original CapturedStmtInfo only if we're done with code emission.
437 auto *OldCSI =
438 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
439 delete CGF.CapturedStmtInfo;
440 CGF.CapturedStmtInfo = OldCSI;
441 if (NoInheritance) {
442 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
443 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
444 CGF.BlockInfo = BlockInfo;
445 }
446 }
447};
448
449/// Values for bit flags used in the ident_t to describe the fields.
450/// All enumeric elements are named and described in accordance with the code
451/// from https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h
452enum OpenMPLocationFlags : unsigned {
453 /// Use trampoline for internal microtask.
454 OMP_IDENT_IMD = 0x01,
455 /// Use c-style ident structure.
456 OMP_IDENT_KMPC = 0x02,
457 /// Atomic reduction option for kmpc_reduce.
458 OMP_ATOMIC_REDUCE = 0x10,
459 /// Explicit 'barrier' directive.
460 OMP_IDENT_BARRIER_EXPL = 0x20,
461 /// Implicit barrier in code.
462 OMP_IDENT_BARRIER_IMPL = 0x40,
463 /// Implicit barrier in 'for' directive.
464 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
465 /// Implicit barrier in 'sections' directive.
466 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
467 /// Implicit barrier in 'single' directive.
468 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
469 /// Call of __kmp_for_static_init for static loop.
470 OMP_IDENT_WORK_LOOP = 0x200,
471 /// Call of __kmp_for_static_init for sections.
472 OMP_IDENT_WORK_SECTIONS = 0x400,
473 /// Call of __kmp_for_static_init for distribute.
474 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
475 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_IDENT_WORK_DISTRIBUTE
476};
477
478namespace {
479LLVM_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^=
;
480/// Values for bit flags for marking which requires clauses have been used.
481enum OpenMPOffloadingRequiresDirFlags : int64_t {
482 /// flag undefined.
483 OMP_REQ_UNDEFINED = 0x000,
484 /// no requires clause present.
485 OMP_REQ_NONE = 0x001,
486 /// reverse_offload clause.
487 OMP_REQ_REVERSE_OFFLOAD = 0x002,
488 /// unified_address clause.
489 OMP_REQ_UNIFIED_ADDRESS = 0x004,
490 /// unified_shared_memory clause.
491 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
492 /// dynamic_allocators clause.
493 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
494 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_REQ_DYNAMIC_ALLOCATORS
495};
496
497enum OpenMPOffloadingReservedDeviceIDs {
498 /// Device ID if the device was not defined, runtime should get it
499 /// from environment variables in the spec.
500 OMP_DEVICEID_UNDEF = -1,
501};
502} // anonymous namespace
503
504/// Describes ident structure that describes a source location.
505/// All descriptions are taken from
506/// https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h
507/// Original structure:
508/// typedef struct ident {
509/// kmp_int32 reserved_1; /**< might be used in Fortran;
510/// see above */
511/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
512/// KMP_IDENT_KMPC identifies this union
513/// member */
514/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
515/// see above */
516///#if USE_ITT_BUILD
517/// /* but currently used for storing
518/// region-specific ITT */
519/// /* contextual information. */
520///#endif /* USE_ITT_BUILD */
521/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
522/// C++ */
523/// char const *psource; /**< String describing the source location.
524/// The string is composed of semi-colon separated
525// fields which describe the source file,
526/// the function and a pair of line numbers that
527/// delimit the construct.
528/// */
529/// } ident_t;
530enum IdentFieldIndex {
531 /// might be used in Fortran
532 IdentField_Reserved_1,
533 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
534 IdentField_Flags,
535 /// Not really used in Fortran any more
536 IdentField_Reserved_2,
537 /// Source[4] in Fortran, do not use for C++
538 IdentField_Reserved_3,
539 /// String describing the source location. The string is composed of
540 /// semi-colon separated fields which describe the source file, the function
541 /// and a pair of line numbers that delimit the construct.
542 IdentField_PSource
543};
544
545/// Schedule types for 'omp for' loops (these enumerators are taken from
546/// the enum sched_type in kmp.h).
547enum OpenMPSchedType {
548 /// Lower bound for default (unordered) versions.
549 OMP_sch_lower = 32,
550 OMP_sch_static_chunked = 33,
551 OMP_sch_static = 34,
552 OMP_sch_dynamic_chunked = 35,
553 OMP_sch_guided_chunked = 36,
554 OMP_sch_runtime = 37,
555 OMP_sch_auto = 38,
556 /// static with chunk adjustment (e.g., simd)
557 OMP_sch_static_balanced_chunked = 45,
558 /// Lower bound for 'ordered' versions.
559 OMP_ord_lower = 64,
560 OMP_ord_static_chunked = 65,
561 OMP_ord_static = 66,
562 OMP_ord_dynamic_chunked = 67,
563 OMP_ord_guided_chunked = 68,
564 OMP_ord_runtime = 69,
565 OMP_ord_auto = 70,
566 OMP_sch_default = OMP_sch_static,
567 /// dist_schedule types
568 OMP_dist_sch_static_chunked = 91,
569 OMP_dist_sch_static = 92,
570 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
571 /// Set if the monotonic schedule modifier was present.
572 OMP_sch_modifier_monotonic = (1 << 29),
573 /// Set if the nonmonotonic schedule modifier was present.
574 OMP_sch_modifier_nonmonotonic = (1 << 30),
575};
576
577/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
578/// region.
579class CleanupTy final : public EHScopeStack::Cleanup {
580 PrePostActionTy *Action;
581
582public:
583 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
584 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
585 if (!CGF.HaveInsertPoint())
586 return;
587 Action->Exit(CGF);
588 }
589};
590
591} // anonymous namespace
592
593void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
594 CodeGenFunction::RunCleanupsScope Scope(CGF);
595 if (PrePostAction) {
596 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
597 Callback(CodeGen, CGF, *PrePostAction);
598 } else {
599 PrePostActionTy Action;
600 Callback(CodeGen, CGF, Action);
601 }
602}
603
604/// Check if the combiner is a call to UDR combiner and if it is so return the
605/// UDR decl used for reduction.
606static const OMPDeclareReductionDecl *
607getReductionInit(const Expr *ReductionOp) {
608 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
609 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
610 if (const auto *DRE =
611 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
612 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
613 return DRD;
614 return nullptr;
615}
616
617static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
618 const OMPDeclareReductionDecl *DRD,
619 const Expr *InitOp,
620 Address Private, Address Original,
621 QualType Ty) {
622 if (DRD->getInitializer()) {
623 std::pair<llvm::Function *, llvm::Function *> Reduction =
624 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
625 const auto *CE = cast<CallExpr>(InitOp);
626 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
627 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
628 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
629 const auto *LHSDRE =
630 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
631 const auto *RHSDRE =
632 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
633 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
634 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
635 [=]() { return Private; });
636 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
637 [=]() { return Original; });
638 (void)PrivateScope.Privatize();
639 RValue Func = RValue::get(Reduction.second);
640 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
641 CGF.EmitIgnoredExpr(InitOp);
642 } else {
643 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
644 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
645 auto *GV = new llvm::GlobalVariable(
646 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
647 llvm::GlobalValue::PrivateLinkage, Init, Name);
648 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
649 RValue InitRVal;
650 switch (CGF.getEvaluationKind(Ty)) {
651 case TEK_Scalar:
652 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
653 break;
654 case TEK_Complex:
655 InitRVal =
656 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
657 break;
658 case TEK_Aggregate: {
659 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_LValue);
660 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, LV);
661 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
662 /*IsInitializer=*/false);
663 return;
664 }
665 }
666 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
667 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
668 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
669 /*IsInitializer=*/false);
670 }
671}
672
673/// Emit initialization of arrays of complex types.
674/// \param DestAddr Address of the array.
675/// \param Type Type of array.
676/// \param Init Initial expression of array.
677/// \param SrcAddr Address of the original array.
678static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
679 QualType Type, bool EmitDeclareReductionInit,
680 const Expr *Init,
681 const OMPDeclareReductionDecl *DRD,
682 Address SrcAddr = Address::invalid()) {
683 // Perform element-by-element initialization.
684 QualType ElementTy;
685
686 // Drill down to the base element type on both arrays.
687 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
688 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
689 DestAddr =
690 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
691 if (DRD)
692 SrcAddr =
693 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
694
695 llvm::Value *SrcBegin = nullptr;
696 if (DRD)
697 SrcBegin = SrcAddr.getPointer();
698 llvm::Value *DestBegin = DestAddr.getPointer();
699 // Cast from pointer to array type to pointer to single element.
700 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
701 // The basic structure here is a while-do loop.
702 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
703 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
704 llvm::Value *IsEmpty =
705 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
706 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
707
708 // Enter the loop body, making that address the current address.
709 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
710 CGF.EmitBlock(BodyBB);
711
712 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
713
714 llvm::PHINode *SrcElementPHI = nullptr;
715 Address SrcElementCurrent = Address::invalid();
716 if (DRD) {
717 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
718 "omp.arraycpy.srcElementPast");
719 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
720 SrcElementCurrent =
721 Address(SrcElementPHI,
722 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
723 }
724 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
725 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
726 DestElementPHI->addIncoming(DestBegin, EntryBB);
727 Address DestElementCurrent =
728 Address(DestElementPHI,
729 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
730
731 // Emit copy.
732 {
733 CodeGenFunction::RunCleanupsScope InitScope(CGF);
734 if (EmitDeclareReductionInit) {
735 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
736 SrcElementCurrent, ElementTy);
737 } else
738 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
739 /*IsInitializer=*/false);
740 }
741
742 if (DRD) {
743 // Shift the address forward by one element.
744 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
745 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
746 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
747 }
748
749 // Shift the address forward by one element.
750 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
751 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
752 // Check whether we've reached the end.
753 llvm::Value *Done =
754 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
755 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
756 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
757
758 // Done.
759 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
760}
761
762LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
763 return CGF.EmitOMPSharedLValue(E);
764}
765
766LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
767 const Expr *E) {
768 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
769 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
770 return LValue();
771}
772
773void ReductionCodeGen::emitAggregateInitialization(
774 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
775 const OMPDeclareReductionDecl *DRD) {
776 // Emit VarDecl with copy init for arrays.
777 // Get the address of the original variable captured in current
778 // captured region.
779 const auto *PrivateVD =
780 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
781 bool EmitDeclareReductionInit =
782 DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
783 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),
784 EmitDeclareReductionInit,
785 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
786 : PrivateVD->getInit(),
787 DRD, SharedLVal.getAddress(CGF));
788}
789
790ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
791 ArrayRef<const Expr *> Origs,
792 ArrayRef<const Expr *> Privates,
793 ArrayRef<const Expr *> ReductionOps) {
794 ClausesData.reserve(Shareds.size());
795 SharedAddresses.reserve(Shareds.size());
796 Sizes.reserve(Shareds.size());
797 BaseDecls.reserve(Shareds.size());
798 const auto *IOrig = Origs.begin();
799 const auto *IPriv = Privates.begin();
800 const auto *IRed = ReductionOps.begin();
801 for (const Expr *Ref : Shareds) {
802 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
803 std::advance(IOrig, 1);
804 std::advance(IPriv, 1);
805 std::advance(IRed, 1);
806 }
807}
808
809void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) {
810 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&((SharedAddresses.size() == N && OrigAddresses.size()
== N && "Number of generated lvalues must be exactly N."
) ? static_cast<void> (0) : __assert_fail ("SharedAddresses.size() == N && OrigAddresses.size() == N && \"Number of generated lvalues must be exactly N.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 811, __PRETTY_FUNCTION__))
811 "Number of generated lvalues must be exactly N.")((SharedAddresses.size() == N && OrigAddresses.size()
== N && "Number of generated lvalues must be exactly N."
) ? static_cast<void> (0) : __assert_fail ("SharedAddresses.size() == N && OrigAddresses.size() == N && \"Number of generated lvalues must be exactly N.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 811, __PRETTY_FUNCTION__))
;
812 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
813 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
814 SharedAddresses.emplace_back(First, Second);
815 if (ClausesData[N].Shared == ClausesData[N].Ref) {
816 OrigAddresses.emplace_back(First, Second);
817 } else {
818 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
819 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
820 OrigAddresses.emplace_back(First, Second);
821 }
822}
823
824void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
825 const auto *PrivateVD =
826 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
827 QualType PrivateType = PrivateVD->getType();
828 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
829 if (!PrivateType->isVariablyModifiedType()) {
830 Sizes.emplace_back(
831 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
832 nullptr);
833 return;
834 }
835 llvm::Value *Size;
836 llvm::Value *SizeInChars;
837 auto *ElemType =
838 cast<llvm::PointerType>(OrigAddresses[N].first.getPointer(CGF)->getType())
839 ->getElementType();
840 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
841 if (AsArraySection) {
842 Size = CGF.Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF),
843 OrigAddresses[N].first.getPointer(CGF));
844 Size = CGF.Builder.CreateNUWAdd(
845 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
846 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf);
847 } else {
848 SizeInChars =
849 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
850 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
851 }
852 Sizes.emplace_back(SizeInChars, Size);
853 CodeGenFunction::OpaqueValueMapping OpaqueMap(
854 CGF,
855 cast<OpaqueValueExpr>(
856 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
857 RValue::get(Size));
858 CGF.EmitVariablyModifiedType(PrivateType);
859}
860
861void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
862 llvm::Value *Size) {
863 const auto *PrivateVD =
864 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
865 QualType PrivateType = PrivateVD->getType();
866 if (!PrivateType->isVariablyModifiedType()) {
867 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 869, __PRETTY_FUNCTION__))
868 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 869, __PRETTY_FUNCTION__))
869 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 869, __PRETTY_FUNCTION__))
;
870 return;
871 }
872 CodeGenFunction::OpaqueValueMapping OpaqueMap(
873 CGF,
874 cast<OpaqueValueExpr>(
875 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
876 RValue::get(Size));
877 CGF.EmitVariablyModifiedType(PrivateType);
878}
879
880void ReductionCodeGen::emitInitialization(
881 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
882 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
883 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 883, __PRETTY_FUNCTION__))
;
884 const auto *PrivateVD =
885 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
886 const OMPDeclareReductionDecl *DRD =
887 getReductionInit(ClausesData[N].ReductionOp);
888 QualType PrivateType = PrivateVD->getType();
889 PrivateAddr = CGF.Builder.CreateElementBitCast(
890 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
891 QualType SharedType = SharedAddresses[N].first.getType();
892 SharedLVal = CGF.MakeAddrLValue(
893 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF),
894 CGF.ConvertTypeForMem(SharedType)),
895 SharedType, SharedAddresses[N].first.getBaseInfo(),
896 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType));
897 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
898 if (DRD && DRD->getInitializer())
899 (void)DefaultInit(CGF);
900 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD);
901 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
902 (void)DefaultInit(CGF);
903 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
904 PrivateAddr, SharedLVal.getAddress(CGF),
905 SharedLVal.getType());
906 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
907 !CGF.isTrivialInitializer(PrivateVD->getInit())) {
908 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,
909 PrivateVD->getType().getQualifiers(),
910 /*IsInitializer=*/false);
911 }
912}
913
914bool ReductionCodeGen::needCleanups(unsigned N) {
915 const auto *PrivateVD =
916 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
917 QualType PrivateType = PrivateVD->getType();
918 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
919 return DTorKind != QualType::DK_none;
920}
921
922void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
923 Address PrivateAddr) {
924 const auto *PrivateVD =
925 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
926 QualType PrivateType = PrivateVD->getType();
927 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
928 if (needCleanups(N)) {
929 PrivateAddr = CGF.Builder.CreateElementBitCast(
930 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
931 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);
932 }
933}
934
935static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
936 LValue BaseLV) {
937 BaseTy = BaseTy.getNonReferenceType();
938 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
939 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
940 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
941 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy);
942 } else {
943 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy);
944 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
945 }
946 BaseTy = BaseTy->getPointeeType();
947 }
948 return CGF.MakeAddrLValue(
949 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF),
950 CGF.ConvertTypeForMem(ElTy)),
951 BaseLV.getType(), BaseLV.getBaseInfo(),
952 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
953}
954
955static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
956 llvm::Type *BaseLVType, CharUnits BaseLVAlignment,
957 llvm::Value *Addr) {
958 Address Tmp = Address::invalid();
959 Address TopTmp = Address::invalid();
960 Address MostTopTmp = Address::invalid();
961 BaseTy = BaseTy.getNonReferenceType();
962 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
963 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
964 Tmp = CGF.CreateMemTemp(BaseTy);
965 if (TopTmp.isValid())
966 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
967 else
968 MostTopTmp = Tmp;
969 TopTmp = Tmp;
970 BaseTy = BaseTy->getPointeeType();
971 }
972 llvm::Type *Ty = BaseLVType;
973 if (Tmp.isValid())
974 Ty = Tmp.getElementType();
975 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);
976 if (Tmp.isValid()) {
977 CGF.Builder.CreateStore(Addr, Tmp);
978 return MostTopTmp;
979 }
980 return Address(Addr, BaseLVAlignment);
981}
982
983static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
984 const VarDecl *OrigVD = nullptr;
985 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
986 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
987 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
988 Base = TempOASE->getBase()->IgnoreParenImpCasts();
989 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
990 Base = TempASE->getBase()->IgnoreParenImpCasts();
991 DE = cast<DeclRefExpr>(Base);
992 OrigVD = cast<VarDecl>(DE->getDecl());
993 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
994 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
995 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
996 Base = TempASE->getBase()->IgnoreParenImpCasts();
997 DE = cast<DeclRefExpr>(Base);
998 OrigVD = cast<VarDecl>(DE->getDecl());
999 }
1000 return OrigVD;
1001}
1002
1003Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
1004 Address PrivateAddr) {
1005 const DeclRefExpr *DE;
1006 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
1007 BaseDecls.emplace_back(OrigVD);
1008 LValue OriginalBaseLValue = CGF.EmitLValue(DE);
1009 LValue BaseLValue =
1010 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
1011 OriginalBaseLValue);
1012 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
1013 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF));
1014 llvm::Value *PrivatePointer =
1015 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1016 PrivateAddr.getPointer(),
1017 SharedAddresses[N].first.getAddress(CGF).getType());
1018 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
1019 return castToBase(CGF, OrigVD->getType(),
1020 SharedAddresses[N].first.getType(),
1021 OriginalBaseLValue.getAddress(CGF).getType(),
1022 OriginalBaseLValue.getAlignment(), Ptr);
1023 }
1024 BaseDecls.emplace_back(
1025 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
1026 return PrivateAddr;
1027}
1028
1029bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
1030 const OMPDeclareReductionDecl *DRD =
1031 getReductionInit(ClausesData[N].ReductionOp);
1032 return DRD && DRD->getInitializer();
1033}
1034
1035LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
1036 return CGF.EmitLoadOfPointerLValue(
1037 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1038 getThreadIDVariable()->getType()->castAs<PointerType>());
1039}
1040
1041void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt *S) {
1042 if (!CGF.HaveInsertPoint())
1043 return;
1044 // 1.2.2 OpenMP Language Terminology
1045 // Structured block - An executable statement with a single entry at the
1046 // top and a single exit at the bottom.
1047 // The point of exit cannot be a branch out of the structured block.
1048 // longjmp() and throw() must not violate the entry/exit criteria.
1049 CGF.EHStack.pushTerminate();
1050 if (S)
1051 CGF.incrementProfileCounter(S);
1052 CodeGen(CGF);
1053 CGF.EHStack.popTerminate();
1054}
1055
1056LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1057 CodeGenFunction &CGF) {
1058 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1059 getThreadIDVariable()->getType(),
1060 AlignmentSource::Decl);
1061}
1062
1063static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1064 QualType FieldTy) {
1065 auto *Field = FieldDecl::Create(
1066 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1067 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1068 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1069 Field->setAccess(AS_public);
1070 DC->addDecl(Field);
1071 return Field;
1072}
1073
1074CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
1075 StringRef Separator)
1076 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
1077 OMPBuilder(CGM.getModule()), OffloadEntriesInfoManager(CGM) {
1078 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
1079
1080 // Initialize Types used in OpenMPIRBuilder from OMPKinds.def
1081 OMPBuilder.initialize();
1082 loadOffloadInfoMetadata();
1083}
1084
1085void CGOpenMPRuntime::clear() {
1086 InternalVars.clear();
1087 // Clean non-target variable declarations possibly used only in debug info.
1088 for (const auto &Data : EmittedNonTargetVariables) {
1089 if (!Data.getValue().pointsToAliveValue())
1090 continue;
1091 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1092 if (!GV)
1093 continue;
1094 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1095 continue;
1096 GV->eraseFromParent();
1097 }
1098}
1099
1100std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1101 SmallString<128> Buffer;
1102 llvm::raw_svector_ostream OS(Buffer);
1103 StringRef Sep = FirstSeparator;
1104 for (StringRef Part : Parts) {
1105 OS << Sep << Part;
1106 Sep = Separator;
1107 }
1108 return std::string(OS.str());
1109}
1110
1111static llvm::Function *
1112emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1113 const Expr *CombinerInitializer, const VarDecl *In,
1114 const VarDecl *Out, bool IsCombiner) {
1115 // void .omp_combiner.(Ty *in, Ty *out);
1116 ASTContext &C = CGM.getContext();
1117 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1118 FunctionArgList Args;
1119 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
1120 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
1121 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
1122 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
1123 Args.push_back(&OmpOutParm);
1124 Args.push_back(&OmpInParm);
1125 const CGFunctionInfo &FnInfo =
1126 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
1127 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
1128 std::string Name = CGM.getOpenMPRuntime().getName(
1129 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1130 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1131 Name, &CGM.getModule());
1132 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
1133 if (CGM.getLangOpts().Optimize) {
1134 Fn->removeFnAttr(llvm::Attribute::NoInline);
1135 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1136 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1137 }
1138 CodeGenFunction CGF(CGM);
1139 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1140 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
1141 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1142 Out->getLocation());
1143 CodeGenFunction::OMPPrivateScope Scope(CGF);
1144 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
1145 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
1146 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
1147 .getAddress(CGF);
1148 });
1149 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
1150 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
1151 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
1152 .getAddress(CGF);
1153 });
1154 (void)Scope.Privatize();
1155 if (!IsCombiner && Out->hasInit() &&
1156 !CGF.isTrivialInitializer(Out->getInit())) {
1157 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1158 Out->getType().getQualifiers(),
1159 /*IsInitializer=*/true);
1160 }
1161 if (CombinerInitializer)
1162 CGF.EmitIgnoredExpr(CombinerInitializer);
1163 Scope.ForceCleanup();
1164 CGF.FinishFunction();
1165 return Fn;
1166}
1167
1168void CGOpenMPRuntime::emitUserDefinedReduction(
1169 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1170 if (UDRMap.count(D) > 0)
1171 return;
1172 llvm::Function *Combiner = emitCombinerOrInitializer(
1173 CGM, D->getType(), D->getCombiner(),
1174 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1175 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
1176 /*IsCombiner=*/true);
1177 llvm::Function *Initializer = nullptr;
1178 if (const Expr *Init = D->getInitializer()) {
1179 Initializer = emitCombinerOrInitializer(
1180 CGM, D->getType(),
1181 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1182 : nullptr,
1183 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1184 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
1185 /*IsCombiner=*/false);
1186 }
1187 UDRMap.try_emplace(D, Combiner, Initializer);
1188 if (CGF) {
1189 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1190 Decls.second.push_back(D);
1191 }
1192}
1193
1194std::pair<llvm::Function *, llvm::Function *>
1195CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1196 auto I = UDRMap.find(D);
1197 if (I != UDRMap.end())
1198 return I->second;
1199 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1200 return UDRMap.lookup(D);
1201}
1202
1203namespace {
1204// Temporary RAII solution to perform a push/pop stack event on the OpenMP IR
1205// Builder if one is present.
1206struct PushAndPopStackRAII {
1207 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF,
1208 bool HasCancel)
1209 : OMPBuilder(OMPBuilder) {
1210 if (!OMPBuilder)
1211 return;
1212
1213 // The following callback is the crucial part of clangs cleanup process.
1214 //
1215 // NOTE:
1216 // Once the OpenMPIRBuilder is used to create parallel regions (and
1217 // similar), the cancellation destination (Dest below) is determined via
1218 // IP. That means if we have variables to finalize we split the block at IP,
1219 // use the new block (=BB) as destination to build a JumpDest (via
1220 // getJumpDestInCurrentScope(BB)) which then is fed to
1221 // EmitBranchThroughCleanup. Furthermore, there will not be the need
1222 // to push & pop an FinalizationInfo object.
1223 // The FiniCB will still be needed but at the point where the
1224 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct.
1225 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1226 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1227, __PRETTY_FUNCTION__))
1227 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1227, __PRETTY_FUNCTION__))
;
1228 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1229 CGF.Builder.restoreIP(IP);
1230 CodeGenFunction::JumpDest Dest =
1231 CGF.getOMPCancelDestination(OMPD_parallel);
1232 CGF.EmitBranchThroughCleanup(Dest);
1233 };
1234
1235 // TODO: Remove this once we emit parallel regions through the
1236 // OpenMPIRBuilder as it can do this setup internally.
1237 llvm::OpenMPIRBuilder::FinalizationInfo FI(
1238 {FiniCB, OMPD_parallel, HasCancel});
1239 OMPBuilder->pushFinalizationCB(std::move(FI));
1240 }
1241 ~PushAndPopStackRAII() {
1242 if (OMPBuilder)
1243 OMPBuilder->popFinalizationCB();
1244 }
1245 llvm::OpenMPIRBuilder *OMPBuilder;
1246};
1247} // namespace
1248
1249static llvm::Function *emitParallelOrTeamsOutlinedFunction(
1250 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1251 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1252 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
1253 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1254, __PRETTY_FUNCTION__))
1254 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1254, __PRETTY_FUNCTION__))
;
1255 CodeGenFunction CGF(CGM, true);
1256 bool HasCancel = false;
1257 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1258 HasCancel = OPD->hasCancel();
1259 else if (const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1260 HasCancel = OPD->hasCancel();
1261 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1262 HasCancel = OPSD->hasCancel();
1263 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1264 HasCancel = OPFD->hasCancel();
1265 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1266 HasCancel = OPFD->hasCancel();
1267 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1268 HasCancel = OPFD->hasCancel();
1269 else if (const auto *OPFD =
1270 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1271 HasCancel = OPFD->hasCancel();
1272 else if (const auto *OPFD =
1273 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1274 HasCancel = OPFD->hasCancel();
1275
1276 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new
1277 // parallel region to make cancellation barriers work properly.
1278 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
1279 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel);
1280 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
1281 HasCancel, OutlinedHelperName);
1282 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
1283 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc());
1284}
1285
1286llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
1287 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1288 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1289 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1290 return emitParallelOrTeamsOutlinedFunction(
1291 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1292}
1293
1294llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
1295 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1296 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1297 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1298 return emitParallelOrTeamsOutlinedFunction(
1299 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1300}
1301
1302llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
1303 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1304 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1305 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1306 bool Tied, unsigned &NumberOfParts) {
1307 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1308 PrePostActionTy &) {
1309 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1310 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
1311 llvm::Value *TaskArgs[] = {
1312 UpLoc, ThreadID,
1313 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1314 TaskTVar->getType()->castAs<PointerType>())
1315 .getPointer(CGF)};
1316 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
1317 CGM.getModule(), OMPRTL___kmpc_omp_task),
1318 TaskArgs);
1319 };
1320 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1321 UntiedCodeGen);
1322 CodeGen.setAction(Action);
1323 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1324, __PRETTY_FUNCTION__))
1324 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1324, __PRETTY_FUNCTION__))
;
1325 const OpenMPDirectiveKind Region =
1326 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1327 : OMPD_task;
1328 const CapturedStmt *CS = D.getCapturedStmt(Region);
1329 bool HasCancel = false;
1330 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1331 HasCancel = TD->hasCancel();
1332 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1333 HasCancel = TD->hasCancel();
1334 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1335 HasCancel = TD->hasCancel();
1336 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1337 HasCancel = TD->hasCancel();
1338
1339 CodeGenFunction CGF(CGM, true);
1340 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1341 InnermostKind, HasCancel, Action);
1342 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
1343 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1344 if (!Tied)
1345 NumberOfParts = Action.getNumberOfParts();
1346 return Res;
1347}
1348
1349static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1350 const RecordDecl *RD, const CGRecordLayout &RL,
1351 ArrayRef<llvm::Constant *> Data) {
1352 llvm::StructType *StructTy = RL.getLLVMType();
1353 unsigned PrevIdx = 0;
1354 ConstantInitBuilder CIBuilder(CGM);
1355 auto DI = Data.begin();
1356 for (const FieldDecl *FD : RD->fields()) {
1357 unsigned Idx = RL.getLLVMFieldNo(FD);
1358 // Fill the alignment.
1359 for (unsigned I = PrevIdx; I < Idx; ++I)
1360 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1361 PrevIdx = Idx + 1;
1362 Fields.add(*DI);
1363 ++DI;
1364 }
1365}
1366
1367template <class... As>
1368static llvm::GlobalVariable *
1369createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1370 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1371 As &&... Args) {
1372 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1373 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1374 ConstantInitBuilder CIBuilder(CGM);
1375 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1376 buildStructValue(Fields, CGM, RD, RL, Data);
1377 return Fields.finishAndCreateGlobal(
1378 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1379 std::forward<As>(Args)...);
1380}
1381
1382template <typename T>
1383static void
1384createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1385 ArrayRef<llvm::Constant *> Data,
1386 T &Parent) {
1387 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1388 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1389 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1390 buildStructValue(Fields, CGM, RD, RL, Data);
1391 Fields.finishAndAddTo(Parent);
1392}
1393
1394void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1395 bool AtCurrentPoint) {
1396 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1397 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1397, __PRETTY_FUNCTION__))
;
1398
1399 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1400 if (AtCurrentPoint) {
1401 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1402 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1403 } else {
1404 Elem.second.ServiceInsertPt =
1405 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1406 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1407 }
1408}
1409
1410void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1411 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1412 if (Elem.second.ServiceInsertPt) {
1413 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1414 Elem.second.ServiceInsertPt = nullptr;
1415 Ptr->eraseFromParent();
1416 }
1417}
1418
1419static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF,
1420 SourceLocation Loc,
1421 SmallString<128> &Buffer) {
1422 llvm::raw_svector_ostream OS(Buffer);
1423 // Build debug location
1424 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1425 OS << ";" << PLoc.getFilename() << ";";
1426 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
1427 OS << FD->getQualifiedNameAsString();
1428 OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1429 return OS.str();
1430}
1431
1432llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1433 SourceLocation Loc,
1434 unsigned Flags) {
1435 llvm::Constant *SrcLocStr;
1436 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
1437 Loc.isInvalid()) {
1438 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr();
1439 } else {
1440 std::string FunctionName = "";
1441 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
1442 FunctionName = FD->getQualifiedNameAsString();
1443 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1444 const char *FileName = PLoc.getFilename();
1445 unsigned Line = PLoc.getLine();
1446 unsigned Column = PLoc.getColumn();
1447 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FunctionName.c_str(), FileName,
1448 Line, Column);
1449 }
1450 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1451 return OMPBuilder.getOrCreateIdent(SrcLocStr, llvm::omp::IdentFlag(Flags),
1452 Reserved2Flags);
1453}
1454
1455llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1456 SourceLocation Loc) {
1457 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1457, __PRETTY_FUNCTION__))
;
1458 // If the OpenMPIRBuilder is used we need to use it for all thread id calls as
1459 // the clang invariants used below might be broken.
1460 if (CGM.getLangOpts().OpenMPIRBuilder) {
1461 SmallString<128> Buffer;
1462 OMPBuilder.updateToLocation(CGF.Builder.saveIP());
1463 auto *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(
1464 getIdentStringFromSourceLocation(CGF, Loc, Buffer));
1465 return OMPBuilder.getOrCreateThreadID(
1466 OMPBuilder.getOrCreateIdent(SrcLocStr));
1467 }
1468
1469 llvm::Value *ThreadID = nullptr;
1470 // Check whether we've already cached a load of the thread id in this
1471 // function.
1472 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1473 if (I != OpenMPLocThreadIDMap.end()) {
1474 ThreadID = I->second.ThreadID;
1475 if (ThreadID != nullptr)
1476 return ThreadID;
1477 }
1478 // If exceptions are enabled, do not use parameter to avoid possible crash.
1479 if (auto *OMPRegionInfo =
1480 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1481 if (OMPRegionInfo->getThreadIDVariable()) {
1482 // Check if this an outlined function with thread id passed as argument.
1483 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1484 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent();
1485 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1486 !CGF.getLangOpts().CXXExceptions ||
1487 CGF.Builder.GetInsertBlock() == TopBlock ||
1488 !isa<llvm::Instruction>(LVal.getPointer(CGF)) ||
1489 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1490 TopBlock ||
1491 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1492 CGF.Builder.GetInsertBlock()) {
1493 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
1494 // If value loaded in entry block, cache it and use it everywhere in
1495 // function.
1496 if (CGF.Builder.GetInsertBlock() == TopBlock) {
1497 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1498 Elem.second.ThreadID = ThreadID;
1499 }
1500 return ThreadID;
1501 }
1502 }
1503 }
1504
1505 // This is not an outlined function region - need to call __kmpc_int32
1506 // kmpc_global_thread_num(ident_t *loc).
1507 // Generate thread id value and cache this value for use across the
1508 // function.
1509 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1510 if (!Elem.second.ServiceInsertPt)
1511 setLocThreadIdInsertPt(CGF);
1512 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1513 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
1514 llvm::CallInst *Call = CGF.Builder.CreateCall(
1515 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
1516 OMPRTL___kmpc_global_thread_num),
1517 emitUpdateLocation(CGF, Loc));
1518 Call->setCallingConv(CGF.getRuntimeCC());
1519 Elem.second.ThreadID = Call;
1520 return Call;
1521}
1522
1523void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
1524 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1524, __PRETTY_FUNCTION__))
;
1525 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1526 clearLocThreadIdInsertPt(CGF);
1527 OpenMPLocThreadIDMap.erase(CGF.CurFn);
1528 }
1529 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
1530 for(const auto *D : FunctionUDRMap[CGF.CurFn])
1531 UDRMap.erase(D);
1532 FunctionUDRMap.erase(CGF.CurFn);
1533 }
1534 auto I = FunctionUDMMap.find(CGF.CurFn);
1535 if (I != FunctionUDMMap.end()) {
1536 for(const auto *D : I->second)
1537 UDMMap.erase(D);
1538 FunctionUDMMap.erase(I);
1539 }
1540 LastprivateConditionalToTypes.erase(CGF.CurFn);
1541 FunctionToUntiedTaskStackMap.erase(CGF.CurFn);
1542}
1543
1544llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
1545 return OMPBuilder.IdentPtr;
1546}
1547
1548llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
1549 if (!Kmpc_MicroTy) {
1550 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1551 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1552 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1553 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1554 }
1555 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1556}
1557
1558llvm::FunctionCallee
1559CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
1560 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1561, __PRETTY_FUNCTION__))
1561 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1561, __PRETTY_FUNCTION__))
;
1562 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
1563 : "__kmpc_for_static_init_4u")
1564 : (IVSigned ? "__kmpc_for_static_init_8"
1565 : "__kmpc_for_static_init_8u");
1566 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1567 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
1568 llvm::Type *TypeParams[] = {
1569 getIdentTyPointerTy(), // loc
1570 CGM.Int32Ty, // tid
1571 CGM.Int32Ty, // schedtype
1572 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1573 PtrTy, // p_lower
1574 PtrTy, // p_upper
1575 PtrTy, // p_stride
1576 ITy, // incr
1577 ITy // chunk
1578 };
1579 auto *FnTy =
1580 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1581 return CGM.CreateRuntimeFunction(FnTy, Name);
1582}
1583
1584llvm::FunctionCallee
1585CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
1586 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1587, __PRETTY_FUNCTION__))
1587 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1587, __PRETTY_FUNCTION__))
;
1588 StringRef Name =
1589 IVSize == 32
1590 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
1591 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
1592 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1593 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
1594 CGM.Int32Ty, // tid
1595 CGM.Int32Ty, // schedtype
1596 ITy, // lower
1597 ITy, // upper
1598 ITy, // stride
1599 ITy // chunk
1600 };
1601 auto *FnTy =
1602 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1603 return CGM.CreateRuntimeFunction(FnTy, Name);
1604}
1605
1606llvm::FunctionCallee
1607CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
1608 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1609, __PRETTY_FUNCTION__))
1609 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1609, __PRETTY_FUNCTION__))
;
1610 StringRef Name =
1611 IVSize == 32
1612 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1613 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1614 llvm::Type *TypeParams[] = {
1615 getIdentTyPointerTy(), // loc
1616 CGM.Int32Ty, // tid
1617 };
1618 auto *FnTy =
1619 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1620 return CGM.CreateRuntimeFunction(FnTy, Name);
1621}
1622
1623llvm::FunctionCallee
1624CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
1625 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1626, __PRETTY_FUNCTION__))
1626 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1626, __PRETTY_FUNCTION__))
;
1627 StringRef Name =
1628 IVSize == 32
1629 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1630 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1631 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1632 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
1633 llvm::Type *TypeParams[] = {
1634 getIdentTyPointerTy(), // loc
1635 CGM.Int32Ty, // tid
1636 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1637 PtrTy, // p_lower
1638 PtrTy, // p_upper
1639 PtrTy // p_stride
1640 };
1641 auto *FnTy =
1642 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1643 return CGM.CreateRuntimeFunction(FnTy, Name);
1644}
1645
1646/// Obtain information that uniquely identifies a target entry. This
1647/// consists of the file and device IDs as well as line number associated with
1648/// the relevant entry source location.
1649static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
1650 unsigned &DeviceID, unsigned &FileID,
1651 unsigned &LineNum) {
1652 SourceManager &SM = C.getSourceManager();
1653
1654 // The loc should be always valid and have a file ID (the user cannot use
1655 // #pragma directives in macros)
1656
1657 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1657, __PRETTY_FUNCTION__))
;
1658
1659 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
1660 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1660, __PRETTY_FUNCTION__))
;
1661
1662 llvm::sys::fs::UniqueID ID;
1663 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) {
1664 PLoc = SM.getPresumedLoc(Loc, /*UseLineDirectives=*/false);
1665 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1665, __PRETTY_FUNCTION__))
;
1666 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
1667 SM.getDiagnostics().Report(diag::err_cannot_open_file)
1668 << PLoc.getFilename() << EC.message();
1669 }
1670
1671 DeviceID = ID.getDevice();
1672 FileID = ID.getFile();
1673 LineNum = PLoc.getLine();
1674}
1675
1676Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
1677 if (CGM.getLangOpts().OpenMPSimd)
1678 return Address::invalid();
1679 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
1680 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1681 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
1682 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
1683 HasRequiresUnifiedSharedMemory))) {
1684 SmallString<64> PtrName;
1685 {
1686 llvm::raw_svector_ostream OS(PtrName);
1687 OS << CGM.getMangledName(GlobalDecl(VD));
1688 if (!VD->isExternallyVisible()) {
1689 unsigned DeviceID, FileID, Line;
1690 getTargetEntryUniqueInfo(CGM.getContext(),
1691 VD->getCanonicalDecl()->getBeginLoc(),
1692 DeviceID, FileID, Line);
1693 OS << llvm::format("_%x", FileID);
1694 }
1695 OS << "_decl_tgt_ref_ptr";
1696 }
1697 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
1698 if (!Ptr) {
1699 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
1700 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
1701 PtrName);
1702
1703 auto *GV = cast<llvm::GlobalVariable>(Ptr);
1704 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
1705
1706 if (!CGM.getLangOpts().OpenMPIsDevice)
1707 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
1708 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
1709 }
1710 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
1711 }
1712 return Address::invalid();
1713}
1714
1715llvm::Constant *
1716CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
1717 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1718, __PRETTY_FUNCTION__))
1718 !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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1718, __PRETTY_FUNCTION__))
;
1719 // Lookup the entry, lazily creating it if necessary.
1720 std::string Suffix = getName({"cache", ""});
1721 return getOrCreateInternalVariable(
1722 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
1723}
1724
1725Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1726 const VarDecl *VD,
1727 Address VDAddr,
1728 SourceLocation Loc) {
1729 if (CGM.getLangOpts().OpenMPUseTLS &&
1730 CGM.getContext().getTargetInfo().isTLSSupported())
1731 return VDAddr;
1732
1733 llvm::Type *VarTy = VDAddr.getElementType();
1734 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1735 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1736 CGM.Int8PtrTy),
1737 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1738 getOrCreateThreadPrivateCache(VD)};
1739 return Address(CGF.EmitRuntimeCall(
1740 OMPBuilder.getOrCreateRuntimeFunction(
1741 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1742 Args),
1743 VDAddr.getAlignment());
1744}
1745
1746void CGOpenMPRuntime::emitThreadPrivateVarInit(
1747 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
1748 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1749 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1750 // library.
1751 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
1752 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
1753 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1754 OMPLoc);
1755 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1756 // to register constructor/destructor for variable.
1757 llvm::Value *Args[] = {
1758 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
1759 Ctor, CopyCtor, Dtor};
1760 CGF.EmitRuntimeCall(
1761 OMPBuilder.getOrCreateRuntimeFunction(
1762 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1763 Args);
1764}
1765
1766llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
1767 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
1768 bool PerformInit, CodeGenFunction *CGF) {
1769 if (CGM.getLangOpts().OpenMPUseTLS &&
1770 CGM.getContext().getTargetInfo().isTLSSupported())
1771 return nullptr;
1772
1773 VD = VD->getDefinition(CGM.getContext());
1774 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
1775 QualType ASTTy = VD->getType();
1776
1777 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1778 const Expr *Init = VD->getAnyInitializer();
1779 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1780 // Generate function that re-emits the declaration's initializer into the
1781 // threadprivate copy of the variable VD
1782 CodeGenFunction CtorCGF(CGM);
1783 FunctionArgList Args;
1784 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
1785 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
1786 ImplicitParamDecl::Other);
1787 Args.push_back(&Dst);
1788
1789 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1790 CGM.getContext().VoidPtrTy, Args);
1791 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1792 std::string Name = getName({"__kmpc_global_ctor_", ""});
1793 llvm::Function *Fn =
1794 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1795 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1796 Args, Loc, Loc);
1797 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
1798 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
1799 CGM.getContext().VoidPtrTy, Dst.getLocation());
1800 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1801 Arg = CtorCGF.Builder.CreateElementBitCast(
1802 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
1803 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1804 /*IsInitializer=*/true);
1805 ArgVal = CtorCGF.EmitLoadOfScalar(
1806 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
1807 CGM.getContext().VoidPtrTy, Dst.getLocation());
1808 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1809 CtorCGF.FinishFunction();
1810 Ctor = Fn;
1811 }
1812 if (VD->getType().isDestructedType() != QualType::DK_none) {
1813 // Generate function that emits destructor call for the threadprivate copy
1814 // of the variable VD
1815 CodeGenFunction DtorCGF(CGM);
1816 FunctionArgList Args;
1817 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
1818 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
1819 ImplicitParamDecl::Other);
1820 Args.push_back(&Dst);
1821
1822 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1823 CGM.getContext().VoidTy, Args);
1824 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1825 std::string Name = getName({"__kmpc_global_dtor_", ""});
1826 llvm::Function *Fn =
1827 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1828 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
1829 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1830 Loc, Loc);
1831 // Create a scope with an artificial location for the body of this function.
1832 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
1833 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
1834 DtorCGF.GetAddrOfLocalVar(&Dst),
1835 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1836 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
1837 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1838 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1839 DtorCGF.FinishFunction();
1840 Dtor = Fn;
1841 }
1842 // Do not emit init function if it is not required.
1843 if (!Ctor && !Dtor)
1844 return nullptr;
1845
1846 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1847 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1848 /*isVarArg=*/false)
1849 ->getPointerTo();
1850 // Copying constructor for the threadprivate variable.
1851 // Must be NULL - reserved by runtime, but currently it requires that this
1852 // parameter is always NULL. Otherwise it fires assertion.
1853 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1854 if (Ctor == nullptr) {
1855 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1856 /*isVarArg=*/false)
1857 ->getPointerTo();
1858 Ctor = llvm::Constant::getNullValue(CtorTy);
1859 }
1860 if (Dtor == nullptr) {
1861 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1862 /*isVarArg=*/false)
1863 ->getPointerTo();
1864 Dtor = llvm::Constant::getNullValue(DtorTy);
1865 }
1866 if (!CGF) {
1867 auto *InitFunctionTy =
1868 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1869 std::string Name = getName({"__omp_threadprivate_init_", ""});
1870 llvm::Function *InitFunction = CGM.CreateGlobalInitOrCleanUpFunction(
1871 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
1872 CodeGenFunction InitCGF(CGM);
1873 FunctionArgList ArgList;
1874 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1875 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1876 Loc, Loc);
1877 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
1878 InitCGF.FinishFunction();
1879 return InitFunction;
1880 }
1881 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
1882 }
1883 return nullptr;
1884}
1885
1886bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
1887 llvm::GlobalVariable *Addr,
1888 bool PerformInit) {
1889 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
1890 !CGM.getLangOpts().OpenMPIsDevice)
1891 return false;
1892 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
1893 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1894 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
1895 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
1896 HasRequiresUnifiedSharedMemory))
1897 return CGM.getLangOpts().OpenMPIsDevice;
1898 VD = VD->getDefinition(CGM.getContext());
1899 assert(VD && "Unknown VarDecl")((VD && "Unknown VarDecl") ? static_cast<void> (
0) : __assert_fail ("VD && \"Unknown VarDecl\"", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 1899, __PRETTY_FUNCTION__))
;
1900
1901 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
1902 return CGM.getLangOpts().OpenMPIsDevice;
1903
1904 QualType ASTTy = VD->getType();
1905 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
1906
1907 // Produce the unique prefix to identify the new target regions. We use
1908 // the source location of the variable declaration which we know to not
1909 // conflict with any target region.
1910 unsigned DeviceID;
1911 unsigned FileID;
1912 unsigned Line;
1913 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
1914 SmallString<128> Buffer, Out;
1915 {
1916 llvm::raw_svector_ostream OS(Buffer);
1917 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
1918 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
1919 }
1920
1921 const Expr *Init = VD->getAnyInitializer();
1922 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1923 llvm::Constant *Ctor;
1924 llvm::Constant *ID;
1925 if (CGM.getLangOpts().OpenMPIsDevice) {
1926 // Generate function that re-emits the declaration's initializer into
1927 // the threadprivate copy of the variable VD
1928 CodeGenFunction CtorCGF(CGM);
1929
1930 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
1931 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1932 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction(
1933 FTy, Twine(Buffer, "_ctor"), FI, Loc);
1934 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
1935 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
1936 FunctionArgList(), Loc, Loc);
1937 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
1938 CtorCGF.EmitAnyExprToMem(Init,
1939 Address(Addr, CGM.getContext().getDeclAlign(VD)),
1940 Init->getType().getQualifiers(),
1941 /*IsInitializer=*/true);
1942 CtorCGF.FinishFunction();
1943 Ctor = Fn;
1944 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
1945 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
1946 } else {
1947 Ctor = new llvm::GlobalVariable(
1948 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
1949 llvm::GlobalValue::PrivateLinkage,
1950 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
1951 ID = Ctor;
1952 }
1953
1954 // Register the information for the entry associated with the constructor.
1955 Out.clear();
1956 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
1957 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
1958 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
1959 }
1960 if (VD->getType().isDestructedType() != QualType::DK_none) {
1961 llvm::Constant *Dtor;
1962 llvm::Constant *ID;
1963 if (CGM.getLangOpts().OpenMPIsDevice) {
1964 // Generate function that emits destructor call for the threadprivate
1965 // copy of the variable VD
1966 CodeGenFunction DtorCGF(CGM);
1967
1968 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
1969 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
1970 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction(
1971 FTy, Twine(Buffer, "_dtor"), FI, Loc);
1972 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
1973 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
1974 FunctionArgList(), Loc, Loc);
1975 // Create a scope with an artificial location for the body of this
1976 // function.
1977 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
1978 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
1979 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1980 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1981 DtorCGF.FinishFunction();
1982 Dtor = Fn;
1983 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
1984 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
1985 } else {
1986 Dtor = new llvm::GlobalVariable(
1987 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
1988 llvm::GlobalValue::PrivateLinkage,
1989 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
1990 ID = Dtor;
1991 }
1992 // Register the information for the entry associated with the destructor.
1993 Out.clear();
1994 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
1995 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
1996 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
1997 }
1998 return CGM.getLangOpts().OpenMPIsDevice;
1999}
2000
2001Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2002 QualType VarType,
2003 StringRef Name) {
2004 std::string Suffix = getName({"artificial", ""});
2005 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
2006 llvm::Value *GAddr =
2007 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
2008 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS &&
2009 CGM.getTarget().isTLSSupported()) {
2010 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true);
2011 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType));
2012 }
2013 std::string CacheSuffix = getName({"cache", ""});
2014 llvm::Value *Args[] = {
2015 emitUpdateLocation(CGF, SourceLocation()),
2016 getThreadID(CGF, SourceLocation()),
2017 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
2018 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
2019 /*isSigned=*/false),
2020 getOrCreateInternalVariable(
2021 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
2022 return Address(
2023 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2024 CGF.EmitRuntimeCall(
2025 OMPBuilder.getOrCreateRuntimeFunction(
2026 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
2027 Args),
2028 VarLVType->getPointerTo(/*AddrSpace=*/0)),
2029 CGM.getContext().getTypeAlignInChars(VarType));
2030}
2031
2032void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond,
2033 const RegionCodeGenTy &ThenGen,
2034 const RegionCodeGenTy &ElseGen) {
2035 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
2036
2037 // If the condition constant folds and can be elided, try to avoid emitting
2038 // the condition and the dead arm of the if/else.
2039 bool CondConstant;
2040 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
2041 if (CondConstant)
2042 ThenGen(CGF);
2043 else
2044 ElseGen(CGF);
2045 return;
2046 }
2047
2048 // Otherwise, the condition did not fold, or we couldn't elide it. Just
2049 // emit the conditional branch.
2050 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
2051 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
2052 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
2053 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
2054
2055 // Emit the 'then' code.
2056 CGF.EmitBlock(ThenBlock);
2057 ThenGen(CGF);
2058 CGF.EmitBranch(ContBlock);
2059 // Emit the 'else' code if present.
2060 // There is no need to emit line number for unconditional branch.
2061 (void)ApplyDebugLocation::CreateEmpty(CGF);
2062 CGF.EmitBlock(ElseBlock);
2063 ElseGen(CGF);
2064 // There is no need to emit line number for unconditional branch.
2065 (void)ApplyDebugLocation::CreateEmpty(CGF);
2066 CGF.EmitBranch(ContBlock);
2067 // Emit the continuation block for code after the if.
2068 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
2069}
2070
2071void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
2072 llvm::Function *OutlinedFn,
2073 ArrayRef<llvm::Value *> CapturedVars,
2074 const Expr *IfCond) {
2075 if (!CGF.HaveInsertPoint())
2076 return;
2077 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
2078 auto &M = CGM.getModule();
2079 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
2080 this](CodeGenFunction &CGF, PrePostActionTy &) {
2081 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
2082 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
2083 llvm::Value *Args[] = {
2084 RTLoc,
2085 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
2086 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
2087 llvm::SmallVector<llvm::Value *, 16> RealArgs;
2088 RealArgs.append(std::begin(Args), std::end(Args));
2089 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2090
2091 llvm::FunctionCallee RTLFn =
2092 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
2093 CGF.EmitRuntimeCall(RTLFn, RealArgs);
2094 };
2095 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
2096 this](CodeGenFunction &CGF, PrePostActionTy &) {
2097 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
2098 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
2099 // Build calls:
2100 // __kmpc_serialized_parallel(&Loc, GTid);
2101 llvm::Value *Args[] = {RTLoc, ThreadID};
2102 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2103 M, OMPRTL___kmpc_serialized_parallel),
2104 Args);
2105
2106 // OutlinedFn(&GTid, &zero_bound, CapturedStruct);
2107 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
2108 Address ZeroAddrBound =
2109 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
2110 /*Name=*/".bound.zero.addr");
2111 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0));
2112 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
2113 // ThreadId for serialized parallels is 0.
2114 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
2115 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer());
2116 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
2117
2118 // Ensure we do not inline the function. This is trivially true for the ones
2119 // passed to __kmpc_fork_call but the ones calles in serialized regions
2120 // could be inlined. This is not a perfect but it is closer to the invariant
2121 // we want, namely, every data environment starts with a new function.
2122 // TODO: We should pass the if condition to the runtime function and do the
2123 // handling there. Much cleaner code.
2124 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
2125 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
2126
2127 // __kmpc_end_serialized_parallel(&Loc, GTid);
2128 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
2129 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2130 M, OMPRTL___kmpc_end_serialized_parallel),
2131 EndArgs);
2132 };
2133 if (IfCond) {
2134 emitIfClause(CGF, IfCond, ThenGen, ElseGen);
2135 } else {
2136 RegionCodeGenTy ThenRCG(ThenGen);
2137 ThenRCG(CGF);
2138 }
2139}
2140
2141// If we're inside an (outlined) parallel region, use the region info's
2142// thread-ID variable (it is passed in a first argument of the outlined function
2143// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
2144// regular serial code region, get thread ID by calling kmp_int32
2145// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
2146// return the address of that temp.
2147Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
2148 SourceLocation Loc) {
2149 if (auto *OMPRegionInfo =
2150 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
2151 if (OMPRegionInfo->getThreadIDVariable())
2152 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF);
2153
2154 llvm::Value *ThreadID = getThreadID(CGF, Loc);
2155 QualType Int32Ty =
2156 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
2157 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
2158 CGF.EmitStoreOfScalar(ThreadID,
2159 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
2160
2161 return ThreadIDTemp;
2162}
2163
2164llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
2165 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
2166 SmallString<256> Buffer;
2167 llvm::raw_svector_ostream Out(Buffer);
2168 Out << Name;
2169 StringRef RuntimeName = Out.str();
2170 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
2171 if (Elem.second) {
2172 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2173, __PRETTY_FUNCTION__))
2173 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2173, __PRETTY_FUNCTION__))
;
2174 return &*Elem.second;
2175 }
2176
2177 return Elem.second = new llvm::GlobalVariable(
2178 CGM.getModule(), Ty, /*IsConstant*/ false,
2179 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
2180 Elem.first(), /*InsertBefore=*/nullptr,
2181 llvm::GlobalValue::NotThreadLocal, AddressSpace);
2182}
2183
2184llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
2185 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
2186 std::string Name = getName({Prefix, "var"});
2187 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
2188}
2189
2190namespace {
2191/// Common pre(post)-action for different OpenMP constructs.
2192class CommonActionTy final : public PrePostActionTy {
2193 llvm::FunctionCallee EnterCallee;
2194 ArrayRef<llvm::Value *> EnterArgs;
2195 llvm::FunctionCallee ExitCallee;
2196 ArrayRef<llvm::Value *> ExitArgs;
2197 bool Conditional;
2198 llvm::BasicBlock *ContBlock = nullptr;
2199
2200public:
2201 CommonActionTy(llvm::FunctionCallee EnterCallee,
2202 ArrayRef<llvm::Value *> EnterArgs,
2203 llvm::FunctionCallee ExitCallee,
2204 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
2205 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2206 ExitArgs(ExitArgs), Conditional(Conditional) {}
2207 void Enter(CodeGenFunction &CGF) override {
2208 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
2209 if (Conditional) {
2210 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
2211 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
2212 ContBlock = CGF.createBasicBlock("omp_if.end");
2213 // Generate the branch (If-stmt)
2214 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2215 CGF.EmitBlock(ThenBlock);
2216 }
2217 }
2218 void Done(CodeGenFunction &CGF) {
2219 // Emit the rest of blocks/branches
2220 CGF.EmitBranch(ContBlock);
2221 CGF.EmitBlock(ContBlock, true);
2222 }
2223 void Exit(CodeGenFunction &CGF) override {
2224 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
2225 }
2226};
2227} // anonymous namespace
2228
2229void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
2230 StringRef CriticalName,
2231 const RegionCodeGenTy &CriticalOpGen,
2232 SourceLocation Loc, const Expr *Hint) {
2233 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
2234 // CriticalOpGen();
2235 // __kmpc_end_critical(ident_t *, gtid, Lock);
2236 // Prepare arguments and build a call to __kmpc_critical
2237 if (!CGF.HaveInsertPoint())
2238 return;
2239 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2240 getCriticalRegionLock(CriticalName)};
2241 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
2242 std::end(Args));
2243 if (Hint) {
2244 EnterArgs.push_back(CGF.Builder.CreateIntCast(
2245 CGF.EmitScalarExpr(Hint), CGM.Int32Ty, /*isSigned=*/false));
2246 }
2247 CommonActionTy Action(
2248 OMPBuilder.getOrCreateRuntimeFunction(
2249 CGM.getModule(),
2250 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical),
2251 EnterArgs,
2252 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
2253 OMPRTL___kmpc_end_critical),
2254 Args);
2255 CriticalOpGen.setAction(Action);
2256 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
2257}
2258
2259void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
2260 const RegionCodeGenTy &MasterOpGen,
2261 SourceLocation Loc) {
2262 if (!CGF.HaveInsertPoint())
2263 return;
2264 // if(__kmpc_master(ident_t *, gtid)) {
2265 // MasterOpGen();
2266 // __kmpc_end_master(ident_t *, gtid);
2267 // }
2268 // Prepare arguments and build a call to __kmpc_master
2269 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2270 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2271 CGM.getModule(), OMPRTL___kmpc_master),
2272 Args,
2273 OMPBuilder.getOrCreateRuntimeFunction(
2274 CGM.getModule(), OMPRTL___kmpc_end_master),
2275 Args,
2276 /*Conditional=*/true);
2277 MasterOpGen.setAction(Action);
2278 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
2279 Action.Done(CGF);
2280}
2281
2282void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
2283 SourceLocation Loc) {
2284 if (!CGF.HaveInsertPoint())
2285 return;
2286 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
2287 OMPBuilder.createTaskyield(CGF.Builder);
2288 } else {
2289 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
2290 llvm::Value *Args[] = {
2291 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2292 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
2293 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2294 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2295 Args);
2296 }
2297
2298 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
2299 Region->emitUntiedSwitch(CGF);
2300}
2301
2302void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
2303 const RegionCodeGenTy &TaskgroupOpGen,
2304 SourceLocation Loc) {
2305 if (!CGF.HaveInsertPoint())
2306 return;
2307 // __kmpc_taskgroup(ident_t *, gtid);
2308 // TaskgroupOpGen();
2309 // __kmpc_end_taskgroup(ident_t *, gtid);
2310 // Prepare arguments and build a call to __kmpc_taskgroup
2311 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2312 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2313 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2314 Args,
2315 OMPBuilder.getOrCreateRuntimeFunction(
2316 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2317 Args);
2318 TaskgroupOpGen.setAction(Action);
2319 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
2320}
2321
2322/// Given an array of pointers to variables, project the address of a
2323/// given variable.
2324static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
2325 unsigned Index, const VarDecl *Var) {
2326 // Pull out the pointer to the variable.
2327 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
2328 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
2329
2330 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
2331 Addr = CGF.Builder.CreateElementBitCast(
2332 Addr, CGF.ConvertTypeForMem(Var->getType()));
2333 return Addr;
2334}
2335
2336static llvm::Value *emitCopyprivateCopyFunction(
2337 CodeGenModule &CGM, llvm::Type *ArgsType,
2338 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
2339 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
2340 SourceLocation Loc) {
2341 ASTContext &C = CGM.getContext();
2342 // void copy_func(void *LHSArg, void *RHSArg);
2343 FunctionArgList Args;
2344 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
2345 ImplicitParamDecl::Other);
2346 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
2347 ImplicitParamDecl::Other);
2348 Args.push_back(&LHSArg);
2349 Args.push_back(&RHSArg);
2350 const auto &CGFI =
2351 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
2352 std::string Name =
2353 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
2354 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
2355 llvm::GlobalValue::InternalLinkage, Name,
2356 &CGM.getModule());
2357 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
2358 Fn->setDoesNotRecurse();
2359 CodeGenFunction CGF(CGM);
2360 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
2361 // Dest = (void*[n])(LHSArg);
2362 // Src = (void*[n])(RHSArg);
2363 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2364 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2365 ArgsType), CGF.getPointerAlign());
2366 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2367 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2368 ArgsType), CGF.getPointerAlign());
2369 // *(Type0*)Dst[0] = *(Type0*)Src[0];
2370 // *(Type1*)Dst[1] = *(Type1*)Src[1];
2371 // ...
2372 // *(Typen*)Dst[n] = *(Typen*)Src[n];
2373 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2374 const auto *DestVar =
2375 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2376 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
2377
2378 const auto *SrcVar =
2379 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2380 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
2381
2382 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2383 QualType Type = VD->getType();
2384 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2385 }
2386 CGF.FinishFunction();
2387 return Fn;
2388}
2389
2390void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
2391 const RegionCodeGenTy &SingleOpGen,
2392 SourceLocation Loc,
2393 ArrayRef<const Expr *> CopyprivateVars,
2394 ArrayRef<const Expr *> SrcExprs,
2395 ArrayRef<const Expr *> DstExprs,
2396 ArrayRef<const Expr *> AssignmentOps) {
2397 if (!CGF.HaveInsertPoint())
2398 return;
2399 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2401, __PRETTY_FUNCTION__))
2400 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2401, __PRETTY_FUNCTION__))
2401 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2401, __PRETTY_FUNCTION__))
;
2402 ASTContext &C = CGM.getContext();
2403 // int32 did_it = 0;
2404 // if(__kmpc_single(ident_t *, gtid)) {
2405 // SingleOpGen();
2406 // __kmpc_end_single(ident_t *, gtid);
2407 // did_it = 1;
2408 // }
2409 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2410 // <copy_func>, did_it);
2411
2412 Address DidIt = Address::invalid();
2413 if (!CopyprivateVars.empty()) {
2414 // int32 did_it = 0;
2415 QualType KmpInt32Ty =
2416 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2417 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
2418 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
2419 }
2420 // Prepare arguments and build a call to __kmpc_single
2421 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2422 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2423 CGM.getModule(), OMPRTL___kmpc_single),
2424 Args,
2425 OMPBuilder.getOrCreateRuntimeFunction(
2426 CGM.getModule(), OMPRTL___kmpc_end_single),
2427 Args,
2428 /*Conditional=*/true);
2429 SingleOpGen.setAction(Action);
2430 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
2431 if (DidIt.isValid()) {
2432 // did_it = 1;
2433 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
2434 }
2435 Action.Done(CGF);
2436 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2437 // <copy_func>, did_it);
2438 if (DidIt.isValid()) {
2439 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
2440 QualType CopyprivateArrayTy = C.getConstantArrayType(
2441 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
2442 /*IndexTypeQuals=*/0);
2443 // Create a list of all private variables for copyprivate.
2444 Address CopyprivateList =
2445 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
2446 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2447 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
2448 CGF.Builder.CreateStore(
2449 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2450 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF),
2451 CGF.VoidPtrTy),
2452 Elem);
2453 }
2454 // Build function that copies private values from single region to all other
2455 // threads in the corresponding parallel region.
2456 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
2457 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
2458 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
2459 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
2460 Address CL =
2461 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
2462 CGF.VoidPtrTy);
2463 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
2464 llvm::Value *Args[] = {
2465 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
2466 getThreadID(CGF, Loc), // i32 <gtid>
2467 BufSize, // size_t <buf_size>
2468 CL.getPointer(), // void *<copyprivate list>
2469 CpyFn, // void (*) (void *, void *) <copy_func>
2470 DidItVal // i32 did_it
2471 };
2472 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2473 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2474 Args);
2475 }
2476}
2477
2478void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
2479 const RegionCodeGenTy &OrderedOpGen,
2480 SourceLocation Loc, bool IsThreads) {
2481 if (!CGF.HaveInsertPoint())
2482 return;
2483 // __kmpc_ordered(ident_t *, gtid);
2484 // OrderedOpGen();
2485 // __kmpc_end_ordered(ident_t *, gtid);
2486 // Prepare arguments and build a call to __kmpc_ordered
2487 if (IsThreads) {
2488 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2489 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
2490 CGM.getModule(), OMPRTL___kmpc_ordered),
2491 Args,
2492 OMPBuilder.getOrCreateRuntimeFunction(
2493 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2494 Args);
2495 OrderedOpGen.setAction(Action);
2496 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2497 return;
2498 }
2499 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2500}
2501
2502unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
2503 unsigned Flags;
2504 if (Kind == OMPD_for)
2505 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2506 else if (Kind == OMPD_sections)
2507 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2508 else if (Kind == OMPD_single)
2509 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2510 else if (Kind == OMPD_barrier)
2511 Flags = OMP_IDENT_BARRIER_EXPL;
2512 else
2513 Flags = OMP_IDENT_BARRIER_IMPL;
2514 return Flags;
2515}
2516
2517void CGOpenMPRuntime::getDefaultScheduleAndChunk(
2518 CodeGenFunction &CGF, const OMPLoopDirective &S,
2519 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
2520 // Check if the loop directive is actually a doacross loop directive. In this
2521 // case choose static, 1 schedule.
2522 if (llvm::any_of(
2523 S.getClausesOfKind<OMPOrderedClause>(),
2524 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
2525 ScheduleKind = OMPC_SCHEDULE_static;
2526 // Chunk size is 1 in this case.
2527 llvm::APInt ChunkSize(32, 1);
2528 ChunkExpr = IntegerLiteral::Create(
2529 CGF.getContext(), ChunkSize,
2530 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
2531 SourceLocation());
2532 }
2533}
2534
2535void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
2536 OpenMPDirectiveKind Kind, bool EmitChecks,
2537 bool ForceSimpleCall) {
2538 // Check if we should use the OMPBuilder
2539 auto *OMPRegionInfo =
2540 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
2541 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
2542 CGF.Builder.restoreIP(OMPBuilder.createBarrier(
2543 CGF.Builder, Kind, ForceSimpleCall, EmitChecks));
2544 return;
2545 }
2546
2547 if (!CGF.HaveInsertPoint())
2548 return;
2549 // Build call __kmpc_cancel_barrier(loc, thread_id);
2550 // Build call __kmpc_barrier(loc, thread_id);
2551 unsigned Flags = getDefaultFlagsForBarriers(Kind);
2552 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
2553 // thread_id);
2554 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
2555 getThreadID(CGF, Loc)};
2556 if (OMPRegionInfo) {
2557 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2558 llvm::Value *Result = CGF.EmitRuntimeCall(
2559 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
2560 OMPRTL___kmpc_cancel_barrier),
2561 Args);
2562 if (EmitChecks) {
2563 // if (__kmpc_cancel_barrier()) {
2564 // exit from construct;
2565 // }
2566 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
2567 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
2568 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
2569 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2570 CGF.EmitBlock(ExitBB);
2571 // exit from construct;
2572 CodeGenFunction::JumpDest CancelDestination =
2573 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
2574 CGF.EmitBranchThroughCleanup(CancelDestination);
2575 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2576 }
2577 return;
2578 }
2579 }
2580 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2581 CGM.getModule(), OMPRTL___kmpc_barrier),
2582 Args);
2583}
2584
2585/// Map the OpenMP loop schedule to the runtime enumeration.
2586static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
2587 bool Chunked, bool Ordered) {
2588 switch (ScheduleKind) {
2589 case OMPC_SCHEDULE_static:
2590 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2591 : (Ordered ? OMP_ord_static : OMP_sch_static);
2592 case OMPC_SCHEDULE_dynamic:
2593 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2594 case OMPC_SCHEDULE_guided:
2595 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2596 case OMPC_SCHEDULE_runtime:
2597 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2598 case OMPC_SCHEDULE_auto:
2599 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2600 case OMPC_SCHEDULE_unknown:
2601 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2601, __PRETTY_FUNCTION__))
;
2602 return Ordered ? OMP_ord_static : OMP_sch_static;
2603 }
2604 llvm_unreachable("Unexpected runtime schedule")::llvm::llvm_unreachable_internal("Unexpected runtime schedule"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2604)
;
2605}
2606
2607/// Map the OpenMP distribute schedule to the runtime enumeration.
2608static OpenMPSchedType
2609getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
2610 // only static is allowed for dist_schedule
2611 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2612}
2613
2614bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
2615 bool Chunked) const {
2616 OpenMPSchedType Schedule =
2617 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
2618 return Schedule == OMP_sch_static;
2619}
2620
2621bool CGOpenMPRuntime::isStaticNonchunked(
2622 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2623 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2624 return Schedule == OMP_dist_sch_static;
2625}
2626
2627bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
2628 bool Chunked) const {
2629 OpenMPSchedType Schedule =
2630 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
2631 return Schedule == OMP_sch_static_chunked;
2632}
2633
2634bool CGOpenMPRuntime::isStaticChunked(
2635 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2636 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2637 return Schedule == OMP_dist_sch_static_chunked;
2638}
2639
2640bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
2641 OpenMPSchedType Schedule =
2642 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
2643 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2643, __PRETTY_FUNCTION__))
;
2644 return Schedule != OMP_sch_static;
2645}
2646
2647static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
2648 OpenMPScheduleClauseModifier M1,
2649 OpenMPScheduleClauseModifier M2) {
2650 int Modifier = 0;
2651 switch (M1) {
2652 case OMPC_SCHEDULE_MODIFIER_monotonic:
2653 Modifier = OMP_sch_modifier_monotonic;
2654 break;
2655 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2656 Modifier = OMP_sch_modifier_nonmonotonic;
2657 break;
2658 case OMPC_SCHEDULE_MODIFIER_simd:
2659 if (Schedule == OMP_sch_static_chunked)
2660 Schedule = OMP_sch_static_balanced_chunked;
2661 break;
2662 case OMPC_SCHEDULE_MODIFIER_last:
2663 case OMPC_SCHEDULE_MODIFIER_unknown:
2664 break;
2665 }
2666 switch (M2) {
2667 case OMPC_SCHEDULE_MODIFIER_monotonic:
2668 Modifier = OMP_sch_modifier_monotonic;
2669 break;
2670 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2671 Modifier = OMP_sch_modifier_nonmonotonic;
2672 break;
2673 case OMPC_SCHEDULE_MODIFIER_simd:
2674 if (Schedule == OMP_sch_static_chunked)
2675 Schedule = OMP_sch_static_balanced_chunked;
2676 break;
2677 case OMPC_SCHEDULE_MODIFIER_last:
2678 case OMPC_SCHEDULE_MODIFIER_unknown:
2679 break;
2680 }
2681 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
2682 // If the static schedule kind is specified or if the ordered clause is
2683 // specified, and if the nonmonotonic modifier is not specified, the effect is
2684 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
2685 // modifier is specified, the effect is as if the nonmonotonic modifier is
2686 // specified.
2687 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
2688 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2689 Schedule == OMP_sch_static_balanced_chunked ||
2690 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2691 Schedule == OMP_dist_sch_static_chunked ||
2692 Schedule == OMP_dist_sch_static))
2693 Modifier = OMP_sch_modifier_nonmonotonic;
2694 }
2695 return Schedule | Modifier;
2696}
2697
2698void CGOpenMPRuntime::emitForDispatchInit(
2699 CodeGenFunction &CGF, SourceLocation Loc,
2700 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
2701 bool Ordered, const DispatchRTInput &DispatchValues) {
2702 if (!CGF.HaveInsertPoint())
2703 return;
2704 OpenMPSchedType Schedule = getRuntimeSchedule(
2705 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
2706 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2709, __PRETTY_FUNCTION__))
2707 (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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2709, __PRETTY_FUNCTION__))
2708 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2709, __PRETTY_FUNCTION__))
2709 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2709, __PRETTY_FUNCTION__))
;
2710 // Call __kmpc_dispatch_init(
2711 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
2712 // kmp_int[32|64] lower, kmp_int[32|64] upper,
2713 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
2714
2715 // If the Chunk was not specified in the clause - use default value 1.
2716 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
2717 : CGF.Builder.getIntN(IVSize, 1);
2718 llvm::Value *Args[] = {
2719 emitUpdateLocation(CGF, Loc),
2720 getThreadID(CGF, Loc),
2721 CGF.Builder.getInt32(addMonoNonMonoModifier(
2722 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
2723 DispatchValues.LB, // Lower
2724 DispatchValues.UB, // Upper
2725 CGF.Builder.getIntN(IVSize, 1), // Stride
2726 Chunk // Chunk
2727 };
2728 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
2729}
2730
2731static void emitForStaticInitCall(
2732 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2733 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2734 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
2735 const CGOpenMPRuntime::StaticRTInput &Values) {
2736 if (!CGF.HaveInsertPoint())
2737 return;
2738
2739 assert(!Values.Ordered)((!Values.Ordered) ? static_cast<void> (0) : __assert_fail
("!Values.Ordered", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2739, __PRETTY_FUNCTION__))
;
2740 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2744, __PRETTY_FUNCTION__))
2741 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2744, __PRETTY_FUNCTION__))
2742 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2744, __PRETTY_FUNCTION__))
2743 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2744, __PRETTY_FUNCTION__))
2744 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2744, __PRETTY_FUNCTION__))
;
2745
2746 // Call __kmpc_for_static_init(
2747 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
2748 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
2749 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
2750 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
2751 llvm::Value *Chunk = Values.Chunk;
2752 if (Chunk == nullptr) {
2753 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2755, __PRETTY_FUNCTION__))
2754 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2755, __PRETTY_FUNCTION__))
2755 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2755, __PRETTY_FUNCTION__))
;
2756 // If the Chunk was not specified in the clause - use default value 1.
2757 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
2758 } else {
2759 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2763, __PRETTY_FUNCTION__))
2760 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2763, __PRETTY_FUNCTION__))
2761 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2763, __PRETTY_FUNCTION__))
2762 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2763, __PRETTY_FUNCTION__))
2763 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2763, __PRETTY_FUNCTION__))
;
2764 }
2765 llvm::Value *Args[] = {
2766 UpdateLocation,
2767 ThreadId,
2768 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
2769 M2)), // Schedule type
2770 Values.IL.getPointer(), // &isLastIter
2771 Values.LB.getPointer(), // &LB
2772 Values.UB.getPointer(), // &UB
2773 Values.ST.getPointer(), // &Stride
2774 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
2775 Chunk // Chunk
2776 };
2777 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
2778}
2779
2780void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
2781 SourceLocation Loc,
2782 OpenMPDirectiveKind DKind,
2783 const OpenMPScheduleTy &ScheduleKind,
2784 const StaticRTInput &Values) {
2785 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
2786 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
2787 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2788, __PRETTY_FUNCTION__))
2788 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2788, __PRETTY_FUNCTION__))
;
2789 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
2790 isOpenMPLoopDirective(DKind)
2791 ? OMP_IDENT_WORK_LOOP
2792 : OMP_IDENT_WORK_SECTIONS);
2793 llvm::Value *ThreadId = getThreadID(CGF, Loc);
2794 llvm::FunctionCallee StaticInitFunction =
2795 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
2796 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
2797 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
2798 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
2799}
2800
2801void CGOpenMPRuntime::emitDistributeStaticInit(
2802 CodeGenFunction &CGF, SourceLocation Loc,
2803 OpenMPDistScheduleClauseKind SchedKind,
2804 const CGOpenMPRuntime::StaticRTInput &Values) {
2805 OpenMPSchedType ScheduleNum =
2806 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
2807 llvm::Value *UpdatedLocation =
2808 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
2809 llvm::Value *ThreadId = getThreadID(CGF, Loc);
2810 llvm::FunctionCallee StaticInitFunction =
2811 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
2812 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
2813 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
2814 OMPC_SCHEDULE_MODIFIER_unknown, Values);
2815}
2816
2817void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
2818 SourceLocation Loc,
2819 OpenMPDirectiveKind DKind) {
2820 if (!CGF.HaveInsertPoint())
2821 return;
2822 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
2823 llvm::Value *Args[] = {
2824 emitUpdateLocation(CGF, Loc,
2825 isOpenMPDistributeDirective(DKind)
2826 ? OMP_IDENT_WORK_DISTRIBUTE
2827 : isOpenMPLoopDirective(DKind)
2828 ? OMP_IDENT_WORK_LOOP
2829 : OMP_IDENT_WORK_SECTIONS),
2830 getThreadID(CGF, Loc)};
2831 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
2832 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2833 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2834 Args);
2835}
2836
2837void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
2838 SourceLocation Loc,
2839 unsigned IVSize,
2840 bool IVSigned) {
2841 if (!CGF.HaveInsertPoint())
2842 return;
2843 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
2844 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2845 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
2846}
2847
2848llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
2849 SourceLocation Loc, unsigned IVSize,
2850 bool IVSigned, Address IL,
2851 Address LB, Address UB,
2852 Address ST) {
2853 // Call __kmpc_dispatch_next(
2854 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2855 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2856 // kmp_int[32|64] *p_stride);
2857 llvm::Value *Args[] = {
2858 emitUpdateLocation(CGF, Loc),
2859 getThreadID(CGF, Loc),
2860 IL.getPointer(), // &isLastIter
2861 LB.getPointer(), // &Lower
2862 UB.getPointer(), // &Upper
2863 ST.getPointer() // &Stride
2864 };
2865 llvm::Value *Call =
2866 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
2867 return CGF.EmitScalarConversion(
2868 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
2869 CGF.getContext().BoolTy, Loc);
2870}
2871
2872void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
2873 llvm::Value *NumThreads,
2874 SourceLocation Loc) {
2875 if (!CGF.HaveInsertPoint())
2876 return;
2877 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
2878 llvm::Value *Args[] = {
2879 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2880 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
2881 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2882 CGM.getModule(), OMPRTL___kmpc_push_num_threads),
2883 Args);
2884}
2885
2886void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
2887 ProcBindKind ProcBind,
2888 SourceLocation Loc) {
2889 if (!CGF.HaveInsertPoint())
2890 return;
2891 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2891, __PRETTY_FUNCTION__))
;
2892 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
2893 llvm::Value *Args[] = {
2894 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2895 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)};
2896 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2897 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2898 Args);
2899}
2900
2901void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
2902 SourceLocation Loc, llvm::AtomicOrdering AO) {
2903 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
2904 OMPBuilder.createFlush(CGF.Builder);
2905 } else {
2906 if (!CGF.HaveInsertPoint())
2907 return;
2908 // Build call void __kmpc_flush(ident_t *loc)
2909 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
2910 CGM.getModule(), OMPRTL___kmpc_flush),
2911 emitUpdateLocation(CGF, Loc));
2912 }
2913}
2914
2915namespace {
2916/// Indexes of fields for type kmp_task_t.
2917enum KmpTaskTFields {
2918 /// List of shared variables.
2919 KmpTaskTShareds,
2920 /// Task routine.
2921 KmpTaskTRoutine,
2922 /// Partition id for the untied tasks.
2923 KmpTaskTPartId,
2924 /// Function with call of destructors for private variables.
2925 Data1,
2926 /// Task priority.
2927 Data2,
2928 /// (Taskloops only) Lower bound.
2929 KmpTaskTLowerBound,
2930 /// (Taskloops only) Upper bound.
2931 KmpTaskTUpperBound,
2932 /// (Taskloops only) Stride.
2933 KmpTaskTStride,
2934 /// (Taskloops only) Is last iteration flag.
2935 KmpTaskTLastIter,
2936 /// (Taskloops only) Reduction data.
2937 KmpTaskTReductions,
2938};
2939} // anonymous namespace
2940
2941bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
2942 return OffloadEntriesTargetRegion.empty() &&
2943 OffloadEntriesDeviceGlobalVar.empty();
2944}
2945
2946/// Initialize target region entry.
2947void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2948 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2949 StringRef ParentName, unsigned LineNum,
2950 unsigned Order) {
2951 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2953, __PRETTY_FUNCTION__))
2952 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2953, __PRETTY_FUNCTION__))
2953 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2953, __PRETTY_FUNCTION__))
;
2954 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
2955 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
2956 OMPTargetRegionEntryTargetRegion);
2957 ++OffloadingEntriesNum;
2958}
2959
2960void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2961 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2962 StringRef ParentName, unsigned LineNum,
2963 llvm::Constant *Addr, llvm::Constant *ID,
2964 OMPTargetRegionEntryKind Flags) {
2965 // If we are emitting code for a target, the entry is already initialized,
2966 // only has to be registered.
2967 if (CGM.getLangOpts().OpenMPIsDevice) {
2968 // This could happen if the device compilation is invoked standalone.
2969 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum))
2970 initializeTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum,
2971 OffloadingEntriesNum);
2972 auto &Entry =
2973 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
2974 Entry.setAddress(Addr);
2975 Entry.setID(ID);
2976 Entry.setFlags(Flags);
2977 } else {
2978 if (Flags ==
2979 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion &&
2980 hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum,
2981 /*IgnoreAddressId*/ true))
2982 return;
2983 assert(!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) &&((!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum
) && "Target region entry already registered!") ? static_cast
<void> (0) : __assert_fail ("!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) && \"Target region entry already registered!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2984, __PRETTY_FUNCTION__))
2984 "Target region entry already registered!")((!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum
) && "Target region entry already registered!") ? static_cast
<void> (0) : __assert_fail ("!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) && \"Target region entry already registered!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 2984, __PRETTY_FUNCTION__))
;
2985 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
2986 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
2987 ++OffloadingEntriesNum;
2988 }
2989}
2990
2991bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
2992 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum,
2993 bool IgnoreAddressId) const {
2994 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
2995 if (PerDevice == OffloadEntriesTargetRegion.end())
2996 return false;
2997 auto PerFile = PerDevice->second.find(FileID);
2998 if (PerFile == PerDevice->second.end())
2999 return false;
3000 auto PerParentName = PerFile->second.find(ParentName);
3001 if (PerParentName == PerFile->second.end())
3002 return false;
3003 auto PerLine = PerParentName->second.find(LineNum);
3004 if (PerLine == PerParentName->second.end())
3005 return false;
3006 // Fail if this entry is already registered.
3007 if (!IgnoreAddressId &&
3008 (PerLine->second.getAddress() || PerLine->second.getID()))
3009 return false;
3010 return true;
3011}
3012
3013void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3014 const OffloadTargetRegionEntryInfoActTy &Action) {
3015 // Scan all target region entries and perform the provided action.
3016 for (const auto &D : OffloadEntriesTargetRegion)
3017 for (const auto &F : D.second)
3018 for (const auto &P : F.second)
3019 for (const auto &L : P.second)
3020 Action(D.first, F.first, P.first(), L.first, L.second);
3021}
3022
3023void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3024 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3025 OMPTargetGlobalVarEntryKind Flags,
3026 unsigned Order) {
3027 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3029, __PRETTY_FUNCTION__))
3028 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3029, __PRETTY_FUNCTION__))
3029 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3029, __PRETTY_FUNCTION__))
;
3030 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3031 ++OffloadingEntriesNum;
3032}
3033
3034void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3035 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3036 CharUnits VarSize,
3037 OMPTargetGlobalVarEntryKind Flags,
3038 llvm::GlobalValue::LinkageTypes Linkage) {
3039 if (CGM.getLangOpts().OpenMPIsDevice) {
3040 // This could happen if the device compilation is invoked standalone.
3041 if (!hasDeviceGlobalVarEntryInfo(VarName))
3042 initializeDeviceGlobalVarEntryInfo(VarName, Flags, OffloadingEntriesNum);
3043 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3044 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3045, __PRETTY_FUNCTION__))
3045 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3045, __PRETTY_FUNCTION__))
;
3046 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3047 if (Entry.getVarSize().isZero()) {
3048 Entry.setVarSize(VarSize);
3049 Entry.setLinkage(Linkage);
3050 }
3051 return;
3052 }
3053 Entry.setVarSize(VarSize);
3054 Entry.setLinkage(Linkage);
3055 Entry.setAddress(Addr);
3056 } else {
3057 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3058 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3059 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3060, __PRETTY_FUNCTION__))
3060 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3060, __PRETTY_FUNCTION__))
;
3061 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3062, __PRETTY_FUNCTION__))
3062 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3062, __PRETTY_FUNCTION__))
;
3063 if (Entry.getVarSize().isZero()) {
3064 Entry.setVarSize(VarSize);
3065 Entry.setLinkage(Linkage);
3066 }
3067 return;
3068 }
3069 OffloadEntriesDeviceGlobalVar.try_emplace(
3070 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
3071 ++OffloadingEntriesNum;
3072 }
3073}
3074
3075void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3076 actOnDeviceGlobalVarEntriesInfo(
3077 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
3078 // Scan all target region entries and perform the provided action.
3079 for (const auto &E : OffloadEntriesDeviceGlobalVar)
3080 Action(E.getKey(), E.getValue());
3081}
3082
3083void CGOpenMPRuntime::createOffloadEntry(
3084 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
3085 llvm::GlobalValue::LinkageTypes Linkage) {
3086 StringRef Name = Addr->getName();
3087 llvm::Module &M = CGM.getModule();
3088 llvm::LLVMContext &C = M.getContext();
3089
3090 // Create constant string with the name.
3091 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
3092
3093 std::string StringName = getName({"omp_offloading", "entry_name"});
3094 auto *Str = new llvm::GlobalVariable(
3095 M, StrPtrInit->getType(), /*isConstant=*/true,
3096 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
3097 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
3098
3099 llvm::Constant *Data[] = {
3100 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(ID, CGM.VoidPtrTy),
3101 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, CGM.Int8PtrTy),
3102 llvm::ConstantInt::get(CGM.SizeTy, Size),
3103 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
3104 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
3105 std::string EntryName = getName({"omp_offloading", "entry", ""});
3106 llvm::GlobalVariable *Entry = createGlobalStruct(
3107 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
3108 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
3109
3110 // The entry has to be created in the section the linker expects it to be.
3111 Entry->setSection("omp_offloading_entries");
3112}
3113
3114void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
3115 // Emit the offloading entries and metadata so that the device codegen side
3116 // can easily figure out what to emit. The produced metadata looks like
3117 // this:
3118 //
3119 // !omp_offload.info = !{!1, ...}
3120 //
3121 // Right now we only generate metadata for function that contain target
3122 // regions.
3123
3124 // If we are in simd mode or there are no entries, we don't need to do
3125 // anything.
3126 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty())
3127 return;
3128
3129 llvm::Module &M = CGM.getModule();
3130 llvm::LLVMContext &C = M.getContext();
3131 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *,
3132 SourceLocation, StringRef>,
3133 16>
3134 OrderedEntries(OffloadEntriesInfoManager.size());
3135 llvm::SmallVector<StringRef, 16> ParentFunctions(
3136 OffloadEntriesInfoManager.size());
3137
3138 // Auxiliary methods to create metadata values and strings.
3139 auto &&GetMDInt = [this](unsigned V) {
3140 return llvm::ConstantAsMetadata::get(
3141 llvm::ConstantInt::get(CGM.Int32Ty, V));
3142 };
3143
3144 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
3145
3146 // Create the offloading info metadata node.
3147 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
3148
3149 // Create function that emits metadata for each target region entry;
3150 auto &&TargetRegionMetadataEmitter =
3151 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt,
3152 &GetMDString](
3153 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3154 unsigned Line,
3155 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
3156 // Generate metadata for target regions. Each entry of this metadata
3157 // contains:
3158 // - Entry 0 -> Kind of this type of metadata (0).
3159 // - Entry 1 -> Device ID of the file where the entry was identified.
3160 // - Entry 2 -> File ID of the file where the entry was identified.
3161 // - Entry 3 -> Mangled name of the function where the entry was
3162 // identified.
3163 // - Entry 4 -> Line in the file where the entry was identified.
3164 // - Entry 5 -> Order the entry was created.
3165 // The first element of the metadata node is the kind.
3166 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
3167 GetMDInt(FileID), GetMDString(ParentName),
3168 GetMDInt(Line), GetMDInt(E.getOrder())};
3169
3170 SourceLocation Loc;
3171 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
3172 E = CGM.getContext().getSourceManager().fileinfo_end();
3173 I != E; ++I) {
3174 if (I->getFirst()->getUniqueID().getDevice() == DeviceID &&
3175 I->getFirst()->getUniqueID().getFile() == FileID) {
3176 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
3177 I->getFirst(), Line, 1);
3178 break;
3179 }
3180 }
3181 // Save this entry in the right position of the ordered entries array.
3182 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName);
3183 ParentFunctions[E.getOrder()] = ParentName;
3184
3185 // Add metadata to the named metadata node.
3186 MD->addOperand(llvm::MDNode::get(C, Ops));
3187 };
3188
3189 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
3190 TargetRegionMetadataEmitter);
3191
3192 // Create function that emits metadata for each device global variable entry;
3193 auto &&DeviceGlobalVarMetadataEmitter =
3194 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
3195 MD](StringRef MangledName,
3196 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
3197 &E) {
3198 // Generate metadata for global variables. Each entry of this metadata
3199 // contains:
3200 // - Entry 0 -> Kind of this type of metadata (1).
3201 // - Entry 1 -> Mangled name of the variable.
3202 // - Entry 2 -> Declare target kind.
3203 // - Entry 3 -> Order the entry was created.
3204 // The first element of the metadata node is the kind.
3205 llvm::Metadata *Ops[] = {
3206 GetMDInt(E.getKind()), GetMDString(MangledName),
3207 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
3208
3209 // Save this entry in the right position of the ordered entries array.
3210 OrderedEntries[E.getOrder()] =
3211 std::make_tuple(&E, SourceLocation(), MangledName);
3212
3213 // Add metadata to the named metadata node.
3214 MD->addOperand(llvm::MDNode::get(C, Ops));
3215 };
3216
3217 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
3218 DeviceGlobalVarMetadataEmitter);
3219
3220 for (const auto &E : OrderedEntries) {
3221 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3221, __PRETTY_FUNCTION__))
;
3222 if (const auto *CE =
3223 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
3224 std::get<0>(E))) {
3225 if (!CE->getID() || !CE->getAddress()) {
3226 // Do not blame the entry if the parent funtion is not emitted.
3227 StringRef FnName = ParentFunctions[CE->getOrder()];
3228 if (!CGM.GetGlobalValue(FnName))
3229 continue;
3230 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3231 DiagnosticsEngine::Error,
3232 "Offloading entry for target region in %0 is incorrect: either the "
3233 "address or the ID is invalid.");
3234 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName;
3235 continue;
3236 }
3237 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
3238 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
3239 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy::
3240 OffloadEntryInfoDeviceGlobalVar>(
3241 std::get<0>(E))) {
3242 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
3243 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
3244 CE->getFlags());
3245 switch (Flags) {
3246 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
3247 if (CGM.getLangOpts().OpenMPIsDevice &&
3248 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
3249 continue;
3250 if (!CE->getAddress()) {
3251 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3252 DiagnosticsEngine::Error, "Offloading entry for declare target "
3253 "variable %0 is incorrect: the "
3254 "address is invalid.");
3255 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E);
3256 continue;
3257 }
3258 // The vaiable has no definition - no need to add the entry.
3259 if (CE->getVarSize().isZero())
3260 continue;
3261 break;
3262 }
3263 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
3264 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3266, __PRETTY_FUNCTION__))
3265 (!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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3266, __PRETTY_FUNCTION__))
3266 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3266, __PRETTY_FUNCTION__))
;
3267 if (CGM.getLangOpts().OpenMPIsDevice)
3268 continue;
3269 if (!CE->getAddress()) {
3270 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3271 DiagnosticsEngine::Error,
3272 "Offloading entry for declare target variable is incorrect: the "
3273 "address is invalid.");
3274 CGM.getDiags().Report(DiagID);
3275 continue;
3276 }
3277 break;
3278 }
3279 createOffloadEntry(CE->getAddress(), CE->getAddress(),
3280 CE->getVarSize().getQuantity(), Flags,
3281 CE->getLinkage());
3282 } else {
3283 llvm_unreachable("Unsupported entry kind.")::llvm::llvm_unreachable_internal("Unsupported entry kind.", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3283)
;
3284 }
3285 }
3286}
3287
3288/// Loads all the offload entries information from the host IR
3289/// metadata.
3290void CGOpenMPRuntime::loadOffloadInfoMetadata() {
3291 // If we are in target mode, load the metadata from the host IR. This code has
3292 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
3293
3294 if (!CGM.getLangOpts().OpenMPIsDevice)
3295 return;
3296
3297 if (CGM.getLangOpts().OMPHostIRFile.empty())
3298 return;
3299
3300 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
3301 if (auto EC = Buf.getError()) {
3302 CGM.getDiags().Report(diag::err_cannot_open_file)
3303 << CGM.getLangOpts().OMPHostIRFile << EC.message();
3304 return;
3305 }
3306
3307 llvm::LLVMContext C;
3308 auto ME = expectedToErrorOrAndEmitErrors(
3309 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
3310
3311 if (auto EC = ME.getError()) {
3312 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3313 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
3314 CGM.getDiags().Report(DiagID)
3315 << CGM.getLangOpts().OMPHostIRFile << EC.message();
3316 return;
3317 }
3318
3319 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
3320 if (!MD)
3321 return;
3322
3323 for (llvm::MDNode *MN : MD->operands()) {
3324 auto &&GetMDInt = [MN](unsigned Idx) {
3325 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
3326 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
3327 };
3328
3329 auto &&GetMDString = [MN](unsigned Idx) {
3330 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
3331 return V->getString();
3332 };
3333
3334 switch (GetMDInt(0)) {
3335 default:
3336 llvm_unreachable("Unexpected metadata!")::llvm::llvm_unreachable_internal("Unexpected metadata!", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3336)
;
3337 break;
3338 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
3339 OffloadingEntryInfoTargetRegion:
3340 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
3341 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
3342 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
3343 /*Order=*/GetMDInt(5));
3344 break;
3345 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
3346 OffloadingEntryInfoDeviceGlobalVar:
3347 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
3348 /*MangledName=*/GetMDString(1),
3349 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
3350 /*Flags=*/GetMDInt(2)),
3351 /*Order=*/GetMDInt(3));
3352 break;
3353 }
3354 }
3355}
3356
3357void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
3358 if (!KmpRoutineEntryPtrTy) {
3359 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
3360 ASTContext &C = CGM.getContext();
3361 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
3362 FunctionProtoType::ExtProtoInfo EPI;
3363 KmpRoutineEntryPtrQTy = C.getPointerType(
3364 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3365 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
3366 }
3367}
3368
3369QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
3370 // Make sure the type of the entry is already created. This is the type we
3371 // have to create:
3372 // struct __tgt_offload_entry{
3373 // void *addr; // Pointer to the offload entry info.
3374 // // (function or global)
3375 // char *name; // Name of the function or global.
3376 // size_t size; // Size of the entry info (0 if it a function).
3377 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
3378 // int32_t reserved; // Reserved, to use by the runtime library.
3379 // };
3380 if (TgtOffloadEntryQTy.isNull()) {
3381 ASTContext &C = CGM.getContext();
3382 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
3383 RD->startDefinition();
3384 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3385 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
3386 addFieldToRecordDecl(C, RD, C.getSizeType());
3387 addFieldToRecordDecl(
3388 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
3389 addFieldToRecordDecl(
3390 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
3391 RD->completeDefinition();
3392 RD->addAttr(PackedAttr::CreateImplicit(C));
3393 TgtOffloadEntryQTy = C.getRecordType(RD);
3394 }
3395 return TgtOffloadEntryQTy;
3396}
3397
3398namespace {
3399struct PrivateHelpersTy {
3400 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original,
3401 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit)
3402 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
3403 PrivateElemInit(PrivateElemInit) {}
3404 PrivateHelpersTy(const VarDecl *Original) : Original(Original) {}
3405 const Expr *OriginalRef = nullptr;
3406 const VarDecl *Original = nullptr;
3407 const VarDecl *PrivateCopy = nullptr;
3408 const VarDecl *PrivateElemInit = nullptr;
3409 bool isLocalPrivate() const {
3410 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
3411 }
3412};
3413typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
3414} // anonymous namespace
3415
3416static bool isAllocatableDecl(const VarDecl *VD) {
3417 const VarDecl *CVD = VD->getCanonicalDecl();
3418 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
3419 return false;
3420 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
3421 // Use the default allocation.
3422 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
3423 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
3424 !AA->getAllocator());
3425}
3426
3427static RecordDecl *
3428createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
3429 if (!Privates.empty()) {
3430 ASTContext &C = CGM.getContext();
3431 // Build struct .kmp_privates_t. {
3432 // /* private vars */
3433 // };
3434 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
3435 RD->startDefinition();
3436 for (const auto &Pair : Privates) {
3437 const VarDecl *VD = Pair.second.Original;
3438 QualType Type = VD->getType().getNonReferenceType();
3439 // If the private variable is a local variable with lvalue ref type,
3440 // allocate the pointer instead of the pointee type.
3441 if (Pair.second.isLocalPrivate()) {
3442 if (VD->getType()->isLValueReferenceType())
3443 Type = C.getPointerType(Type);
3444 if (isAllocatableDecl(VD))
3445 Type = C.getPointerType(Type);
3446 }
3447 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
3448 if (VD->hasAttrs()) {
3449 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
3450 E(VD->getAttrs().end());
3451 I != E; ++I)
3452 FD->addAttr(*I);
3453 }
3454 }
3455 RD->completeDefinition();
3456 return RD;
3457 }
3458 return nullptr;
3459}
3460
3461static RecordDecl *
3462createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
3463 QualType KmpInt32Ty,
3464 QualType KmpRoutineEntryPointerQTy) {
3465 ASTContext &C = CGM.getContext();
3466 // Build struct kmp_task_t {
3467 // void * shareds;
3468 // kmp_routine_entry_t routine;
3469 // kmp_int32 part_id;
3470 // kmp_cmplrdata_t data1;
3471 // kmp_cmplrdata_t data2;
3472 // For taskloops additional fields:
3473 // kmp_uint64 lb;
3474 // kmp_uint64 ub;
3475 // kmp_int64 st;
3476 // kmp_int32 liter;
3477 // void * reductions;
3478 // };
3479 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
3480 UD->startDefinition();
3481 addFieldToRecordDecl(C, UD, KmpInt32Ty);
3482 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
3483 UD->completeDefinition();
3484 QualType KmpCmplrdataTy = C.getRecordType(UD);
3485 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
3486 RD->startDefinition();
3487 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3488 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
3489 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3490 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
3491 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
3492 if (isOpenMPTaskLoopDirective(Kind)) {
3493 QualType KmpUInt64Ty =
3494 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
3495 QualType KmpInt64Ty =
3496 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
3497 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
3498 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
3499 addFieldToRecordDecl(C, RD, KmpInt64Ty);
3500 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3501 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3502 }
3503 RD->completeDefinition();
3504 return RD;
3505}
3506
3507static RecordDecl *
3508createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
3509 ArrayRef<PrivateDataTy> Privates) {
3510 ASTContext &C = CGM.getContext();
3511 // Build struct kmp_task_t_with_privates {
3512 // kmp_task_t task_data;
3513 // .kmp_privates_t. privates;
3514 // };
3515 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
3516 RD->startDefinition();
3517 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
3518 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
3519 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
3520 RD->completeDefinition();
3521 return RD;
3522}
3523
3524/// Emit a proxy function which accepts kmp_task_t as the second
3525/// argument.
3526/// \code
3527/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
3528/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
3529/// For taskloops:
3530/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
3531/// tt->reductions, tt->shareds);
3532/// return 0;
3533/// }
3534/// \endcode
3535static llvm::Function *
3536emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
3537 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
3538 QualType KmpTaskTWithPrivatesPtrQTy,
3539 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
3540 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3541 llvm::Value *TaskPrivatesMap) {
3542 ASTContext &C = CGM.getContext();
3543 FunctionArgList Args;
3544 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
3545 ImplicitParamDecl::Other);
3546 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3547 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
3548 ImplicitParamDecl::Other);
3549 Args.push_back(&GtidArg);
3550 Args.push_back(&TaskTypeArg);
3551 const auto &TaskEntryFnInfo =
3552 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
3553 llvm::FunctionType *TaskEntryTy =
3554 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
3555 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
3556 auto *TaskEntry = llvm::Function::Create(
3557 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
3558 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
3559 TaskEntry->setDoesNotRecurse();
3560 CodeGenFunction CGF(CGM);
3561 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
3562 Loc, Loc);
3563
3564 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
3565 // tt,
3566 // For taskloops:
3567 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
3568 // tt->task_data.shareds);
3569 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
3570 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
3571 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3572 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3573 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3574 const auto *KmpTaskTWithPrivatesQTyRD =
3575 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3576 LValue Base =
3577 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
3578 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
3579 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3580 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
3581 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3582
3583 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3584 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
3585 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3586 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
3587 CGF.ConvertTypeForMem(SharedsPtrTy));
3588
3589 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3590 llvm::Value *PrivatesParam;
3591 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3592 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
3593 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3594 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy);
3595 } else {
3596 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3597 }
3598
3599 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
3600 TaskPrivatesMap,
3601 CGF.Builder
3602 .CreatePointerBitCastOrAddrSpaceCast(
3603 TDBase.getAddress(CGF), CGF.VoidPtrTy)
3604 .getPointer()};
3605 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
3606 std::end(CommonArgs));
3607 if (isOpenMPTaskLoopDirective(Kind)) {
3608 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3609 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
3610 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
3611 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3612 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
3613 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
3614 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3615 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
3616 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
3617 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3618 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
3619 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
3620 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3621 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
3622 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
3623 CallArgs.push_back(LBParam);
3624 CallArgs.push_back(UBParam);
3625 CallArgs.push_back(StParam);
3626 CallArgs.push_back(LIParam);
3627 CallArgs.push_back(RParam);
3628 }
3629 CallArgs.push_back(SharedsParam);
3630
3631 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
3632 CallArgs);
3633 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
3634 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
3635 CGF.FinishFunction();
3636 return TaskEntry;
3637}
3638
3639static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
3640 SourceLocation Loc,
3641 QualType KmpInt32Ty,
3642 QualType KmpTaskTWithPrivatesPtrQTy,
3643 QualType KmpTaskTWithPrivatesQTy) {
3644 ASTContext &C = CGM.getContext();
3645 FunctionArgList Args;
3646 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
3647 ImplicitParamDecl::Other);
3648 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3649 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
3650 ImplicitParamDecl::Other);
3651 Args.push_back(&GtidArg);
3652 Args.push_back(&TaskTypeArg);
3653 const auto &DestructorFnInfo =
3654 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
3655 llvm::FunctionType *DestructorFnTy =
3656 CGM.getTypes().GetFunctionType(DestructorFnInfo);
3657 std::string Name =
3658 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
3659 auto *DestructorFn =
3660 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3661 Name, &CGM.getModule());
3662 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
3663 DestructorFnInfo);
3664 DestructorFn->setDoesNotRecurse();
3665 CodeGenFunction CGF(CGM);
3666 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
3667 Args, Loc, Loc);
3668
3669 LValue Base = CGF.EmitLoadOfPointerLValue(
3670 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3671 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3672 const auto *KmpTaskTWithPrivatesQTyRD =
3673 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3674 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3675 Base = CGF.EmitLValueForField(Base, *FI);
3676 for (const auto *Field :
3677 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3678 if (QualType::DestructionKind DtorKind =
3679 Field->getType().isDestructedType()) {
3680 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
3681 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType());
3682 }
3683 }
3684 CGF.FinishFunction();
3685 return DestructorFn;
3686}
3687
3688/// Emit a privates mapping function for correct handling of private and
3689/// firstprivate variables.
3690/// \code
3691/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
3692/// **noalias priv1,..., <tyn> **noalias privn) {
3693/// *priv1 = &.privates.priv1;
3694/// ...;
3695/// *privn = &.privates.privn;
3696/// }
3697/// \endcode
3698static llvm::Value *
3699emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
3700 const OMPTaskDataTy &Data, QualType PrivatesQTy,
3701 ArrayRef<PrivateDataTy> Privates) {
3702 ASTContext &C = CGM.getContext();
3703 FunctionArgList Args;
3704 ImplicitParamDecl TaskPrivatesArg(
3705 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3706 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3707 ImplicitParamDecl::Other);
3708 Args.push_back(&TaskPrivatesArg);
3709 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, unsigned> PrivateVarsPos;
3710 unsigned Counter = 1;
3711 for (const Expr *E : Data.PrivateVars) {
3712 Args.push_back(ImplicitParamDecl::Create(
3713 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3714 C.getPointerType(C.getPointerType(E->getType()))
3715 .withConst()
3716 .withRestrict(),
3717 ImplicitParamDecl::Other));
3718 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3719 PrivateVarsPos[VD] = Counter;
3720 ++Counter;
3721 }
3722 for (const Expr *E : Data.FirstprivateVars) {
3723 Args.push_back(ImplicitParamDecl::Create(
3724 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3725 C.getPointerType(C.getPointerType(E->getType()))
3726 .withConst()
3727 .withRestrict(),
3728 ImplicitParamDecl::Other));
3729 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3730 PrivateVarsPos[VD] = Counter;
3731 ++Counter;
3732 }
3733 for (const Expr *E : Data.LastprivateVars) {
3734 Args.push_back(ImplicitParamDecl::Create(
3735 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3736 C.getPointerType(C.getPointerType(E->getType()))
3737 .withConst()
3738 .withRestrict(),
3739 ImplicitParamDecl::Other));
3740 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3741 PrivateVarsPos[VD] = Counter;
3742 ++Counter;
3743 }
3744 for (const VarDecl *VD : Data.PrivateLocals) {
3745 QualType Ty = VD->getType().getNonReferenceType();
3746 if (VD->getType()->isLValueReferenceType())
3747 Ty = C.getPointerType(Ty);
3748 if (isAllocatableDecl(VD))
3749 Ty = C.getPointerType(Ty);
3750 Args.push_back(ImplicitParamDecl::Create(
3751 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3752 C.getPointerType(C.getPointerType(Ty)).withConst().withRestrict(),
3753 ImplicitParamDecl::Other));
3754 PrivateVarsPos[VD] = Counter;
3755 ++Counter;
3756 }
3757 const auto &TaskPrivatesMapFnInfo =
3758 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
3759 llvm::FunctionType *TaskPrivatesMapTy =
3760 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
3761 std::string Name =
3762 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
3763 auto *TaskPrivatesMap = llvm::Function::Create(
3764 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3765 &CGM.getModule());
3766 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
3767 TaskPrivatesMapFnInfo);
3768 if (CGM.getLangOpts().Optimize) {
3769 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3770 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3771 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3772 }
3773 CodeGenFunction CGF(CGM);
3774 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
3775 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3776
3777 // *privi = &.privates.privi;
3778 LValue Base = CGF.EmitLoadOfPointerLValue(
3779 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
3780 TaskPrivatesArg.getType()->castAs<PointerType>());
3781 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
3782 Counter = 0;
3783 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
3784 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
3785 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
3786 LValue RefLVal =
3787 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
3788 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
3789 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>());
3790 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal);
3791 ++Counter;
3792 }
3793 CGF.FinishFunction();
3794 return TaskPrivatesMap;
3795}
3796
3797/// Emit initialization for private variables in task-based directives.
3798static void emitPrivatesInit(CodeGenFunction &CGF,
3799 const OMPExecutableDirective &D,
3800 Address KmpTaskSharedsPtr, LValue TDBase,
3801 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
3802 QualType SharedsTy, QualType SharedsPtrTy,
3803 const OMPTaskDataTy &Data,
3804 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
3805 ASTContext &C = CGF.getContext();
3806 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3807 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
3808 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
3809 ? OMPD_taskloop
3810 : OMPD_task;
3811 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
3812 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
3813 LValue SrcBase;
3814 bool IsTargetTask =
3815 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
3816 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
3817 // For target-based directives skip 4 firstprivate arrays BasePointersArray,
3818 // PointersArray, SizesArray, and MappersArray. The original variables for
3819 // these arrays are not captured and we get their addresses explicitly.
3820 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) ||
3821 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
3822 SrcBase = CGF.MakeAddrLValue(
3823 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3824 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
3825 SharedsTy);
3826 }
3827 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
3828 for (const PrivateDataTy &Pair : Privates) {
3829 // Do not initialize private locals.
3830 if (Pair.second.isLocalPrivate()) {
3831 ++FI;
3832 continue;
3833 }
3834 const VarDecl *VD = Pair.second.PrivateCopy;
3835 const Expr *Init = VD->getAnyInitializer();
3836 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
3837 !CGF.isTrivialInitializer(Init)))) {
3838 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
3839 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
3840 const VarDecl *OriginalVD = Pair.second.Original;
3841 // Check if the variable is the target-based BasePointersArray,
3842 // PointersArray, SizesArray, or MappersArray.
3843 LValue SharedRefLValue;
3844 QualType Type = PrivateLValue.getType();
3845 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
3846 if (IsTargetTask && !SharedField) {
3847 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3854, __PRETTY_FUNCTION__))
3848 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3854, __PRETTY_FUNCTION__))
3849 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3854, __PRETTY_FUNCTION__))
3850 ->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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3854, __PRETTY_FUNCTION__))
3851 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3854, __PRETTY_FUNCTION__))
3852 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3854, __PRETTY_FUNCTION__))
3853 ->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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3854, __PRETTY_FUNCTION__))
3854 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3854, __PRETTY_FUNCTION__))
;
3855 SharedRefLValue =
3856 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
3857 } else if (ForDup) {
3858 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
3859 SharedRefLValue = CGF.MakeAddrLValue(
3860 Address(SharedRefLValue.getPointer(CGF),
3861 C.getDeclAlign(OriginalVD)),
3862 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
3863 SharedRefLValue.getTBAAInfo());
3864 } else if (CGF.LambdaCaptureFields.count(
3865 Pair.second.Original->getCanonicalDecl()) > 0 ||
3866 dyn_cast_or_null<BlockDecl>(CGF.CurCodeDecl)) {
3867 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef);
3868 } else {
3869 // Processing for implicitly captured variables.
3870 InlinedOpenMPRegionRAII Region(
3871 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown,
3872 /*HasCancel=*/false, /*NoInheritance=*/true);
3873 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef);
3874 }
3875 if (Type->isArrayType()) {
3876 // Initialize firstprivate array.
3877 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
3878 // Perform simple memcpy.
3879 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
3880 } else {
3881 // Initialize firstprivate array using element-by-element
3882 // initialization.
3883 CGF.EmitOMPAggregateAssign(
3884 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF),
3885 Type,
3886 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
3887 Address SrcElement) {
3888 // Clean up any temporaries needed by the initialization.
3889 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3890 InitScope.addPrivate(
3891 Elem, [SrcElement]() -> Address { return SrcElement; });
3892 (void)InitScope.Privatize();
3893 // Emit initialization for single element.
3894 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3895 CGF, &CapturesInfo);
3896 CGF.EmitAnyExprToMem(Init, DestElement,
3897 Init->getType().getQualifiers(),
3898 /*IsInitializer=*/false);
3899 });
3900 }
3901 } else {
3902 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3903 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address {
3904 return SharedRefLValue.getAddress(CGF);
3905 });
3906 (void)InitScope.Privatize();
3907 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
3908 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
3909 /*capturedByInit=*/false);
3910 }
3911 } else {
3912 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
3913 }
3914 }
3915 ++FI;
3916 }
3917}
3918
3919/// Check if duplication function is required for taskloops.
3920static bool checkInitIsRequired(CodeGenFunction &CGF,
3921 ArrayRef<PrivateDataTy> Privates) {
3922 bool InitRequired = false;
3923 for (const PrivateDataTy &Pair : Privates) {
3924 if (Pair.second.isLocalPrivate())
3925 continue;
3926 const VarDecl *VD = Pair.second.PrivateCopy;
3927 const Expr *Init = VD->getAnyInitializer();
3928 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
3929 !CGF.isTrivialInitializer(Init));
3930 if (InitRequired)
3931 break;
3932 }
3933 return InitRequired;
3934}
3935
3936
3937/// Emit task_dup function (for initialization of
3938/// private/firstprivate/lastprivate vars and last_iter flag)
3939/// \code
3940/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
3941/// lastpriv) {
3942/// // setup lastprivate flag
3943/// task_dst->last = lastpriv;
3944/// // could be constructor calls here...
3945/// }
3946/// \endcode
3947static llvm::Value *
3948emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
3949 const OMPExecutableDirective &D,
3950 QualType KmpTaskTWithPrivatesPtrQTy,
3951 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
3952 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
3953 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
3954 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
3955 ASTContext &C = CGM.getContext();
3956 FunctionArgList Args;
3957 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3958 KmpTaskTWithPrivatesPtrQTy,
3959 ImplicitParamDecl::Other);
3960 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3961 KmpTaskTWithPrivatesPtrQTy,
3962 ImplicitParamDecl::Other);
3963 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
3964 ImplicitParamDecl::Other);
3965 Args.push_back(&DstArg);
3966 Args.push_back(&SrcArg);
3967 Args.push_back(&LastprivArg);
3968 const auto &TaskDupFnInfo =
3969 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
3970 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
3971 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
3972 auto *TaskDup = llvm::Function::Create(
3973 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
3974 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
3975 TaskDup->setDoesNotRecurse();
3976 CodeGenFunction CGF(CGM);
3977 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
3978 Loc);
3979
3980 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3981 CGF.GetAddrOfLocalVar(&DstArg),
3982 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3983 // task_dst->liter = lastpriv;
3984 if (WithLastIter) {
3985 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3986 LValue Base = CGF.EmitLValueForField(
3987 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
3988 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
3989 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
3990 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
3991 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
3992 }
3993
3994 // Emit initial values for private copies (if any).
3995 assert(!Privates.empty())((!Privates.empty()) ? static_cast<void> (0) : __assert_fail
("!Privates.empty()", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 3995, __PRETTY_FUNCTION__))
;
3996 Address KmpTaskSharedsPtr = Address::invalid();
3997 if (!Data.FirstprivateVars.empty()) {
3998 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3999 CGF.GetAddrOfLocalVar(&SrcArg),
4000 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4001 LValue Base = CGF.EmitLValueForField(
4002 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4003 KmpTaskSharedsPtr = Address(
4004 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4005 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4006 KmpTaskTShareds)),
4007 Loc),
4008 CGM.getNaturalTypeAlignment(SharedsTy));
4009 }
4010 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4011 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
4012 CGF.FinishFunction();
4013 return TaskDup;
4014}
4015
4016/// Checks if destructor function is required to be generated.
4017/// \return true if cleanups are required, false otherwise.
4018static bool
4019checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4020 ArrayRef<PrivateDataTy> Privates) {
4021 for (const PrivateDataTy &P : Privates) {
4022 if (P.second.isLocalPrivate())
4023 continue;
4024 QualType Ty = P.second.Original->getType().getNonReferenceType();
4025 if (Ty.isDestructedType())
4026 return true;
4027 }
4028 return false;
4029}
4030
4031namespace {
4032/// Loop generator for OpenMP iterator expression.
4033class OMPIteratorGeneratorScope final
4034 : public CodeGenFunction::OMPPrivateScope {
4035 CodeGenFunction &CGF;
4036 const OMPIteratorExpr *E = nullptr;
4037 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
4038 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
4039 OMPIteratorGeneratorScope() = delete;
4040 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete;
4041
4042public:
4043 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E)
4044 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
4045 if (!E)
4046 return;
4047 SmallVector<llvm::Value *, 4> Uppers;
4048 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
4049 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
4050 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
4051 addPrivate(VD, [&CGF, VD]() {
4052 return CGF.CreateMemTemp(VD->getType(), VD->getName());
4053 });
4054 const OMPIteratorHelperData &HelperData = E->getHelper(I);
4055 addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() {
4056 return CGF.CreateMemTemp(HelperData.CounterVD->getType(),
4057 "counter.addr");
4058 });
4059 }
4060 Privatize();
4061
4062 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
4063 const OMPIteratorHelperData &HelperData = E->getHelper(I);
4064 LValue CLVal =
4065 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
4066 HelperData.CounterVD->getType());
4067 // Counter = 0;
4068 CGF.EmitStoreOfScalar(
4069 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0),
4070 CLVal);
4071 CodeGenFunction::JumpDest &ContDest =
4072 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont"));
4073 CodeGenFunction::JumpDest &ExitDest =
4074 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit"));
4075 // N = <number-of_iterations>;
4076 llvm::Value *N = Uppers[I];
4077 // cont:
4078 // if (Counter < N) goto body; else goto exit;
4079 CGF.EmitBlock(ContDest.getBlock());
4080 auto *CVal =
4081 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
4082 llvm::Value *Cmp =
4083 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
4084 ? CGF.Builder.CreateICmpSLT(CVal, N)
4085 : CGF.Builder.CreateICmpULT(CVal, N);
4086 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body");
4087 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
4088 // body:
4089 CGF.EmitBlock(BodyBB);
4090 // Iteri = Begini + Counter * Stepi;
4091 CGF.EmitIgnoredExpr(HelperData.Update);
4092 }
4093 }
4094 ~OMPIteratorGeneratorScope() {
4095 if (!E)
4096 return;
4097 for (unsigned I = E->numOfIterators(); I > 0; --I) {
4098 // Counter = Counter + 1;
4099 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1);
4100 CGF.EmitIgnoredExpr(HelperData.CounterUpdate);
4101 // goto cont;
4102 CGF.EmitBranchThroughCleanup(ContDests[I - 1]);
4103 // exit:
4104 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1);
4105 }
4106 }
4107};
4108} // namespace
4109
4110static std::pair<llvm::Value *, llvm::Value *>
4111getPointerAndSize(CodeGenFunction &CGF, const Expr *E) {
4112 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
4113 llvm::Value *Addr;
4114 if (OASE) {
4115 const Expr *Base = OASE->getBase();
4116 Addr = CGF.EmitScalarExpr(Base);
4117 } else {
4118 Addr = CGF.EmitLValue(E).getPointer(CGF);
4119 }
4120 llvm::Value *SizeVal;
4121 QualType Ty = E->getType();
4122 if (OASE) {
4123 SizeVal = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType());
4124 for (const Expr *SE : OASE->getDimensions()) {
4125 llvm::Value *Sz = CGF.EmitScalarExpr(SE);
4126 Sz = CGF.EmitScalarConversion(
4127 Sz, SE->getType(), CGF.getContext().getSizeType(), SE->getExprLoc());
4128 SizeVal = CGF.Builder.CreateNUWMul(SizeVal, Sz);
4129 }
4130 } else if (const auto *ASE =
4131 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
4132 LValue UpAddrLVal =
4133 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
4134 llvm::Value *UpAddr =
4135 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(CGF), /*Idx0=*/1);
4136 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy);
4137 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy);
4138 SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
4139 } else {
4140 SizeVal = CGF.getTypeSize(Ty);
4141 }
4142 return std::make_pair(Addr, SizeVal);
4143}
4144
4145/// Builds kmp_depend_info, if it is not built yet, and builds flags type.
4146static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) {
4147 QualType FlagsTy = C.getIntTypeForBitwidth(32, /*Signed=*/false);
4148 if (KmpTaskAffinityInfoTy.isNull()) {
4149 RecordDecl *KmpAffinityInfoRD =
4150 C.buildImplicitRecord("kmp_task_affinity_info_t");
4151 KmpAffinityInfoRD->startDefinition();
4152 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getIntPtrType());
4153 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType());
4154 addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy);
4155 KmpAffinityInfoRD->completeDefinition();
4156 KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD);
4157 }
4158}
4159
4160CGOpenMPRuntime::TaskResultTy
4161CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4162 const OMPExecutableDirective &D,
4163 llvm::Function *TaskFunction, QualType SharedsTy,
4164 Address Shareds, const OMPTaskDataTy &Data) {
4165 ASTContext &C = CGM.getContext();
4166 llvm::SmallVector<PrivateDataTy, 4> Privates;
4167 // Aggregate privates and sort them by the alignment.
4168 const auto *I = Data.PrivateCopies.begin();
4169 for (const Expr *E : Data.PrivateVars) {
4170 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4171 Privates.emplace_back(
4172 C.getDeclAlign(VD),
4173 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
4174 /*PrivateElemInit=*/nullptr));
4175 ++I;
4176 }
4177 I = Data.FirstprivateCopies.begin();
4178 const auto *IElemInitRef = Data.FirstprivateInits.begin();
4179 for (const Expr *E : Data.FirstprivateVars) {
4180 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4181 Privates.emplace_back(
4182 C.getDeclAlign(VD),
4183 PrivateHelpersTy(
4184 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
4185 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
4186 ++I;
4187 ++IElemInitRef;
4188 }
4189 I = Data.LastprivateCopies.begin();
4190 for (const Expr *E : Data.LastprivateVars) {
4191 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
4192 Privates.emplace_back(
4193 C.getDeclAlign(VD),
4194 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
4195 /*PrivateElemInit=*/nullptr));
4196 ++I;
4197 }
4198 for (const VarDecl *VD : Data.PrivateLocals) {
4199 if (isAllocatableDecl(VD))
4200 Privates.emplace_back(CGM.getPointerAlign(), PrivateHelpersTy(VD));
4201 else
4202 Privates.emplace_back(C.getDeclAlign(VD), PrivateHelpersTy(VD));
4203 }
4204 llvm::stable_sort(Privates,
4205 [](const PrivateDataTy &L, const PrivateDataTy &R) {
4206 return L.first > R.first;
4207 });
4208 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
4209 // Build type kmp_routine_entry_t (if not built yet).
4210 emitKmpRoutineEntryT(KmpInt32Ty);
4211 // Build type kmp_task_t (if not built yet).
4212 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
4213 if (SavedKmpTaskloopTQTy.isNull()) {
4214 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
4215 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
4216 }
4217 KmpTaskTQTy = SavedKmpTaskloopTQTy;
4218 } else {
4219 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4222, __PRETTY_FUNCTION__))
4220 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4222, __PRETTY_FUNCTION__))
4221 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4222, __PRETTY_FUNCTION__))
4222 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4222, __PRETTY_FUNCTION__))
;
4223 if (SavedKmpTaskTQTy.isNull()) {
4224 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
4225 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
4226 }
4227 KmpTaskTQTy = SavedKmpTaskTQTy;
4228 }
4229 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
4230 // Build particular struct kmp_task_t for the given task.
4231 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
4232 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
4233 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
4234 QualType KmpTaskTWithPrivatesPtrQTy =
4235 C.getPointerType(KmpTaskTWithPrivatesQTy);
4236 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
4237 llvm::Type *KmpTaskTWithPrivatesPtrTy =
4238 KmpTaskTWithPrivatesTy->getPointerTo();
4239 llvm::Value *KmpTaskTWithPrivatesTySize =
4240 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
4241 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
4242
4243 // Emit initial values for private copies (if any).
4244 llvm::Value *TaskPrivatesMap = nullptr;
4245 llvm::Type *TaskPrivatesMapTy =
4246 std::next(TaskFunction->arg_begin(), 3)->getType();
4247 if (!Privates.empty()) {
4248 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4249 TaskPrivatesMap =
4250 emitTaskPrivateMappingFunction(CGM, Loc, Data, FI->getType(), Privates);
4251 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4252 TaskPrivatesMap, TaskPrivatesMapTy);
4253 } else {
4254 TaskPrivatesMap = llvm::ConstantPointerNull::get(
4255 cast<llvm::PointerType>(TaskPrivatesMapTy));
4256 }
4257 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
4258 // kmp_task_t *tt);
4259 llvm::Function *TaskEntry = emitProxyTaskFunction(
4260 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4261 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
4262 TaskPrivatesMap);
4263
4264 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
4265 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
4266 // kmp_routine_entry_t *task_entry);
4267 // Task flags. Format is taken from
4268 // https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h,
4269 // description of kmp_tasking_flags struct.
4270 enum {
4271 TiedFlag = 0x1,
4272 FinalFlag = 0x2,
4273 DestructorsFlag = 0x8,
4274 PriorityFlag = 0x20,
4275 DetachableFlag = 0x40,
4276 };
4277 unsigned Flags = Data.Tied ? TiedFlag : 0;
4278 bool NeedsCleanup = false;
4279 if (!Privates.empty()) {
4280 NeedsCleanup =
4281 checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD, Privates);
4282 if (NeedsCleanup)
4283 Flags = Flags | DestructorsFlag;
4284 }
4285 if (Data.Priority.getInt())
4286 Flags = Flags | PriorityFlag;
4287 if (D.hasClausesOfKind<OMPDetachClause>())
4288 Flags = Flags | DetachableFlag;
4289 llvm::Value *TaskFlags =
4290 Data.Final.getPointer()
4291 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
4292 CGF.Builder.getInt32(FinalFlag),
4293 CGF.Builder.getInt32(/*C=*/0))
4294 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
4295 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
4296 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
4297 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
4298 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
4299 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4300 TaskEntry, KmpRoutineEntryPtrTy)};
4301 llvm::Value *NewTask;
4302 if (D.hasClausesOfKind<OMPNowaitClause>()) {
4303 // Check if we have any device clause associated with the directive.
4304 const Expr *Device = nullptr;
4305 if (auto *C = D.getSingleClause<OMPDeviceClause>())
4306 Device = C->getDevice();
4307 // Emit device ID if any otherwise use default value.
4308 llvm::Value *DeviceID;
4309 if (Device)
4310 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
4311 CGF.Int64Ty, /*isSigned=*/true);
4312 else
4313 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
4314 AllocArgs.push_back(DeviceID);
4315 NewTask = CGF.EmitRuntimeCall(
4316 OMPBuilder.getOrCreateRuntimeFunction(
4317 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
4318 AllocArgs);
4319 } else {
4320 NewTask =
4321 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
4322 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
4323 AllocArgs);
4324 }
4325 // Emit detach clause initialization.
4326 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid,
4327 // task_descriptor);
4328 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) {
4329 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts();
4330 LValue EvtLVal = CGF.EmitLValue(Evt);
4331
4332 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref,
4333 // int gtid, kmp_task_t *task);
4334 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc());
4335 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc());
4336 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false);
4337 llvm::Value *EvtVal = CGF.EmitRuntimeCall(
4338 OMPBuilder.getOrCreateRuntimeFunction(
4339 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
4340 {Loc, Tid, NewTask});
4341 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(),
4342 Evt->getExprLoc());
4343 CGF.EmitStoreOfScalar(EvtVal, EvtLVal);
4344 }
4345 // Process affinity clauses.
4346 if (D.hasClausesOfKind<OMPAffinityClause>()) {
4347 // Process list of affinity data.
4348 ASTContext &C = CGM.getContext();
4349 Address AffinitiesArray = Address::invalid();
4350 // Calculate number of elements to form the array of affinity data.
4351 llvm::Value *NumOfElements = nullptr;
4352 unsigned NumAffinities = 0;
4353 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
4354 if (const Expr *Modifier = C->getModifier()) {
4355 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts());
4356 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4357 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper);
4358 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false);
4359 NumOfElements =
4360 NumOfElements ? CGF.Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
4361 }
4362 } else {
4363 NumAffinities += C->varlist_size();
4364 }
4365 }
4366 getKmpAffinityType(CGM.getContext(), KmpTaskAffinityInfoTy);
4367 // Fields ids in kmp_task_affinity_info record.
4368 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
4369
4370 QualType KmpTaskAffinityInfoArrayTy;
4371 if (NumOfElements) {
4372 NumOfElements = CGF.Builder.CreateNUWAdd(
4373 llvm::ConstantInt::get(CGF.SizeTy, NumAffinities), NumOfElements);
4374 OpaqueValueExpr OVE(
4375 Loc,
4376 C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0),
4377 VK_RValue);
4378 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE,
4379 RValue::get(NumOfElements));
4380 KmpTaskAffinityInfoArrayTy =
4381 C.getVariableArrayType(KmpTaskAffinityInfoTy, &OVE, ArrayType::Normal,
4382 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc));
4383 // Properly emit variable-sized array.
4384 auto *PD = ImplicitParamDecl::Create(C, KmpTaskAffinityInfoArrayTy,
4385 ImplicitParamDecl::Other);
4386 CGF.EmitVarDecl(*PD);
4387 AffinitiesArray = CGF.GetAddrOfLocalVar(PD);
4388 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty,
4389 /*isSigned=*/false);
4390 } else {
4391 KmpTaskAffinityInfoArrayTy = C.getConstantArrayType(
4392 KmpTaskAffinityInfoTy,
4393 llvm::APInt(C.getTypeSize(C.getSizeType()), NumAffinities), nullptr,
4394 ArrayType::Normal, /*IndexTypeQuals=*/0);
4395 AffinitiesArray =
4396 CGF.CreateMemTemp(KmpTaskAffinityInfoArrayTy, ".affs.arr.addr");
4397 AffinitiesArray = CGF.Builder.CreateConstArrayGEP(AffinitiesArray, 0);
4398 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumAffinities,
4399 /*isSigned=*/false);
4400 }
4401
4402 const auto *KmpAffinityInfoRD = KmpTaskAffinityInfoTy->getAsRecordDecl();
4403 // Fill array by elements without iterators.
4404 unsigned Pos = 0;
4405 bool HasIterator = false;
4406 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
4407 if (C->getModifier()) {
4408 HasIterator = true;
4409 continue;
4410 }
4411 for (const Expr *E : C->varlists()) {
4412 llvm::Value *Addr;
4413 llvm::Value *Size;
4414 std::tie(Addr, Size) = getPointerAndSize(CGF, E);
4415 LValue Base =
4416 CGF.MakeAddrLValue(CGF.Builder.CreateConstGEP(AffinitiesArray, Pos),
4417 KmpTaskAffinityInfoTy);
4418 // affs[i].base_addr = &<Affinities[i].second>;
4419 LValue BaseAddrLVal = CGF.EmitLValueForField(
4420 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4421 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy),
4422 BaseAddrLVal);
4423 // affs[i].len = sizeof(<Affinities[i].second>);
4424 LValue LenLVal = CGF.EmitLValueForField(
4425 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4426 CGF.EmitStoreOfScalar(Size, LenLVal);
4427 ++Pos;
4428 }
4429 }
4430 LValue PosLVal;
4431 if (HasIterator) {
4432 PosLVal = CGF.MakeAddrLValue(
4433 CGF.CreateMemTemp(C.getSizeType(), "affs.counter.addr"),
4434 C.getSizeType());
4435 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal);
4436 }
4437 // Process elements with iterators.
4438 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
4439 const Expr *Modifier = C->getModifier();
4440 if (!Modifier)
4441 continue;
4442 OMPIteratorGeneratorScope IteratorScope(
4443 CGF, cast_or_null<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts()));
4444 for (const Expr *E : C->varlists()) {
4445 llvm::Value *Addr;
4446 llvm::Value *Size;
4447 std::tie(Addr, Size) = getPointerAndSize(CGF, E);
4448 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4449 LValue Base = CGF.MakeAddrLValue(
4450 Address(CGF.Builder.CreateGEP(AffinitiesArray.getPointer(), Idx),
4451 AffinitiesArray.getAlignment()),
4452 KmpTaskAffinityInfoTy);
4453 // affs[i].base_addr = &<Affinities[i].second>;
4454 LValue BaseAddrLVal = CGF.EmitLValueForField(
4455 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
4456 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy),
4457 BaseAddrLVal);
4458 // affs[i].len = sizeof(<Affinities[i].second>);
4459 LValue LenLVal = CGF.EmitLValueForField(
4460 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
4461 CGF.EmitStoreOfScalar(Size, LenLVal);
4462 Idx = CGF.Builder.CreateNUWAdd(
4463 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
4464 CGF.EmitStoreOfScalar(Idx, PosLVal);
4465 }
4466 }
4467 // Call to kmp_int32 __kmpc_omp_reg_task_with_affinity(ident_t *loc_ref,
4468 // kmp_int32 gtid, kmp_task_t *new_task, kmp_int32
4469 // naffins, kmp_task_affinity_info_t *affin_list);
4470 llvm::Value *LocRef = emitUpdateLocation(CGF, Loc);
4471 llvm::Value *GTid = getThreadID(CGF, Loc);
4472 llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4473 AffinitiesArray.getPointer(), CGM.VoidPtrTy);
4474 // FIXME: Emit the function and ignore its result for now unless the
4475 // runtime function is properly implemented.
4476 (void)CGF.EmitRuntimeCall(
4477 OMPBuilder.getOrCreateRuntimeFunction(
4478 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
4479 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
4480 }
4481 llvm::Value *NewTaskNewTaskTTy =
4482 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4483 NewTask, KmpTaskTWithPrivatesPtrTy);
4484 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
4485 KmpTaskTWithPrivatesQTy);
4486 LValue TDBase =
4487 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
4488 // Fill the data in the resulting kmp_task_t record.
4489 // Copy shareds if there are any.
4490 Address KmpTaskSharedsPtr = Address::invalid();
4491 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
4492 KmpTaskSharedsPtr =
4493 Address(CGF.EmitLoadOfScalar(
4494 CGF.EmitLValueForField(
4495 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
4496 KmpTaskTShareds)),
4497 Loc),
4498 CGM.getNaturalTypeAlignment(SharedsTy));
4499 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
4500 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
4501 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
4502 }
4503 // Emit initial values for private copies (if any).
4504 TaskResultTy Result;
4505 if (!Privates.empty()) {
4506 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
4507 SharedsTy, SharedsPtrTy, Data, Privates,
4508 /*ForDup=*/false);
4509 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
4510 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
4511 Result.TaskDupFn = emitTaskDupFunction(
4512 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
4513 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
4514 /*WithLastIter=*/!Data.LastprivateVars.empty());
4515 }
4516 }
4517 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
4518 enum { Priority = 0, Destructors = 1 };
4519 // Provide pointer to function with destructors for privates.
4520 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
4521 const RecordDecl *KmpCmplrdataUD =
4522 (*FI)->getType()->getAsUnionType()->getDecl();
4523 if (NeedsCleanup) {
4524 llvm::Value *DestructorFn = emitDestructorsFunction(
4525 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
4526 KmpTaskTWithPrivatesQTy);
4527 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
4528 LValue DestructorsLV = CGF.EmitLValueForField(
4529 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4530 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4531 DestructorFn, KmpRoutineEntryPtrTy),
4532 DestructorsLV);
4533 }
4534 // Set priority.
4535 if (Data.Priority.getInt()) {
4536 LValue Data2LV = CGF.EmitLValueForField(
4537 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4538 LValue PriorityLV = CGF.EmitLValueForField(
4539 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4540 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
4541 }
4542 Result.NewTask = NewTask;
4543 Result.TaskEntry = TaskEntry;
4544 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4545 Result.TDBase = TDBase;
4546 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4547 return Result;
4548}
4549
4550namespace {
4551/// Dependence kind for RTL.
4552enum RTLDependenceKindTy {
4553 DepIn = 0x01,
4554 DepInOut = 0x3,
4555 DepMutexInOutSet = 0x4
4556};
4557/// Fields ids in kmp_depend_info record.
4558enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
4559} // namespace
4560
4561/// Translates internal dependency kind into the runtime kind.
4562static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) {
4563 RTLDependenceKindTy DepKind;
4564 switch (K) {
4565 case OMPC_DEPEND_in:
4566 DepKind = DepIn;
4567 break;
4568 // Out and InOut dependencies must use the same code.
4569 case OMPC_DEPEND_out:
4570 case OMPC_DEPEND_inout:
4571 DepKind = DepInOut;
4572 break;
4573 case OMPC_DEPEND_mutexinoutset:
4574 DepKind = DepMutexInOutSet;
4575 break;
4576 case OMPC_DEPEND_source:
4577 case OMPC_DEPEND_sink:
4578 case OMPC_DEPEND_depobj:
4579 case OMPC_DEPEND_unknown:
4580 llvm_unreachable("Unknown task dependence type")::llvm::llvm_unreachable_internal("Unknown task dependence type"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4580)
;
4581 }
4582 return DepKind;
4583}
4584
4585/// Builds kmp_depend_info, if it is not built yet, and builds flags type.
4586static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy,
4587 QualType &FlagsTy) {
4588 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
4589 if (KmpDependInfoTy.isNull()) {
4590 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
4591 KmpDependInfoRD->startDefinition();
4592 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
4593 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
4594 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
4595 KmpDependInfoRD->completeDefinition();
4596 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
4597 }
4598}
4599
4600std::pair<llvm::Value *, LValue>
4601CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal,
4602 SourceLocation Loc) {
4603 ASTContext &C = CGM.getContext();
4604 QualType FlagsTy;
4605 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4606 RecordDecl *KmpDependInfoRD =
4607 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4608 LValue Base = CGF.EmitLoadOfPointerLValue(
4609 DepobjLVal.getAddress(CGF),
4610 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
4611 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
4612 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4613 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy));
4614 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
4615 Base.getTBAAInfo());
4616 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
4617 Addr.getPointer(),
4618 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
4619 LValue NumDepsBase = CGF.MakeAddrLValue(
4620 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
4621 Base.getBaseInfo(), Base.getTBAAInfo());
4622 // NumDeps = deps[i].base_addr;
4623 LValue BaseAddrLVal = CGF.EmitLValueForField(
4624 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
4625 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc);
4626 return std::make_pair(NumDeps, Base);
4627}
4628
4629static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy,
4630 llvm::PointerUnion<unsigned *, LValue *> Pos,
4631 const OMPTaskDataTy::DependData &Data,
4632 Address DependenciesArray) {
4633 CodeGenModule &CGM = CGF.CGM;
4634 ASTContext &C = CGM.getContext();
4635 QualType FlagsTy;
4636 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4637 RecordDecl *KmpDependInfoRD =
4638 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4639 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
4640
4641 OMPIteratorGeneratorScope IteratorScope(
4642 CGF, cast_or_null<OMPIteratorExpr>(
4643 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts()
4644 : nullptr));
4645 for (const Expr *E : Data.DepExprs) {
4646 llvm::Value *Addr;
4647 llvm::Value *Size;
4648 std::tie(Addr, Size) = getPointerAndSize(CGF, E);
4649 LValue Base;
4650 if (unsigned *P = Pos.dyn_cast<unsigned *>()) {
4651 Base = CGF.MakeAddrLValue(
4652 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy);
4653 } else {
4654 LValue &PosLVal = *Pos.get<LValue *>();
4655 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4656 Base = CGF.MakeAddrLValue(
4657 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Idx),
4658 DependenciesArray.getAlignment()),
4659 KmpDependInfoTy);
4660 }
4661 // deps[i].base_addr = &<Dependencies[i].second>;
4662 LValue BaseAddrLVal = CGF.EmitLValueForField(
4663 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
4664 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy),
4665 BaseAddrLVal);
4666 // deps[i].len = sizeof(<Dependencies[i].second>);
4667 LValue LenLVal = CGF.EmitLValueForField(
4668 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
4669 CGF.EmitStoreOfScalar(Size, LenLVal);
4670 // deps[i].flags = <Dependencies[i].first>;
4671 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind);
4672 LValue FlagsLVal = CGF.EmitLValueForField(
4673 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
4674 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
4675 FlagsLVal);
4676 if (unsigned *P = Pos.dyn_cast<unsigned *>()) {
4677 ++(*P);
4678 } else {
4679 LValue &PosLVal = *Pos.get<LValue *>();
4680 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4681 Idx = CGF.Builder.CreateNUWAdd(Idx,
4682 llvm::ConstantInt::get(Idx->getType(), 1));
4683 CGF.EmitStoreOfScalar(Idx, PosLVal);
4684 }
4685 }
4686}
4687
4688static SmallVector<llvm::Value *, 4>
4689emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy,
4690 const OMPTaskDataTy::DependData &Data) {
4691 assert(Data.DepKind == OMPC_DEPEND_depobj &&((Data.DepKind == OMPC_DEPEND_depobj && "Expected depobj dependecy kind."
) ? static_cast<void> (0) : __assert_fail ("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependecy kind.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4692, __PRETTY_FUNCTION__))
4692 "Expected depobj dependecy kind.")((Data.DepKind == OMPC_DEPEND_depobj && "Expected depobj dependecy kind."
) ? static_cast<void> (0) : __assert_fail ("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependecy kind.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4692, __PRETTY_FUNCTION__))
;
4693 SmallVector<llvm::Value *, 4> Sizes;
4694 SmallVector<LValue, 4> SizeLVals;
4695 ASTContext &C = CGF.getContext();
4696 QualType FlagsTy;
4697 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4698 RecordDecl *KmpDependInfoRD =
4699 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4700 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
4701 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy);
4702 {
4703 OMPIteratorGeneratorScope IteratorScope(
4704 CGF, cast_or_null<OMPIteratorExpr>(
4705 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts()
4706 : nullptr));
4707 for (const Expr *E : Data.DepExprs) {
4708 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts());
4709 LValue Base = CGF.EmitLoadOfPointerLValue(
4710 DepobjLVal.getAddress(CGF),
4711 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
4712 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4713 Base.getAddress(CGF), KmpDependInfoPtrT);
4714 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
4715 Base.getTBAAInfo());
4716 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
4717 Addr.getPointer(),
4718 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
4719 LValue NumDepsBase = CGF.MakeAddrLValue(
4720 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
4721 Base.getBaseInfo(), Base.getTBAAInfo());
4722 // NumDeps = deps[i].base_addr;
4723 LValue BaseAddrLVal = CGF.EmitLValueForField(
4724 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
4725 llvm::Value *NumDeps =
4726 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc());
4727 LValue NumLVal = CGF.MakeAddrLValue(
4728 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"),
4729 C.getUIntPtrType());
4730 CGF.InitTempAlloca(NumLVal.getAddress(CGF),
4731 llvm::ConstantInt::get(CGF.IntPtrTy, 0));
4732 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc());
4733 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps);
4734 CGF.EmitStoreOfScalar(Add, NumLVal);
4735 SizeLVals.push_back(NumLVal);
4736 }
4737 }
4738 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4739 llvm::Value *Size =
4740 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc());
4741 Sizes.push_back(Size);
4742 }
4743 return Sizes;
4744}
4745
4746static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy,
4747 LValue PosLVal,
4748 const OMPTaskDataTy::DependData &Data,
4749 Address DependenciesArray) {
4750 assert(Data.DepKind == OMPC_DEPEND_depobj &&((Data.DepKind == OMPC_DEPEND_depobj && "Expected depobj dependecy kind."
) ? static_cast<void> (0) : __assert_fail ("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependecy kind.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4751, __PRETTY_FUNCTION__))
4751 "Expected depobj dependecy kind.")((Data.DepKind == OMPC_DEPEND_depobj && "Expected depobj dependecy kind."
) ? static_cast<void> (0) : __assert_fail ("Data.DepKind == OMPC_DEPEND_depobj && \"Expected depobj dependecy kind.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 4751, __PRETTY_FUNCTION__))
;
4752 ASTContext &C = CGF.getContext();
4753 QualType FlagsTy;
4754 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4755 RecordDecl *KmpDependInfoRD =
4756 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4757 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
4758 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy);
4759 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy);
4760 {
4761 OMPIteratorGeneratorScope IteratorScope(
4762 CGF, cast_or_null<OMPIteratorExpr>(
4763 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts()
4764 : nullptr));
4765 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) {
4766 const Expr *E = Data.DepExprs[I];
4767 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts());
4768 LValue Base = CGF.EmitLoadOfPointerLValue(
4769 DepobjLVal.getAddress(CGF),
4770 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
4771 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4772 Base.getAddress(CGF), KmpDependInfoPtrT);
4773 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
4774 Base.getTBAAInfo());
4775
4776 // Get number of elements in a single depobj.
4777 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
4778 Addr.getPointer(),
4779 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
4780 LValue NumDepsBase = CGF.MakeAddrLValue(
4781 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
4782 Base.getBaseInfo(), Base.getTBAAInfo());
4783 // NumDeps = deps[i].base_addr;
4784 LValue BaseAddrLVal = CGF.EmitLValueForField(
4785 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
4786 llvm::Value *NumDeps =
4787 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc());
4788
4789 // memcopy dependency data.
4790 llvm::Value *Size = CGF.Builder.CreateNUWMul(
4791 ElSize,
4792 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false));
4793 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
4794 Address DepAddr =
4795 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Pos),
4796 DependenciesArray.getAlignment());
4797 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size);
4798
4799 // Increase pos.
4800 // pos += size;
4801 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps);
4802 CGF.EmitStoreOfScalar(Add, PosLVal);
4803 }
4804 }
4805}
4806
4807std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause(
4808 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies,
4809 SourceLocation Loc) {
4810 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) {
4811 return D.DepExprs.empty();
4812 }))
4813 return std::make_pair(nullptr, Address::invalid());
4814 // Process list of dependencies.
4815 ASTContext &C = CGM.getContext();
4816 Address DependenciesArray = Address::invalid();
4817 llvm::Value *NumOfElements = nullptr;
4818 unsigned NumDependencies = std::accumulate(
4819 Dependencies.begin(), Dependencies.end(), 0,
4820 [](unsigned V, const OMPTaskDataTy::DependData &D) {
4821 return D.DepKind == OMPC_DEPEND_depobj
4822 ? V
4823 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4824 });
4825 QualType FlagsTy;
4826 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4827 bool HasDepobjDeps = false;
4828 bool HasRegularWithIterators = false;
4829 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0);
4830 llvm::Value *NumOfRegularWithIterators =
4831 llvm::ConstantInt::get(CGF.IntPtrTy, 1);
4832 // Calculate number of depobj dependecies and regular deps with the iterators.
4833 for (const OMPTaskDataTy::DependData &D : Dependencies) {
4834 if (D.DepKind == OMPC_DEPEND_depobj) {
4835 SmallVector<llvm::Value *, 4> Sizes =
4836 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D);
4837 for (llvm::Value *Size : Sizes) {
4838 NumOfDepobjElements =
4839 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4840 }
4841 HasDepobjDeps = true;
4842 continue;
4843 }
4844 // Include number of iterations, if any.
4845 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) {
4846 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4847 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper);
4848 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false);
4849 NumOfRegularWithIterators =
4850 CGF.Builder.CreateNUWMul(NumOfRegularWithIterators, Sz);
4851 }
4852 HasRegularWithIterators = true;
4853 continue;
4854 }
4855 }
4856
4857 QualType KmpDependInfoArrayTy;
4858 if (HasDepobjDeps || HasRegularWithIterators) {
4859 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies,
4860 /*isSigned=*/false);
4861 if (HasDepobjDeps) {
4862 NumOfElements =
4863 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4864 }
4865 if (HasRegularWithIterators) {
4866 NumOfElements =
4867 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4868 }
4869 OpaqueValueExpr OVE(Loc,
4870 C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0),
4871 VK_RValue);
4872 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE,
4873 RValue::get(NumOfElements));
4874 KmpDependInfoArrayTy =
4875 C.getVariableArrayType(KmpDependInfoTy, &OVE, ArrayType::Normal,
4876 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc));
4877 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy);
4878 // Properly emit variable-sized array.
4879 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy,
4880 ImplicitParamDecl::Other);
4881 CGF.EmitVarDecl(*PD);
4882 DependenciesArray = CGF.GetAddrOfLocalVar(PD);
4883 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty,
4884 /*isSigned=*/false);
4885 } else {
4886 KmpDependInfoArrayTy = C.getConstantArrayType(
4887 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr,
4888 ArrayType::Normal, /*IndexTypeQuals=*/0);
4889 DependenciesArray =
4890 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
4891 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0);
4892 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies,
4893 /*isSigned=*/false);
4894 }
4895 unsigned Pos = 0;
4896 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4897 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj ||
4898 Dependencies[I].IteratorExpr)
4899 continue;
4900 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I],
4901 DependenciesArray);
4902 }
4903 // Copy regular dependecies with iterators.
4904 LValue PosLVal = CGF.MakeAddrLValue(
4905 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType());
4906 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal);
4907 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4908 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj ||
4909 !Dependencies[I].IteratorExpr)
4910 continue;
4911 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I],
4912 DependenciesArray);
4913 }
4914 // Copy final depobj arrays without iterators.
4915 if (HasDepobjDeps) {
4916 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) {
4917 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj)
4918 continue;
4919 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I],
4920 DependenciesArray);
4921 }
4922 }
4923 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4924 DependenciesArray, CGF.VoidPtrTy);
4925 return std::make_pair(NumOfElements, DependenciesArray);
4926}
4927
4928Address CGOpenMPRuntime::emitDepobjDependClause(
4929 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies,
4930 SourceLocation Loc) {
4931 if (Dependencies.DepExprs.empty())
4932 return Address::invalid();
4933 // Process list of dependencies.
4934 ASTContext &C = CGM.getContext();
4935 Address DependenciesArray = Address::invalid();
4936 unsigned NumDependencies = Dependencies.DepExprs.size();
4937 QualType FlagsTy;
4938 getDependTypes(C, KmpDependInfoTy, FlagsTy);
4939 RecordDecl *KmpDependInfoRD =
4940 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
4941
4942 llvm::Value *Size;
4943 // Define type kmp_depend_info[<Dependencies.size()>];
4944 // For depobj reserve one extra element to store the number of elements.
4945 // It is required to handle depobj(x) update(in) construct.
4946 // kmp_depend_info[<Dependencies.size()>] deps;
4947 llvm::Value *NumDepsVal;
4948 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy);
4949 if (const auto *IE =
4950 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) {
4951 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1);
4952 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
4953 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper);
4954 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false);
4955 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz);
4956 }
4957 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1),
4958 NumDepsVal);
4959 CharUnits SizeInBytes =
4960 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align);
4961 llvm::Value *RecSize = CGM.getSize(SizeInBytes);
4962 Size = CGF.Builder.CreateNUWMul(Size, RecSize);
4963 NumDepsVal =
4964 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false);
4965 } else {
4966 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
4967 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1),
4968 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
4969 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy);
4970 Size = CGM.getSize(Sz.alignTo(Align));
4971 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies);
4972 }
4973 // Need to allocate on the dynamic memory.
4974 llvm::Value *ThreadID = getThreadID(CGF, Loc);
4975 // Use default allocator.
4976 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
4977 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4978
4979 llvm::Value *Addr =
4980 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
4981 CGM.getModule(), OMPRTL___kmpc_alloc),
4982 Args, ".dep.arr.addr");
4983 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4984 Addr, CGF.ConvertTypeForMem(KmpDependInfoTy)->getPointerTo());
4985 DependenciesArray = Address(Addr, Align);
4986 // Write number of elements in the first element of array for depobj.
4987 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy);
4988 // deps[i].base_addr = NumDependencies;
4989 LValue BaseAddrLVal = CGF.EmitLValueForField(
4990 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
4991 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal);
4992 llvm::PointerUnion<unsigned *, LValue *> Pos;
4993 unsigned Idx = 1;
4994 LValue PosLVal;
4995 if (Dependencies.IteratorExpr) {
4996 PosLVal = CGF.MakeAddrLValue(
4997 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"),
4998 C.getSizeType());
4999 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal,
5000 /*IsInit=*/true);
5001 Pos = &PosLVal;
5002 } else {
5003 Pos = &Idx;
5004 }
5005 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray);
5006 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5007 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy);
5008 return DependenciesArray;
5009}
5010
5011void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal,
5012 SourceLocation Loc) {
5013 ASTContext &C = CGM.getContext();
5014 QualType FlagsTy;
5015 getDependTypes(C, KmpDependInfoTy, FlagsTy);
5016 LValue Base = CGF.EmitLoadOfPointerLValue(
5017 DepobjLVal.getAddress(CGF),
5018 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5019 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
5020 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5021 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy));
5022 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
5023 Addr.getPointer(),
5024 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
5025 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr,
5026 CGF.VoidPtrTy);
5027 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5028 // Use default allocator.
5029 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5030 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
5031
5032 // _kmpc_free(gtid, addr, nullptr);
5033 (void)CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
5034 CGM.getModule(), OMPRTL___kmpc_free),
5035 Args);
5036}
5037
5038void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal,
5039 OpenMPDependClauseKind NewDepKind,
5040 SourceLocation Loc) {
5041 ASTContext &C = CGM.getContext();
5042 QualType FlagsTy;
5043 getDependTypes(C, KmpDependInfoTy, FlagsTy);
5044 RecordDecl *KmpDependInfoRD =
5045 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
5046 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5047 llvm::Value *NumDeps;
5048 LValue Base;
5049 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc);
5050
5051 Address Begin = Base.getAddress(CGF);
5052 // Cast from pointer to array type to pointer to single element.
5053 llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps);
5054 // The basic structure here is a while-do loop.
5055 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body");
5056 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done");
5057 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
5058 CGF.EmitBlock(BodyBB);
5059 llvm::PHINode *ElementPHI =
5060 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast");
5061 ElementPHI->addIncoming(Begin.getPointer(), EntryBB);
5062 Begin = Address(ElementPHI, Begin.getAlignment());
5063 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(),
5064 Base.getTBAAInfo());
5065 // deps[i].flags = NewDepKind;
5066 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind);
5067 LValue FlagsLVal = CGF.EmitLValueForField(
5068 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5069 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5070 FlagsLVal);
5071
5072 // Shift the address forward by one element.
5073 Address ElementNext =
5074 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext");
5075 ElementPHI->addIncoming(ElementNext.getPointer(),
5076 CGF.Builder.GetInsertBlock());
5077 llvm::Value *IsEmpty =
5078 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty");
5079 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5080 // Done.
5081 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5082}
5083
5084void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5085 const OMPExecutableDirective &D,
5086 llvm::Function *TaskFunction,
5087 QualType SharedsTy, Address Shareds,
5088 const Expr *IfCond,
5089 const OMPTaskDataTy &Data) {
5090 if (!CGF.HaveInsertPoint())
5091 return;
5092
5093 TaskResultTy Result =
5094 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5095 llvm::Value *NewTask = Result.NewTask;
5096 llvm::Function *TaskEntry = Result.TaskEntry;
5097 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5098 LValue TDBase = Result.TDBase;
5099 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5100 // Process list of dependences.
5101 Address DependenciesArray = Address::invalid();
5102 llvm::Value *NumOfElements;
5103 std::tie(NumOfElements, DependenciesArray) =
5104 emitDependClause(CGF, Data.Dependences, Loc);
5105
5106 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
5107 // libcall.
5108 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5109 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5110 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5111 // list is not empty
5112 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5113 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5114 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5115 llvm::Value *DepTaskArgs[7];
5116 if (!Data.Dependences.empty()) {
5117 DepTaskArgs[0] = UpLoc;
5118 DepTaskArgs[1] = ThreadID;
5119 DepTaskArgs[2] = NewTask;
5120 DepTaskArgs[3] = NumOfElements;
5121 DepTaskArgs[4] = DependenciesArray.getPointer();
5122 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5123 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5124 }
5125 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
5126 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
5127 if (!Data.Tied) {
5128 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
5129 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
5130 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5131 }
5132 if (!Data.Dependences.empty()) {
5133 CGF.EmitRuntimeCall(
5134 OMPBuilder.getOrCreateRuntimeFunction(
5135 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
5136 DepTaskArgs);
5137 } else {
5138 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
5139 CGM.getModule(), OMPRTL___kmpc_omp_task),
5140 TaskArgs);
5141 }
5142 // Check if parent region is untied and build return for untied task;
5143 if (auto *Region =
5144 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5145 Region->emitUntiedSwitch(CGF);
5146 };
5147
5148 llvm::Value *DepWaitTaskArgs[6];
5149 if (!Data.Dependences.empty()) {
5150 DepWaitTaskArgs[0] = UpLoc;
5151 DepWaitTaskArgs[1] = ThreadID;
5152 DepWaitTaskArgs[2] = NumOfElements;
5153 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5154 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5155 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5156 }
5157 auto &M = CGM.getModule();
5158 auto &&ElseCodeGen = [this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
5159 TaskEntry, &Data, &DepWaitTaskArgs,
5160 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
5161 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5162 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5163 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5164 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5165 // is specified.
5166 if (!Data.Dependences.empty())
5167 CGF.EmitRuntimeCall(
5168 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps),
5169 DepWaitTaskArgs);
5170 // Call proxy_task_entry(gtid, new_task);
5171 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5172 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
5173 Action.Enter(CGF);
5174 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
5175 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
5176 OutlinedFnArgs);
5177 };
5178
5179 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5180 // kmp_task_t *new_task);
5181 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5182 // kmp_task_t *new_task);
5183 RegionCodeGenTy RCG(CodeGen);
5184 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
5185 M, OMPRTL___kmpc_omp_task_begin_if0),
5186 TaskArgs,
5187 OMPBuilder.getOrCreateRuntimeFunction(
5188 M, OMPRTL___kmpc_omp_task_complete_if0),
5189 TaskArgs);
5190 RCG.setAction(Action);
5191 RCG(CGF);
5192 };
5193
5194 if (IfCond) {
5195 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
5196 } else {
5197 RegionCodeGenTy ThenRCG(ThenCodeGen);
5198 ThenRCG(CGF);
5199 }
5200}
5201
5202void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5203 const OMPLoopDirective &D,
5204 llvm::Function *TaskFunction,
5205 QualType SharedsTy, Address Shareds,
5206 const Expr *IfCond,
5207 const OMPTaskDataTy &Data) {
5208 if (!CGF.HaveInsertPoint())
5209 return;
5210 TaskResultTy Result =
5211 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5212 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
5213 // libcall.
5214 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5215 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5216 // sched, kmp_uint64 grainsize, void *task_dup);
5217 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5218 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5219 llvm::Value *IfVal;
5220 if (IfCond) {
5221 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5222 /*isSigned=*/true);
5223 } else {
5224 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
5225 }
5226
5227 LValue LBLVal = CGF.EmitLValueForField(
5228 Result.TDBase,
5229 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
5230 const auto *LBVar =
5231 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5232 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF),
5233 LBLVal.getQuals(),
5234 /*IsInitializer=*/true);
5235 LValue UBLVal = CGF.EmitLValueForField(
5236 Result.TDBase,
5237 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
5238 const auto *UBVar =
5239 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5240 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF),
5241 UBLVal.getQuals(),
5242 /*IsInitializer=*/true);
5243 LValue StLVal = CGF.EmitLValueForField(
5244 Result.TDBase,
5245 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
5246 const auto *StVar =
5247 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5248 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF),
5249 StLVal.getQuals(),
5250 /*IsInitializer=*/true);
5251 // Store reductions address.
5252 LValue RedLVal = CGF.EmitLValueForField(
5253 Result.TDBase,
5254 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
5255 if (Data.Reductions) {
5256 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
5257 } else {
5258 CGF.EmitNullInitialization(RedLVal.getAddress(CGF),
5259 CGF.getContext().VoidPtrTy);
5260 }
5261 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
5262 llvm::Value *TaskArgs[] = {
5263 UpLoc,
5264 ThreadID,
5265 Result.NewTask,
5266 IfVal,
5267 LBLVal.getPointer(CGF),
5268 UBLVal.getPointer(CGF),
5269 CGF.EmitLoadOfScalar(StLVal, Loc),
5270 llvm::ConstantInt::getSigned(
5271 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
5272 llvm::ConstantInt::getSigned(
5273 CGF.IntTy, Data.Schedule.getPointer()
5274 ? Data.Schedule.getInt() ? NumTasks : Grainsize
5275 : NoSchedule),
5276 Data.Schedule.getPointer()
5277 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
5278 /*isSigned=*/false)
5279 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
5280 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5281 Result.TaskDupFn, CGF.VoidPtrTy)
5282 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
5283 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
5284 CGM.getModule(), OMPRTL___kmpc_taskloop),
5285 TaskArgs);
5286}
5287
5288/// Emit reduction operation for each element of array (required for
5289/// array sections) LHS op = RHS.
5290/// \param Type Type of array.
5291/// \param LHSVar Variable on the left side of the reduction operation
5292/// (references element of array in original variable).
5293/// \param RHSVar Variable on the right side of the reduction operation
5294/// (references element of array in original variable).
5295/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5296/// RHSVar.
5297static void EmitOMPAggregateReduction(
5298 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5299 const VarDecl *RHSVar,
5300 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5301 const Expr *, const Expr *)> &RedOpGen,
5302 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5303 const Expr *UpExpr = nullptr) {
5304 // Perform element-by-element initialization.
5305 QualType ElementTy;
5306 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5307 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5308
5309 // Drill down to the base element type on both arrays.
5310 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5311 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
5312
5313 llvm::Value *RHSBegin = RHSAddr.getPointer();
5314 llvm::Value *LHSBegin = LHSAddr.getPointer();
5315 // Cast from pointer to array type to pointer to single element.
5316 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
5317 // The basic structure here is a while-do loop.
5318 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5319 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5320 llvm::Value *IsEmpty =
5321 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5322 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5323
5324 // Enter the loop body, making that address the current address.
5325 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
5326 CGF.EmitBlock(BodyBB);
5327
5328 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5329
5330 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5331 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5332 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5333 Address RHSElementCurrent =
5334 Address(RHSElementPHI,
5335 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5336
5337 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5338 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5339 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5340 Address LHSElementCurrent =
5341 Address(LHSElementPHI,
5342 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5343
5344 // Emit copy.
5345 CodeGenFunction::OMPPrivateScope Scope(CGF);
5346 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5347 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
5348 Scope.Privatize();
5349 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5350 Scope.ForceCleanup();
5351
5352 // Shift the address forward by one element.
5353 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
5354 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
5355 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
5356 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5357 // Check whether we've reached the end.
5358 llvm::Value *Done =
5359 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5360 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5361 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5362 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5363
5364 // Done.
5365 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5366}
5367
5368/// Emit reduction combiner. If the combiner is a simple expression emit it as
5369/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5370/// UDR combiner function.
5371static void emitReductionCombiner(CodeGenFunction &CGF,
5372 const Expr *ReductionOp) {
5373 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5374 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5375 if (const auto *DRE =
5376 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
5377 if (const auto *DRD =
5378 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
5379 std::pair<llvm::Function *, llvm::Function *> Reduction =
5380 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5381 RValue Func = RValue::get(Reduction.first);
5382 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5383 CGF.EmitIgnoredExpr(ReductionOp);
5384 return;
5385 }
5386 CGF.EmitIgnoredExpr(ReductionOp);
5387}
5388
5389llvm::Function *CGOpenMPRuntime::emitReductionFunction(
5390 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5391 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5392 ArrayRef<const Expr *> ReductionOps) {
5393 ASTContext &C = CGM.getContext();
5394
5395 // void reduction_func(void *LHSArg, void *RHSArg);
5396 FunctionArgList Args;
5397 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5398 ImplicitParamDecl::Other);
5399 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5400 ImplicitParamDecl::Other);
5401 Args.push_back(&LHSArg);
5402 Args.push_back(&RHSArg);
5403 const auto &CGFI =
5404 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5405 std::string Name = getName({"omp", "reduction", "reduction_func"});
5406 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5407 llvm::GlobalValue::InternalLinkage, Name,
5408 &CGM.getModule());
5409 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
5410 Fn->setDoesNotRecurse();
5411 CodeGenFunction CGF(CGM);
5412 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
5413
5414 // Dst = (void*[n])(LHSArg);
5415 // Src = (void*[n])(RHSArg);
5416 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5417 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5418 ArgsType), CGF.getPointerAlign());
5419 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5420 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5421 ArgsType), CGF.getPointerAlign());
5422
5423 // ...
5424 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5425 // ...
5426 CodeGenFunction::OMPPrivateScope Scope(CGF);
5427 auto IPriv = Privates.begin();
5428 unsigned Idx = 0;
5429 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
5430 const auto *RHSVar =
5431 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5432 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
5433 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
5434 });
5435 const auto *LHSVar =
5436 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5437 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
5438 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
5439 });
5440 QualType PrivTy = (*IPriv)->getType();
5441 if (PrivTy->isVariablyModifiedType()) {
5442 // Get array size and emit VLA type.
5443 ++Idx;
5444 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
5445 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
5446 const VariableArrayType *VLA =
5447 CGF.getContext().getAsVariableArrayType(PrivTy);
5448 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
5449 CodeGenFunction::OpaqueValueMapping OpaqueMap(
5450 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
5451 CGF.EmitVariablyModifiedType(PrivTy);
5452 }
5453 }
5454 Scope.Privatize();
5455 IPriv = Privates.begin();
5456 auto ILHS = LHSExprs.begin();
5457 auto IRHS = RHSExprs.begin();
5458 for (const Expr *E : ReductionOps) {
5459 if ((*IPriv)->getType()->isArrayType()) {
5460 // Emit reduction for array section.
5461 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5462 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5463 EmitOMPAggregateReduction(
5464 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5465 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5466 emitReductionCombiner(CGF, E);
5467 });
5468 } else {
5469 // Emit reduction for array subscript or single variable.
5470 emitReductionCombiner(CGF, E);
5471 }
5472 ++IPriv;
5473 ++ILHS;
5474 ++IRHS;
5475 }
5476 Scope.ForceCleanup();
5477 CGF.FinishFunction();
5478 return Fn;
5479}
5480
5481void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5482 const Expr *ReductionOp,
5483 const Expr *PrivateRef,
5484 const DeclRefExpr *LHS,
5485 const DeclRefExpr *RHS) {
5486 if (PrivateRef->getType()->isArrayType()) {
5487 // Emit reduction for array section.
5488 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5489 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
5490 EmitOMPAggregateReduction(
5491 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5492 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5493 emitReductionCombiner(CGF, ReductionOp);
5494 });
5495 } else {
5496 // Emit reduction for array subscript or single variable.
5497 emitReductionCombiner(CGF, ReductionOp);
5498 }
5499}
5500
5501void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
5502 ArrayRef<const Expr *> Privates,
5503 ArrayRef<const Expr *> LHSExprs,
5504 ArrayRef<const Expr *> RHSExprs,
5505 ArrayRef<const Expr *> ReductionOps,
5506 ReductionOptionsTy Options) {
5507 if (!CGF.HaveInsertPoint())
5508 return;
5509
5510 bool WithNowait = Options.WithNowait;
5511 bool SimpleReduction = Options.SimpleReduction;
5512
5513 // Next code should be emitted for reduction:
5514 //
5515 // static kmp_critical_name lock = { 0 };
5516 //
5517 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5518 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5519 // ...
5520 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5521 // *(Type<n>-1*)rhs[<n>-1]);
5522 // }
5523 //
5524 // ...
5525 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5526 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5527 // RedList, reduce_func, &<lock>)) {
5528 // case 1:
5529 // ...
5530 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5531 // ...
5532 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5533 // break;
5534 // case 2:
5535 // ...
5536 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5537 // ...
5538 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
5539 // break;
5540 // default:;
5541 // }
5542 //
5543 // if SimpleReduction is true, only the next code is generated:
5544 // ...
5545 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5546 // ...
5547
5548 ASTContext &C = CGM.getContext();
5549
5550 if (SimpleReduction) {
5551 CodeGenFunction::RunCleanupsScope Scope(CGF);
5552 auto IPriv = Privates.begin();
5553 auto ILHS = LHSExprs.begin();
5554 auto IRHS = RHSExprs.begin();
5555 for (const Expr *E : ReductionOps) {
5556 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5557 cast<DeclRefExpr>(*IRHS));
5558 ++IPriv;
5559 ++ILHS;
5560 ++IRHS;
5561 }
5562 return;
5563 }
5564
5565 // 1. Build a list of reduction variables.
5566 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
5567 auto Size = RHSExprs.size();
5568 for (const Expr *E : Privates) {
5569 if (E->getType()->isVariablyModifiedType())
5570 // Reserve place for array size.
5571 ++Size;
5572 }
5573 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
5574 QualType ReductionArrayTy =
5575 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
5576 /*IndexTypeQuals=*/0);
5577 Address ReductionList =
5578 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
5579 auto IPriv = Privates.begin();
5580 unsigned Idx = 0;
5581 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5582 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
5583 CGF.Builder.CreateStore(
5584 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5585 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy),
5586 Elem);
5587 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5588 // Store array size.
5589 ++Idx;
5590 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
5591 llvm::Value *Size = CGF.Builder.CreateIntCast(
5592 CGF.getVLASize(
5593 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
5594 .NumElts,
5595 CGF.SizeTy, /*isSigned=*/false);
5596 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5597 Elem);
5598 }
5599 }
5600
5601 // 2. Emit reduce_func().
5602 llvm::Function *ReductionFn = emitReductionFunction(
5603 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5604 LHSExprs, RHSExprs, ReductionOps);
5605
5606 // 3. Create static kmp_critical_name lock = { 0 };
5607 std::string Name = getName({"reduction"});
5608 llvm::Value *Lock = getCriticalRegionLock(Name);
5609
5610 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5611 // RedList, reduce_func, &<lock>);
5612 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5613 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5614 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5615 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5616 ReductionList.getPointer(), CGF.VoidPtrTy);
5617 llvm::Value *Args[] = {
5618 IdentTLoc, // ident_t *<loc>
5619 ThreadId, // i32 <gtid>
5620 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5621 ReductionArrayTySize, // size_type sizeof(RedList)
5622 RL, // void *RedList
5623 ReductionFn, // void (*) (void *, void *) <reduce_func>
5624 Lock // kmp_critical_name *&<lock>
5625 };
5626 llvm::Value *Res = CGF.EmitRuntimeCall(
5627 OMPBuilder.getOrCreateRuntimeFunction(
5628 CGM.getModule(),
5629 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5630 Args);
5631
5632 // 5. Build switch(res)
5633 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5634 llvm::SwitchInst *SwInst =
5635 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
5636
5637 // 6. Build case 1:
5638 // ...
5639 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5640 // ...
5641 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5642 // break;
5643 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
5644 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5645 CGF.EmitBlock(Case1BB);
5646
5647 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5648 llvm::Value *EndArgs[] = {
5649 IdentTLoc, // ident_t *<loc>
5650 ThreadId, // i32 <gtid>
5651 Lock // kmp_critical_name *&<lock>
5652 };
5653 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5654 CodeGenFunction &CGF, PrePostActionTy &Action) {
5655 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
5656 auto IPriv = Privates.begin();
5657 auto ILHS = LHSExprs.begin();
5658 auto IRHS = RHSExprs.begin();
5659 for (const Expr *E : ReductionOps) {
5660 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5661 cast<DeclRefExpr>(*IRHS));
5662 ++IPriv;
5663 ++ILHS;
5664 ++IRHS;
5665 }
5666 };
5667 RegionCodeGenTy RCG(CodeGen);
5668 CommonActionTy Action(
5669 nullptr, llvm::None,
5670 OMPBuilder.getOrCreateRuntimeFunction(
5671 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5672 : OMPRTL___kmpc_end_reduce),
5673 EndArgs);
5674 RCG.setAction(Action);
5675 RCG(CGF);
5676
5677 CGF.EmitBranch(DefaultBB);
5678
5679 // 7. Build case 2:
5680 // ...
5681 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5682 // ...
5683 // break;
5684 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
5685 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5686 CGF.EmitBlock(Case2BB);
5687
5688 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5689 CodeGenFunction &CGF, PrePostActionTy &Action) {
5690 auto ILHS = LHSExprs.begin();
5691 auto IRHS = RHSExprs.begin();
5692 auto IPriv = Privates.begin();
5693 for (const Expr *E : ReductionOps) {
5694 const Expr *XExpr = nullptr;
5695 const Expr *EExpr = nullptr;
5696 const Expr *UpExpr = nullptr;
5697 BinaryOperatorKind BO = BO_Comma;
5698 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
5699 if (BO->getOpcode() == BO_Assign) {
5700 XExpr = BO->getLHS();
5701 UpExpr = BO->getRHS();
5702 }
5703 }
5704 // Try to emit update expression as a simple atomic.
5705 const Expr *RHSExpr = UpExpr;
5706 if (RHSExpr) {
5707 // Analyze RHS part of the whole expression.
5708 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5709 RHSExpr->IgnoreParenImpCasts())) {
5710 // If this is a conditional operator, analyze its condition for
5711 // min/max reduction operator.
5712 RHSExpr = ACO->getCond();
5713 }
5714 if (const auto *BORHS =
5715 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5716 EExpr = BORHS->getRHS();
5717 BO = BORHS->getOpcode();
5718 }
5719 }
5720 if (XExpr) {
5721 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5722 auto &&AtomicRedGen = [BO, VD,
5723 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5724 const Expr *EExpr, const Expr *UpExpr) {
5725 LValue X = CGF.EmitLValue(XExpr);
5726 RValue E;
5727 if (EExpr)
5728 E = CGF.EmitAnyExpr(EExpr);
5729 CGF.EmitOMPAtomicSimpleUpdateExpr(
5730 X, E, BO, /*IsXLHSInRHSPart=*/true,
5731 llvm::AtomicOrdering::Monotonic, Loc,
5732 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
5733 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5734 PrivateScope.addPrivate(
5735 VD, [&CGF, VD, XRValue, Loc]() {
5736 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5737 CGF.emitOMPSimpleStore(
5738 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5739 VD->getType().getNonReferenceType(), Loc);
5740 return LHSTemp;
5741 });
5742 (void)PrivateScope.Privatize();
5743 return CGF.EmitAnyExpr(UpExpr);
5744 });
5745 };
5746 if ((*IPriv)->getType()->isArrayType()) {
5747 // Emit atomic reduction for array section.
5748 const auto *RHSVar =
5749 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5750 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5751 AtomicRedGen, XExpr, EExpr, UpExpr);
5752 } else {
5753 // Emit atomic reduction for array subscript or single variable.
5754 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5755 }
5756 } else {
5757 // Emit as a critical region.
5758 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
5759 const Expr *, const Expr *) {
5760 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
5761 std::string Name = RT.getName({"atomic_reduction"});
5762 RT.emitCriticalRegion(
5763 CGF, Name,
5764 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5765 Action.Enter(CGF);
5766 emitReductionCombiner(CGF, E);
5767 },
5768 Loc);
5769 };
5770 if ((*IPriv)->getType()->isArrayType()) {
5771 const auto *LHSVar =
5772 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5773 const auto *RHSVar =
5774 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
5775 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5776 CritRedGen);
5777 } else {
5778 CritRedGen(CGF, nullptr, nullptr, nullptr);
5779 }
5780 }
5781 ++ILHS;
5782 ++IRHS;
5783 ++IPriv;
5784 }
5785 };
5786 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5787 if (!WithNowait) {
5788 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5789 llvm::Value *EndArgs[] = {
5790 IdentTLoc, // ident_t *<loc>
5791 ThreadId, // i32 <gtid>
5792 Lock // kmp_critical_name *&<lock>
5793 };
5794 CommonActionTy Action(nullptr, llvm::None,
5795 OMPBuilder.getOrCreateRuntimeFunction(
5796 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5797 EndArgs);
5798 AtomicRCG.setAction(Action);
5799 AtomicRCG(CGF);
5800 } else {
5801 AtomicRCG(CGF);
5802 }
5803
5804 CGF.EmitBranch(DefaultBB);
5805 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5806}
5807
5808/// Generates unique name for artificial threadprivate variables.
5809/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5810static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5811 const Expr *Ref) {
5812 SmallString<256> Buffer;
5813 llvm::raw_svector_ostream Out(Buffer);
5814 const clang::DeclRefExpr *DE;
5815 const VarDecl *D = ::getBaseDecl(Ref, DE);
5816 if (!D)
5817 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5818 D = D->getCanonicalDecl();
5819 std::string Name = CGM.getOpenMPRuntime().getName(
5820 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
5821 Out << Prefix << Name << "_"
5822 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
5823 return std::string(Out.str());
5824}
5825
5826/// Emits reduction initializer function:
5827/// \code
5828/// void @.red_init(void* %arg, void* %orig) {
5829/// %0 = bitcast void* %arg to <type>*
5830/// store <type> <init>, <type>* %0
5831/// ret void
5832/// }
5833/// \endcode
5834static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
5835 SourceLocation Loc,
5836 ReductionCodeGen &RCG, unsigned N) {
5837 ASTContext &C = CGM.getContext();
5838 QualType VoidPtrTy = C.VoidPtrTy;
5839 VoidPtrTy.addRestrict();
5840 FunctionArgList Args;
5841 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy,
5842 ImplicitParamDecl::Other);
5843 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy,
5844 ImplicitParamDecl::Other);
5845 Args.emplace_back(&Param);
5846 Args.emplace_back(&ParamOrig);
5847 const auto &FnInfo =
5848 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5849 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
5850 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
5851 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5852 Name, &CGM.getModule());
5853 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
5854 Fn->setDoesNotRecurse();
5855 CodeGenFunction CGF(CGM);
5856 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
5857 Address PrivateAddr = CGF.EmitLoadOfPointer(
5858 CGF.GetAddrOfLocalVar(&Param),
5859 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5860 llvm::Value *Size = nullptr;
5861 // If the size of the reduction item is non-constant, load it from global
5862 // threadprivate variable.
5863 if (RCG.getSizes(N).second) {
5864 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5865 CGF, CGM.getContext().getSizeType(),
5866 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
5867 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
5868 CGM.getContext().getSizeType(), Loc);
5869 }
5870 RCG.emitAggregateType(CGF, N, Size);
5871 LValue OrigLVal;
5872 // If initializer uses initializer from declare reduction construct, emit a
5873 // pointer to the address of the original reduction item (reuired by reduction
5874 // initializer)
5875 if (RCG.usesReductionInitializer(N)) {
5876 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig);
5877 SharedAddr = CGF.EmitLoadOfPointer(
5878 SharedAddr,
5879 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
5880 OrigLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
5881 } else {
5882 OrigLVal = CGF.MakeNaturalAlignAddrLValue(
5883 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
5884 CGM.getContext().VoidPtrTy);
5885 }
5886 // Emit the initializer:
5887 // %0 = bitcast void* %arg to <type>*
5888 // store <type> <init>, <type>* %0
5889 RCG.emitInitialization(CGF, N, PrivateAddr, OrigLVal,
5890 [](CodeGenFunction &) { return false; });
5891 CGF.FinishFunction();
5892 return Fn;
5893}
5894
5895/// Emits reduction combiner function:
5896/// \code
5897/// void @.red_comb(void* %arg0, void* %arg1) {
5898/// %lhs = bitcast void* %arg0 to <type>*
5899/// %rhs = bitcast void* %arg1 to <type>*
5900/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
5901/// store <type> %2, <type>* %lhs
5902/// ret void
5903/// }
5904/// \endcode
5905static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
5906 SourceLocation Loc,
5907 ReductionCodeGen &RCG, unsigned N,
5908 const Expr *ReductionOp,
5909 const Expr *LHS, const Expr *RHS,
5910 const Expr *PrivateRef) {
5911 ASTContext &C = CGM.getContext();
5912 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
5913 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
5914 FunctionArgList Args;
5915 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
5916 C.VoidPtrTy, ImplicitParamDecl::Other);
5917 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5918 ImplicitParamDecl::Other);
5919 Args.emplace_back(&ParamInOut);
5920 Args.emplace_back(&ParamIn);
5921 const auto &FnInfo =
5922 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5923 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
5924 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
5925 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5926 Name, &CGM.getModule());
5927 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
5928 Fn->setDoesNotRecurse();
5929 CodeGenFunction CGF(CGM);
5930 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
5931 llvm::Value *Size = nullptr;
5932 // If the size of the reduction item is non-constant, load it from global
5933 // threadprivate variable.
5934 if (RCG.getSizes(N).second) {
5935 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5936 CGF, CGM.getContext().getSizeType(),
5937 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
5938 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
5939 CGM.getContext().getSizeType(), Loc);
5940 }
5941 RCG.emitAggregateType(CGF, N, Size);
5942 // Remap lhs and rhs variables to the addresses of the function arguments.
5943 // %lhs = bitcast void* %arg0 to <type>*
5944 // %rhs = bitcast void* %arg1 to <type>*
5945 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5946 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
5947 // Pull out the pointer to the variable.
5948 Address PtrAddr = CGF.EmitLoadOfPointer(
5949 CGF.GetAddrOfLocalVar(&ParamInOut),
5950 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5951 return CGF.Builder.CreateElementBitCast(
5952 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
5953 });
5954 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
5955 // Pull out the pointer to the variable.
5956 Address PtrAddr = CGF.EmitLoadOfPointer(
5957 CGF.GetAddrOfLocalVar(&ParamIn),
5958 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5959 return CGF.Builder.CreateElementBitCast(
5960 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
5961 });
5962 PrivateScope.Privatize();
5963 // Emit the combiner body:
5964 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
5965 // store <type> %2, <type>* %lhs
5966 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
5967 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
5968 cast<DeclRefExpr>(RHS));
5969 CGF.FinishFunction();
5970 return Fn;
5971}
5972
5973/// Emits reduction finalizer function:
5974/// \code
5975/// void @.red_fini(void* %arg) {
5976/// %0 = bitcast void* %arg to <type>*
5977/// <destroy>(<type>* %0)
5978/// ret void
5979/// }
5980/// \endcode
5981static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
5982 SourceLocation Loc,
5983 ReductionCodeGen &RCG, unsigned N) {
5984 if (!RCG.needCleanups(N))
5985 return nullptr;
5986 ASTContext &C = CGM.getContext();
5987 FunctionArgList Args;
5988 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5989 ImplicitParamDecl::Other);
5990 Args.emplace_back(&Param);
5991 const auto &FnInfo =
5992 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
5993 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
5994 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
5995 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5996 Name, &CGM.getModule());
5997 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
5998 Fn->setDoesNotRecurse();
5999 CodeGenFunction CGF(CGM);
6000 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
6001 Address PrivateAddr = CGF.EmitLoadOfPointer(
6002 CGF.GetAddrOfLocalVar(&Param),
6003 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6004 llvm::Value *Size = nullptr;
6005 // If the size of the reduction item is non-constant, load it from global
6006 // threadprivate variable.
6007 if (RCG.getSizes(N).second) {
6008 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6009 CGF, CGM.getContext().getSizeType(),
6010 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
6011 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6012 CGM.getContext().getSizeType(), Loc);
6013 }
6014 RCG.emitAggregateType(CGF, N, Size);
6015 // Emit the finalizer body:
6016 // <destroy>(<type>* %0)
6017 RCG.emitCleanups(CGF, N, PrivateAddr);
6018 CGF.FinishFunction(Loc);
6019 return Fn;
6020}
6021
6022llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6023 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6024 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6025 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6026 return nullptr;
6027
6028 // Build typedef struct:
6029 // kmp_taskred_input {
6030 // void *reduce_shar; // shared reduction item
6031 // void *reduce_orig; // original reduction item used for initialization
6032 // size_t reduce_size; // size of data item
6033 // void *reduce_init; // data initialization routine
6034 // void *reduce_fini; // data finalization routine
6035 // void *reduce_comb; // data combiner routine
6036 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6037 // } kmp_taskred_input_t;
6038 ASTContext &C = CGM.getContext();
6039 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t");
6040 RD->startDefinition();
6041 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6042 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6043 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6044 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6045 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6046 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6047 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6048 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6049 RD->completeDefinition();
6050 QualType RDType = C.getRecordType(RD);
6051 unsigned Size = Data.ReductionVars.size();
6052 llvm::APInt ArraySize(/*numBits=*/64, Size);
6053 QualType ArrayRDType = C.getConstantArrayType(
6054 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
6055 // kmp_task_red_input_t .rd_input.[Size];
6056 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6057 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs,
6058 Data.ReductionCopies, Data.ReductionOps);
6059 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6060 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6061 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6062 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6063 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6064 TaskRedInput.getPointer(), Idxs,
6065 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6066 ".rd_input.gep.");
6067 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6068 // ElemLVal.reduce_shar = &Shareds[Cnt];
6069 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6070 RCG.emitSharedOrigLValue(CGF, Cnt);
6071 llvm::Value *CastedShared =
6072 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF));
6073 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6074 // ElemLVal.reduce_orig = &Origs[Cnt];
6075 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD);
6076 llvm::Value *CastedOrig =
6077 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF));
6078 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal);
6079 RCG.emitAggregateType(CGF, Cnt);
6080 llvm::Value *SizeValInChars;
6081 llvm::Value *SizeVal;
6082 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6083 // We use delayed creation/initialization for VLAs and array sections. It is
6084 // required because runtime does not provide the way to pass the sizes of
6085 // VLAs/array sections to initializer/combiner/finalizer functions. Instead
6086 // threadprivate global variables are used to store these values and use
6087 // them in the functions.
6088 bool DelayedCreation = !!SizeVal;
6089 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6090 /*isSigned=*/false);
6091 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6092 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6093 // ElemLVal.reduce_init = init;
6094 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6095 llvm::Value *InitAddr =
6096 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6097 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6098 // ElemLVal.reduce_fini = fini;
6099 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6100 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6101 llvm::Value *FiniAddr = Fini
6102 ? CGF.EmitCastToVoidPtr(Fini)
6103 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6104 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6105 // ElemLVal.reduce_comb = comb;
6106 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6107 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6108 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6109 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6110 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6111 // ElemLVal.flags = 0;
6112 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6113 if (DelayedCreation) {
6114 CGF.EmitStoreOfScalar(
6115 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
6116 FlagsLVal);
6117 } else
6118 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF),
6119 FlagsLVal.getType());
6120 }
6121 if (Data.IsReductionWithTaskMod) {
6122 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int
6123 // is_ws, int num, void *data);
6124 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc);
6125 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
6126 CGM.IntTy, /*isSigned=*/true);
6127 llvm::Value *Args[] = {
6128 IdentTLoc, GTid,
6129 llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0,
6130 /*isSigned=*/true),
6131 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6132 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6133 TaskRedInput.getPointer(), CGM.VoidPtrTy)};
6134 return CGF.EmitRuntimeCall(
6135 OMPBuilder.getOrCreateRuntimeFunction(
6136 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
6137 Args);
6138 }
6139 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data);
6140 llvm::Value *Args[] = {
6141 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6142 /*isSigned=*/true),
6143 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6144 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6145 CGM.VoidPtrTy)};
6146 return CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
6147 CGM.getModule(), OMPRTL___kmpc_taskred_init),
6148 Args);
6149}
6150
6151void CGOpenMPRuntime::emitTaskReductionFini(CodeGenFunction &CGF,
6152 SourceLocation Loc,
6153 bool IsWorksharingReduction) {
6154 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int
6155 // is_ws, int num, void *data);
6156 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc);
6157 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
6158 CGM.IntTy, /*isSigned=*/true);
6159 llvm::Value *Args[] = {IdentTLoc, GTid,
6160 llvm::ConstantInt::get(CGM.IntTy,
6161 IsWorksharingReduction ? 1 : 0,
6162 /*isSigned=*/true)};
6163 (void)CGF.EmitRuntimeCall(
6164 OMPBuilder.getOrCreateRuntimeFunction(
6165 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
6166 Args);
6167}
6168
6169void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6170 SourceLocation Loc,
6171 ReductionCodeGen &RCG,
6172 unsigned N) {
6173 auto Sizes = RCG.getSizes(N);
6174 // Emit threadprivate global variable if the type is non-constant
6175 // (Sizes.second = nullptr).
6176 if (Sizes.second) {
6177 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6178 /*isSigned=*/false);
6179 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6180 CGF, CGM.getContext().getSizeType(),
6181 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
6182 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6183 }
6184}
6185
6186Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6187 SourceLocation Loc,
6188 llvm::Value *ReductionsPtr,
6189 LValue SharedLVal) {
6190 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6191 // *d);
6192 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
6193 CGM.IntTy,
6194 /*isSigned=*/true),
6195 ReductionsPtr,
6196 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6197 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)};
6198 return Address(
6199 CGF.EmitRuntimeCall(
6200 OMPBuilder.getOrCreateRuntimeFunction(
6201 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
6202 Args),
6203 SharedLVal.getAlignment());
6204}
6205
6206void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6207 SourceLocation Loc) {
6208 if (!CGF.HaveInsertPoint())
6209 return;
6210
6211 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
6212 OMPBuilder.createTaskwait(CGF.Builder);
6213 } else {
6214 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6215 // global_tid);
6216 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6217 // Ignore return result until untied tasks are supported.
6218 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
6219 CGM.getModule(), OMPRTL___kmpc_omp_taskwait),
6220 Args);
6221 }
6222
6223 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6224 Region->emitUntiedSwitch(CGF);
6225}
6226
6227void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
6228 OpenMPDirectiveKind InnerKind,
6229 const RegionCodeGenTy &CodeGen,
6230 bool HasCancel) {
6231 if (!CGF.HaveInsertPoint())
6232 return;
6233 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel,
6234 InnerKind != OMPD_critical &&
6235 InnerKind != OMPD_master);
6236 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
6237}
6238
6239namespace {
6240enum RTCancelKind {
6241 CancelNoreq = 0,
6242 CancelParallel = 1,
6243 CancelLoop = 2,
6244 CancelSections = 3,
6245 CancelTaskgroup = 4
6246};
6247} // anonymous namespace
6248
6249static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6250 RTCancelKind CancelKind = CancelNoreq;
6251 if (CancelRegion == OMPD_parallel)
6252 CancelKind = CancelParallel;
6253 else if (CancelRegion == OMPD_for)
6254 CancelKind = CancelLoop;
6255 else if (CancelRegion == OMPD_sections)
6256 CancelKind = CancelSections;
6257 else {
6258 assert(CancelRegion == OMPD_taskgroup)((CancelRegion == OMPD_taskgroup) ? static_cast<void> (
0) : __assert_fail ("CancelRegion == OMPD_taskgroup", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6258, __PRETTY_FUNCTION__))
;
6259 CancelKind = CancelTaskgroup;
6260 }
6261 return CancelKind;
6262}
6263
6264void CGOpenMPRuntime::emitCancellationPointCall(
6265 CodeGenFunction &CGF, SourceLocation Loc,
6266 OpenMPDirectiveKind CancelRegion) {
6267 if (!CGF.HaveInsertPoint())
6268 return;
6269 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6270 // global_tid, kmp_int32 cncl_kind);
6271 if (auto *OMPRegionInfo =
6272 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
6273 // For 'cancellation point taskgroup', the task region info may not have a
6274 // cancel. This may instead happen in another adjacent task.
6275 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6276 llvm::Value *Args[] = {
6277 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6278 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6279 // Ignore return result until untied tasks are supported.
6280 llvm::Value *Result = CGF.EmitRuntimeCall(
6281 OMPBuilder.getOrCreateRuntimeFunction(
6282 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6283 Args);
6284 // if (__kmpc_cancellationpoint()) {
6285 // exit from construct;
6286 // }
6287 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6288 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6289 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
6290 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6291 CGF.EmitBlock(ExitBB);
6292 // exit from construct;
6293 CodeGenFunction::JumpDest CancelDest =
6294 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6295 CGF.EmitBranchThroughCleanup(CancelDest);
6296 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6297 }
6298 }
6299}
6300
6301void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
6302 const Expr *IfCond,
6303 OpenMPDirectiveKind CancelRegion) {
6304 if (!CGF.HaveInsertPoint())
6305 return;
6306 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6307 // kmp_int32 cncl_kind);
6308 auto &M = CGM.getModule();
6309 if (auto *OMPRegionInfo =
6310 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
6311 auto &&ThenGen = [this, &M, Loc, CancelRegion,
6312 OMPRegionInfo](CodeGenFunction &CGF, PrePostActionTy &) {
6313 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
6314 llvm::Value *Args[] = {
6315 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
6316 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6317 // Ignore return result until untied tasks are supported.
6318 llvm::Value *Result = CGF.EmitRuntimeCall(
6319 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6320 // if (__kmpc_cancel()) {
6321 // exit from construct;
6322 // }
6323 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6324 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6325 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
6326 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6327 CGF.EmitBlock(ExitBB);
6328 // exit from construct;
6329 CodeGenFunction::JumpDest CancelDest =
6330 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6331 CGF.EmitBranchThroughCleanup(CancelDest);
6332 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6333 };
6334 if (IfCond) {
6335 emitIfClause(CGF, IfCond, ThenGen,
6336 [](CodeGenFunction &, PrePostActionTy &) {});
6337 } else {
6338 RegionCodeGenTy ThenRCG(ThenGen);
6339 ThenRCG(CGF);
6340 }
6341 }
6342}
6343
6344namespace {
6345/// Cleanup action for uses_allocators support.
6346class OMPUsesAllocatorsActionTy final : public PrePostActionTy {
6347 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators;
6348
6349public:
6350 OMPUsesAllocatorsActionTy(
6351 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6352 : Allocators(Allocators) {}
6353 void Enter(CodeGenFunction &CGF) override {
6354 if (!CGF.HaveInsertPoint())
6355 return;
6356 for (const auto &AllocatorData : Allocators) {
6357 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsInit(
6358 CGF, AllocatorData.first, AllocatorData.second);
6359 }
6360 }
6361 void Exit(CodeGenFunction &CGF) override {
6362 if (!CGF.HaveInsertPoint())
6363 return;
6364 for (const auto &AllocatorData : Allocators) {
6365 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsFini(CGF,
6366 AllocatorData.first);
6367 }
6368 }
6369};
6370} // namespace
6371
6372void CGOpenMPRuntime::emitTargetOutlinedFunction(
6373 const OMPExecutableDirective &D, StringRef ParentName,
6374 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6375 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
6376 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6376, __PRETTY_FUNCTION__))
;
6377 HasEmittedTargetRegion = true;
6378 SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators;
6379 for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) {
6380 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
6381 const OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
6382 if (!D.AllocatorTraits)
6383 continue;
6384 Allocators.emplace_back(D.Allocator, D.AllocatorTraits);
6385 }
6386 }
6387 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6388 CodeGen.setAction(UsesAllocatorAction);
6389 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6390 IsOffloadEntry, CodeGen);
6391}
6392
6393void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF,
6394 const Expr *Allocator,
6395 const Expr *AllocatorTraits) {
6396 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc());
6397 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true);
6398 // Use default memspace handle.
6399 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
6400 llvm::Value *NumTraits = llvm::ConstantInt::get(
6401 CGF.IntTy, cast<ConstantArrayType>(
6402 AllocatorTraits->getType()->getAsArrayTypeUnsafe())
6403 ->getSize()
6404 .getLimitedValue());
6405 LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits);
6406 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6407 AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy);
6408 AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy,
6409 AllocatorTraitsLVal.getBaseInfo(),
6410 AllocatorTraitsLVal.getTBAAInfo());
6411 llvm::Value *Traits =
6412 CGF.EmitLoadOfScalar(AllocatorTraitsLVal, AllocatorTraits->getExprLoc());
6413
6414 llvm::Value *AllocatorVal =
6415 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
6416 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6417 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6418 // Store to allocator.
6419 CGF.EmitVarDecl(*cast<VarDecl>(
6420 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl()));
6421 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts());
6422 AllocatorVal =
6423 CGF.EmitScalarConversion(AllocatorVal, CGF.getContext().VoidPtrTy,
6424 Allocator->getType(), Allocator->getExprLoc());
6425 CGF.EmitStoreOfScalar(AllocatorVal, AllocatorLVal);
6426}
6427
6428void CGOpenMPRuntime::emitUsesAllocatorsFini(CodeGenFunction &CGF,
6429 const Expr *Allocator) {
6430 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc());
6431 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true);
6432 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts());
6433 llvm::Value *AllocatorVal =
6434 CGF.EmitLoadOfScalar(AllocatorLVal, Allocator->getExprLoc());
6435 AllocatorVal = CGF.EmitScalarConversion(AllocatorVal, Allocator->getType(),
6436 CGF.getContext().VoidPtrTy,
6437 Allocator->getExprLoc());
6438 (void)CGF.EmitRuntimeCall(
6439 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
6440 OMPRTL___kmpc_destroy_allocator),
6441 {ThreadId, AllocatorVal});
6442}
6443
6444void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6445 const OMPExecutableDirective &D, StringRef ParentName,
6446 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6447 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
6448 // Create a unique name for the entry function using the source location
6449 // information of the current target region. The name will be something like:
6450 //
6451 // __omp_offloading_DD_FFFF_PP_lBB
6452 //
6453 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
6454 // mangled name of the function that encloses the target region and BB is the
6455 // line number of the target region.
6456
6457 unsigned DeviceID;
6458 unsigned FileID;
6459 unsigned Line;
6460 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
6461 Line);
6462 SmallString<64> EntryFnName;
6463 {
6464 llvm::raw_svector_ostream OS(EntryFnName);
6465 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6466 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
6467 }
6468
6469 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6470
6471 CodeGenFunction CGF(CGM, true);
6472 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
6473 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6474
6475 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc());
6476
6477 // If this target outline function is not an offload entry, we don't need to
6478 // register it.
6479 if (!IsOffloadEntry)
6480 return;
6481
6482 // The target region ID is used by the runtime library to identify the current
6483 // target region, so it only has to be unique and not necessarily point to
6484 // anything. It could be the pointer to the outlined function that implements
6485 // the target region, but we aren't using that so that the compiler doesn't
6486 // need to keep that, and could therefore inline the host function if proven
6487 // worthwhile during optimization. In the other hand, if emitting code for the
6488 // device, the ID has to be the function address so that it can retrieved from
6489 // the offloading entry and launched by the runtime library. We also mark the
6490 // outlined function to have external linkage in case we are emitting code for
6491 // the device, because these functions will be entry points to the device.
6492
6493 if (CGM.getLangOpts().OpenMPIsDevice) {
6494 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
6495 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
6496 OutlinedFn->setDSOLocal(false);
6497 if (CGM.getTriple().isAMDGCN())
6498 OutlinedFn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
6499 } else {
6500 std::string Name = getName({EntryFnName, "region_id"});
6501 OutlinedFnID = new llvm::GlobalVariable(
6502 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
6503 llvm::GlobalValue::WeakAnyLinkage,
6504 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
6505 }
6506
6507 // Register the information for the entry associated with this target region.
6508 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
6509 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
6510 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
6511}
6512
6513/// Checks if the expression is constant or does not have non-trivial function
6514/// calls.
6515static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6516 // We can skip constant expressions.
6517 // We can skip expressions with trivial calls or simple expressions.
6518 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6519 !E->hasNonTrivialCall(Ctx)) &&
6520 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6521}
6522
6523const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6524 const Stmt *Body) {
6525 const Stmt *Child = Body->IgnoreContainers();
6526 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6527 Child = nullptr;
6528 for (const Stmt *S : C->body()) {
6529 if (const auto *E = dyn_cast<Expr>(S)) {
6530 if (isTrivial(Ctx, E))
6531 continue;
6532 }
6533 // Some of the statements can be ignored.
6534 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6535 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6536 continue;
6537 // Analyze declarations.
6538 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6539 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6540 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6541 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6542 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6543 isa<UsingDirectiveDecl>(D) ||
6544 isa<OMPDeclareReductionDecl>(D) ||
6545 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6546 return true;
6547 const auto *VD = dyn_cast<VarDecl>(D);
6548 if (!VD)
6549 return false;
6550 return VD->isConstexpr() ||
6551 ((VD->getType().isTrivialType(Ctx) ||
6552 VD->getType()->isReferenceType()) &&
6553 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6554 }))
6555 continue;
6556 }
6557 // Found multiple children - cannot get the one child only.
6558 if (Child)
6559 return nullptr;
6560 Child = S;
6561 }
6562 if (Child)
6563 Child = Child->IgnoreContainers();
6564 }
6565 return Child;
6566}
6567
6568/// Emit the number of teams for a target directive. Inspect the num_teams
6569/// clause associated with a teams construct combined or closely nested
6570/// with the target directive.
6571///
6572/// Emit a team of size one for directives such as 'target parallel' that
6573/// have no associated teams construct.
6574///
6575/// Otherwise, return nullptr.
6576static llvm::Value *
6577emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
6578 const OMPExecutableDirective &D) {
6579 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6581, __PRETTY_FUNCTION__))
6580 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6581, __PRETTY_FUNCTION__))
6581 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6581, __PRETTY_FUNCTION__))
;
6582 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6583 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6584, __PRETTY_FUNCTION__))
6584 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6584, __PRETTY_FUNCTION__))
;
6585 CGBuilderTy &Bld = CGF.Builder;
6586 switch (DirectiveKind) {
6587 case OMPD_target: {
6588 const auto *CS = D.getInnermostCapturedStmt();
6589 const auto *Body =
6590 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6591 const Stmt *ChildStmt =
6592 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6593 if (const auto *NestedDir =
6594 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6595 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6596 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6597 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6598 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6599 const Expr *NumTeams =
6600 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6601 llvm::Value *NumTeamsVal =
6602 CGF.EmitScalarExpr(NumTeams,
6603 /*IgnoreResultAssign*/ true);
6604 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6605 /*isSigned=*/true);
6606 }
6607 return Bld.getInt32(0);
6608 }
6609 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6610 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6611 return Bld.getInt32(1);
6612 return Bld.getInt32(0);
6613 }
6614 return nullptr;
6615 }
6616 case OMPD_target_teams:
6617 case OMPD_target_teams_distribute:
6618 case OMPD_target_teams_distribute_simd:
6619 case OMPD_target_teams_distribute_parallel_for:
6620 case OMPD_target_teams_distribute_parallel_for_simd: {
6621 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6622 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6623 const Expr *NumTeams =
6624 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6625 llvm::Value *NumTeamsVal =
6626 CGF.EmitScalarExpr(NumTeams,
6627 /*IgnoreResultAssign*/ true);
6628 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6629 /*isSigned=*/true);
6630 }
6631 return Bld.getInt32(0);
6632 }
6633 case OMPD_target_parallel:
6634 case OMPD_target_parallel_for:
6635 case OMPD_target_parallel_for_simd:
6636 case OMPD_target_simd:
6637 return Bld.getInt32(1);
6638 case OMPD_parallel:
6639 case OMPD_for:
6640 case OMPD_parallel_for:
6641 case OMPD_parallel_master:
6642 case OMPD_parallel_sections:
6643 case OMPD_for_simd:
6644 case OMPD_parallel_for_simd:
6645 case OMPD_cancel:
6646 case OMPD_cancellation_point:
6647 case OMPD_ordered:
6648 case OMPD_threadprivate:
6649 case OMPD_allocate:
6650 case OMPD_task:
6651 case OMPD_simd:
6652 case OMPD_tile:
6653 case OMPD_sections:
6654 case OMPD_section:
6655 case OMPD_single:
6656 case OMPD_master:
6657 case OMPD_critical:
6658 case OMPD_taskyield:
6659 case OMPD_barrier:
6660 case OMPD_taskwait:
6661 case OMPD_taskgroup:
6662 case OMPD_atomic:
6663 case OMPD_flush:
6664 case OMPD_depobj:
6665 case OMPD_scan:
6666 case OMPD_teams:
6667 case OMPD_target_data:
6668 case OMPD_target_exit_data:
6669 case OMPD_target_enter_data:
6670 case OMPD_distribute:
6671 case OMPD_distribute_simd:
6672 case OMPD_distribute_parallel_for:
6673 case OMPD_distribute_parallel_for_simd:
6674 case OMPD_teams_distribute:
6675 case OMPD_teams_distribute_simd:
6676 case OMPD_teams_distribute_parallel_for:
6677 case OMPD_teams_distribute_parallel_for_simd:
6678 case OMPD_target_update:
6679 case OMPD_declare_simd:
6680 case OMPD_declare_variant:
6681 case OMPD_begin_declare_variant:
6682 case OMPD_end_declare_variant:
6683 case OMPD_declare_target:
6684 case OMPD_end_declare_target:
6685 case OMPD_declare_reduction:
6686 case OMPD_declare_mapper:
6687 case OMPD_taskloop:
6688 case OMPD_taskloop_simd:
6689 case OMPD_master_taskloop:
6690 case OMPD_master_taskloop_simd:
6691 case OMPD_parallel_master_taskloop:
6692 case OMPD_parallel_master_taskloop_simd:
6693 case OMPD_requires:
6694 case OMPD_unknown:
6695 break;
6696 default:
6697 break;
6698 }
6699 llvm_unreachable("Unexpected directive kind.")::llvm::llvm_unreachable_internal("Unexpected directive kind."
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6699)
;
6700}
6701
6702static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6703 llvm::Value *DefaultThreadLimitVal) {
6704 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6705 CGF.getContext(), CS->getCapturedStmt());
6706 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6707 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
6708 llvm::Value *NumThreads = nullptr;
6709 llvm::Value *CondVal = nullptr;
6710 // Handle if clause. If if clause present, the number of threads is
6711 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6712 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6713 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6714 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6715 const OMPIfClause *IfClause = nullptr;
6716 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6717 if (C->getNameModifier() == OMPD_unknown ||
6718 C->getNameModifier() == OMPD_parallel) {
6719 IfClause = C;
6720 break;
6721 }
6722 }
6723 if (IfClause) {
6724 const Expr *Cond = IfClause->getCondition();
6725 bool Result;
6726 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6727 if (!Result)
6728 return CGF.Builder.getInt32(1);
6729 } else {
6730 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6731 if (const auto *PreInit =
6732 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6733 for (const auto *I : PreInit->decls()) {
6734 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6735 CGF.EmitVarDecl(cast<VarDecl>(*I));
6736 } else {
6737 CodeGenFunction::AutoVarEmission Emission =
6738 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6739 CGF.EmitAutoVarCleanups(Emission);
6740 }
6741 }
6742 }
6743 CondVal = CGF.EvaluateExprAsBool(Cond);
6744 }
6745 }
6746 }
6747 // Check the value of num_threads clause iff if clause was not specified
6748 // or is not evaluated to false.
6749 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6750 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6751 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6752 const auto *NumThreadsClause =
6753 Dir->getSingleClause<OMPNumThreadsClause>();
6754 CodeGenFunction::LexicalScope Scope(
6755 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6756 if (const auto *PreInit =
6757 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6758 for (const auto *I : PreInit->decls()) {
6759 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6760 CGF.EmitVarDecl(cast<VarDecl>(*I));
6761 } else {
6762 CodeGenFunction::AutoVarEmission Emission =
6763 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6764 CGF.EmitAutoVarCleanups(Emission);
6765 }
6766 }
6767 }
6768 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
6769 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
6770 /*isSigned=*/false);
6771 if (DefaultThreadLimitVal)
6772 NumThreads = CGF.Builder.CreateSelect(
6773 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6774 DefaultThreadLimitVal, NumThreads);
6775 } else {
6776 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6777 : CGF.Builder.getInt32(0);
6778 }
6779 // Process condition of the if clause.
6780 if (CondVal) {
6781 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6782 CGF.Builder.getInt32(1));
6783 }
6784 return NumThreads;
6785 }
6786 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6787 return CGF.Builder.getInt32(1);
6788 return DefaultThreadLimitVal;
6789 }
6790 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6791 : CGF.Builder.getInt32(0);
6792}
6793
6794/// Emit the number of threads for a target directive. Inspect the
6795/// thread_limit clause associated with a teams construct combined or closely
6796/// nested with the target directive.
6797///
6798/// Emit the num_threads clause for directives such as 'target parallel' that
6799/// have no associated teams construct.
6800///
6801/// Otherwise, return nullptr.
6802static llvm::Value *
6803emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
6804 const OMPExecutableDirective &D) {
6805 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6807, __PRETTY_FUNCTION__))
6806 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6807, __PRETTY_FUNCTION__))
6807 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6807, __PRETTY_FUNCTION__))
;
6808 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6809 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6810, __PRETTY_FUNCTION__))
6810 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 6810, __PRETTY_FUNCTION__))
;
6811 CGBuilderTy &Bld = CGF.Builder;
6812 llvm::Value *ThreadLimitVal = nullptr;
6813 llvm::Value *NumThreadsVal = nullptr;
6814 switch (DirectiveKind) {
6815 case OMPD_target: {
6816 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6817 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6818 return NumThreads;
6819 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6820 CGF.getContext(), CS->getCapturedStmt());
6821 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6822 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6823 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6824 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6825 const auto *ThreadLimitClause =
6826 Dir->getSingleClause<OMPThreadLimitClause>();
6827 CodeGenFunction::LexicalScope Scope(
6828 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6829 if (const auto *PreInit =
6830 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6831 for (const auto *I : PreInit->decls()) {
6832 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6833 CGF.EmitVarDecl(cast<VarDecl>(*I));
6834 } else {
6835 CodeGenFunction::AutoVarEmission Emission =
6836 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6837 CGF.EmitAutoVarCleanups(Emission);
6838 }
6839 }
6840 }
6841 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6842 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6843 ThreadLimitVal =
6844 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6845 }
6846 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6847 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6848 CS = Dir->getInnermostCapturedStmt();
6849 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6850 CGF.getContext(), CS->getCapturedStmt());
6851 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6852 }
6853 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6854 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6855 CS = Dir->getInnermostCapturedStmt();
6856 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6857 return NumThreads;
6858 }
6859 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6860 return Bld.getInt32(1);
6861 }
6862 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6863 }
6864 case OMPD_target_teams: {
6865 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6866 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6867 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6868 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6869 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6870 ThreadLimitVal =
6871 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6872 }
6873 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6874 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6875 return NumThreads;
6876 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6877 CGF.getContext(), CS->getCapturedStmt());
6878 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6879 if (Dir->getDirectiveKind() == OMPD_distribute) {
6880 CS = Dir->getInnermostCapturedStmt();
6881 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6882 return NumThreads;
6883 }
6884 }
6885 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6886 }
6887 case OMPD_target_teams_distribute:
6888 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6889 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6890 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6891 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6892 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6893 ThreadLimitVal =
6894 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6895 }
6896 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6897 case OMPD_target_parallel:
6898 case OMPD_target_parallel_for:
6899 case OMPD_target_parallel_for_simd:
6900 case OMPD_target_teams_distribute_parallel_for:
6901 case OMPD_target_teams_distribute_parallel_for_simd: {
6902 llvm::Value *CondVal = nullptr;
6903 // Handle if clause. If if clause present, the number of threads is
6904 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6905 if (D.hasClausesOfKind<OMPIfClause>()) {
6906 const OMPIfClause *IfClause = nullptr;
6907 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6908 if (C->getNameModifier() == OMPD_unknown ||
6909 C->getNameModifier() == OMPD_parallel) {
6910 IfClause = C;
6911 break;
6912 }
6913 }
6914 if (IfClause) {
6915 const Expr *Cond = IfClause->getCondition();
6916 bool Result;
6917 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6918 if (!Result)
6919 return Bld.getInt32(1);
6920 } else {
6921 CodeGenFunction::RunCleanupsScope Scope(CGF);
6922 CondVal = CGF.EvaluateExprAsBool(Cond);
6923 }
6924 }
6925 }
6926 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6927 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6928 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6929 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6930 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6931 ThreadLimitVal =
6932 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
6933 }
6934 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
6935 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
6936 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6937 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6938 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
6939 NumThreadsVal =
6940 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
6941 ThreadLimitVal = ThreadLimitVal
6942 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
6943 ThreadLimitVal),
6944 NumThreadsVal, ThreadLimitVal)
6945 : NumThreadsVal;
6946 }
6947 if (!ThreadLimitVal)
6948 ThreadLimitVal = Bld.getInt32(0);
6949 if (CondVal)
6950 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6951 return ThreadLimitVal;
6952 }
6953 case OMPD_target_teams_distribute_simd:
6954 case OMPD_target_simd:
6955 return Bld.getInt32(1);
6956 case OMPD_parallel:
6957 case OMPD_for:
6958 case OMPD_parallel_for:
6959 case OMPD_parallel_master:
6960 case OMPD_parallel_sections:
6961 case OMPD_for_simd:
6962 case OMPD_parallel_for_simd:
6963 case OMPD_cancel:
6964 case OMPD_cancellation_point:
6965 case OMPD_ordered:
6966 case OMPD_threadprivate:
6967 case OMPD_allocate:
6968 case OMPD_task:
6969 case OMPD_simd:
6970 case OMPD_tile:
6971 case OMPD_sections:
6972 case OMPD_section:
6973 case OMPD_single:
6974 case OMPD_master:
6975 case OMPD_critical:
6976 case OMPD_taskyield:
6977 case OMPD_barrier:
6978 case OMPD_taskwait:
6979 case OMPD_taskgroup:
6980 case OMPD_atomic:
6981 case OMPD_flush:
6982 case OMPD_depobj:
6983 case OMPD_scan:
6984 case OMPD_teams:
6985 case OMPD_target_data:
6986 case OMPD_target_exit_data:
6987 case OMPD_target_enter_data:
6988 case OMPD_distribute:
6989 case OMPD_distribute_simd:
6990 case OMPD_distribute_parallel_for:
6991 case OMPD_distribute_parallel_for_simd:
6992 case OMPD_teams_distribute:
6993 case OMPD_teams_distribute_simd:
6994 case OMPD_teams_distribute_parallel_for:
6995 case OMPD_teams_distribute_parallel_for_simd:
6996 case OMPD_target_update:
6997 case OMPD_declare_simd:
6998 case OMPD_declare_variant:
6999 case OMPD_begin_declare_variant:
7000 case OMPD_end_declare_variant:
7001 case OMPD_declare_target:
7002 case OMPD_end_declare_target:
7003 case OMPD_declare_reduction:
7004 case OMPD_declare_mapper:
7005 case OMPD_taskloop:
7006 case OMPD_taskloop_simd:
7007 case OMPD_master_taskloop:
7008 case OMPD_master_taskloop_simd:
7009 case OMPD_parallel_master_taskloop:
7010 case OMPD_parallel_master_taskloop_simd:
7011 case OMPD_requires:
7012 case OMPD_unknown:
7013 break;
7014 default:
7015 break;
7016 }
7017 llvm_unreachable("Unsupported directive kind.")::llvm::llvm_unreachable_internal("Unsupported directive kind."
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7017)
;
7018}
7019
7020namespace {
7021LLVM_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^=
;
7022
7023// Utility to handle information from clauses associated with a given
7024// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7025// It provides a convenient interface to obtain the information and generate
7026// code for that information.
7027class MappableExprsHandler {
7028public:
7029 /// Values for bit flags used to specify the mapping type for
7030 /// offloading.
7031 enum OpenMPOffloadMappingFlags : uint64_t {
7032 /// No flags
7033 OMP_MAP_NONE = 0x0,
7034 /// Allocate memory on the device and move data from host to device.
7035 OMP_MAP_TO = 0x01,
7036 /// Allocate memory on the device and move data from device to host.
7037 OMP_MAP_FROM = 0x02,
7038 /// Always perform the requested mapping action on the element, even
7039 /// if it was already mapped before.
7040 OMP_MAP_ALWAYS = 0x04,
7041 /// Delete the element from the device environment, ignoring the
7042 /// current reference count associated with the element.
7043 OMP_MAP_DELETE = 0x08,
7044 /// The element being mapped is a pointer-pointee pair; both the
7045 /// pointer and the pointee should be mapped.
7046 OMP_MAP_PTR_AND_OBJ = 0x10,
7047 /// This flags signals that the base address of an entry should be
7048 /// passed to the target kernel as an argument.
7049 OMP_MAP_TARGET_PARAM = 0x20,
7050 /// Signal that the runtime library has to return the device pointer
7051 /// in the current position for the data being mapped. Used when we have the
7052 /// use_device_ptr or use_device_addr clause.
7053 OMP_MAP_RETURN_PARAM = 0x40,
7054 /// This flag signals that the reference being passed is a pointer to
7055 /// private data.
7056 OMP_MAP_PRIVATE = 0x80,
7057 /// Pass the element to the device by value.
7058 OMP_MAP_LITERAL = 0x100,
7059 /// Implicit map
7060 OMP_MAP_IMPLICIT = 0x200,
7061 /// Close is a hint to the runtime to allocate memory close to
7062 /// the target device.
7063 OMP_MAP_CLOSE = 0x400,
7064 /// 0x800 is reserved for compatibility with XLC.
7065 /// Produce a runtime error if the data is not already allocated.
7066 OMP_MAP_PRESENT = 0x1000,
7067 /// Signal that the runtime library should use args as an array of
7068 /// descriptor_dim pointers and use args_size as dims. Used when we have
7069 /// non-contiguous list items in target update directive
7070 OMP_MAP_NON_CONTIG = 0x100000000000,
7071 /// The 16 MSBs of the flags indicate whether the entry is member of some
7072 /// struct/class.
7073 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7074 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF)LLVM_BITMASK_LARGEST_ENUMERATOR = OMP_MAP_MEMBER_OF,
7075 };
7076
7077 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7078 static unsigned getFlagMemberOffset() {
7079 unsigned Offset = 0;
7080 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7081 Remain = Remain >> 1)
7082 Offset++;
7083 return Offset;
7084 }
7085
7086 /// Class that holds debugging information for a data mapping to be passed to
7087 /// the runtime library.
7088 class MappingExprInfo {
7089 /// The variable declaration used for the data mapping.
7090 const ValueDecl *MapDecl = nullptr;
7091 /// The original expression used in the map clause, or null if there is
7092 /// none.
7093 const Expr *MapExpr = nullptr;
7094
7095 public:
7096 MappingExprInfo(const ValueDecl *MapDecl, const Expr *MapExpr = nullptr)
7097 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7098
7099 const ValueDecl *getMapDecl() const { return MapDecl; }
7100 const Expr *getMapExpr() const { return MapExpr; }
7101 };
7102
7103 /// Class that associates information with a base pointer to be passed to the
7104 /// runtime library.
7105 class BasePointerInfo {
7106 /// The base pointer.
7107 llvm::Value *Ptr = nullptr;
7108 /// The base declaration that refers to this device pointer, or null if
7109 /// there is none.
7110 const ValueDecl *DevPtrDecl = nullptr;
7111
7112 public:
7113 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7114 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7115 llvm::Value *operator*() const { return Ptr; }
7116 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7117 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7118 };
7119
7120 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7121 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7122 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7123 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7124 using MapMappersArrayTy = SmallVector<const ValueDecl *, 4>;
7125 using MapDimArrayTy = SmallVector<uint64_t, 4>;
7126 using MapNonContiguousArrayTy = SmallVector<MapValuesArrayTy, 4>;
7127
7128 /// This structure contains combined information generated for mappable
7129 /// clauses, including base pointers, pointers, sizes, map types, user-defined
7130 /// mappers, and non-contiguous information.
7131 struct MapCombinedInfoTy {
7132 struct StructNonContiguousInfo {
7133 bool IsNonContiguous = false;
7134 MapDimArrayTy Dims;
7135 MapNonContiguousArrayTy Offsets;
7136 MapNonContiguousArrayTy Counts;
7137 MapNonContiguousArrayTy Strides;
7138 };
7139 MapExprsArrayTy Exprs;
7140 MapBaseValuesArrayTy BasePointers;
7141 MapValuesArrayTy Pointers;
7142 MapValuesArrayTy Sizes;
7143 MapFlagsArrayTy Types;
7144 MapMappersArrayTy Mappers;
7145 StructNonContiguousInfo NonContigInfo;
7146
7147 /// Append arrays in \a CurInfo.
7148 void append(MapCombinedInfoTy &CurInfo) {
7149 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7150 BasePointers.append(CurInfo.BasePointers.begin(),
7151 CurInfo.BasePointers.end());
7152 Pointers.append(CurInfo.Pointers.begin(), CurInfo.Pointers.end());
7153 Sizes.append(CurInfo.Sizes.begin(), CurInfo.Sizes.end());
7154 Types.append(CurInfo.Types.begin(), CurInfo.Types.end());
7155 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7156 NonContigInfo.Dims.append(CurInfo.NonContigInfo.Dims.begin(),
7157 CurInfo.NonContigInfo.Dims.end());
7158 NonContigInfo.Offsets.append(CurInfo.NonContigInfo.Offsets.begin(),
7159 CurInfo.NonContigInfo.Offsets.end());
7160 NonContigInfo.Counts.append(CurInfo.NonContigInfo.Counts.begin(),
7161 CurInfo.NonContigInfo.Counts.end());
7162 NonContigInfo.Strides.append(CurInfo.NonContigInfo.Strides.begin(),
7163 CurInfo.NonContigInfo.Strides.end());
7164 }
7165 };
7166
7167 /// Map between a struct and the its lowest & highest elements which have been
7168 /// mapped.
7169 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7170 /// HE(FieldIndex, Pointer)}
7171 struct StructRangeInfoTy {
7172 MapCombinedInfoTy PreliminaryMapData;
7173 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7174 0, Address::invalid()};
7175 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7176 0, Address::invalid()};
7177 Address Base = Address::invalid();
7178 Address LB = Address::invalid();
7179 bool IsArraySection = false;
7180 bool HasCompleteRecord = false;
7181 };
7182
7183private:
7184 /// Kind that defines how a device pointer has to be returned.
7185 struct MapInfo {
7186 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7187 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
7188 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7189 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7190 bool ReturnDevicePointer = false;
7191 bool IsImplicit = false;
7192 const ValueDecl *Mapper = nullptr;
7193 const Expr *VarRef = nullptr;
7194 bool ForDeviceAddr = false;
7195
7196 MapInfo() = default;
7197 MapInfo(
7198 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
7199 OpenMPMapClauseKind MapType,
7200 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7201 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7202 bool ReturnDevicePointer, bool IsImplicit,
7203 const ValueDecl *Mapper = nullptr, const Expr *VarRef = nullptr,
7204 bool ForDeviceAddr = false)
7205 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7206 MotionModifiers(MotionModifiers),
7207 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7208 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {}
7209 };
7210
7211 /// If use_device_ptr or use_device_addr is used on a decl which is a struct
7212 /// member and there is no map information about it, then emission of that
7213 /// entry is deferred until the whole struct has been processed.
7214 struct DeferredDevicePtrEntryTy {
7215 const Expr *IE = nullptr;
7216 const ValueDecl *VD = nullptr;
7217 bool ForDeviceAddr = false;
7218
7219 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD,
7220 bool ForDeviceAddr)
7221 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {}
7222 };
7223
7224 /// The target directive from where the mappable clauses were extracted. It
7225 /// is either a executable directive or a user-defined mapper directive.
7226 llvm::PointerUnion<const OMPExecutableDirective *,
7227 const OMPDeclareMapperDecl *>
7228 CurDir;
7229
7230 /// Function the directive is being generated for.
7231 CodeGenFunction &CGF;
7232
7233 /// Set of all first private variables in the current directive.
7234 /// bool data is set to true if the variable is implicitly marked as
7235 /// firstprivate, false otherwise.
7236 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
7237
7238 /// Map between device pointer declarations and their expression components.
7239 /// The key value for declarations in 'this' is null.
7240 llvm::DenseMap<
7241 const ValueDecl *,
7242 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7243 DevPointersMap;
7244
7245 llvm::Value *getExprTypeSize(const Expr *E) const {
7246 QualType ExprTy = E->getType().getCanonicalType();
7247
7248 // Calculate the size for array shaping expression.
7249 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7250 llvm::Value *Size =
7251 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType());
7252 for (const Expr *SE : OAE->getDimensions()) {
7253 llvm::Value *Sz = CGF.EmitScalarExpr(SE);
7254 Sz = CGF.EmitScalarConversion(Sz, SE->getType(),
7255 CGF.getContext().getSizeType(),
7256 SE->getExprLoc());
7257 Size = CGF.Builder.CreateNUWMul(Size, Sz);
7258 }
7259 return Size;
7260 }
7261
7262 // Reference types are ignored for mapping purposes.
7263 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
7264 ExprTy = RefTy->getPointeeType().getCanonicalType();
7265
7266 // Given that an array section is considered a built-in type, we need to
7267 // do the calculation based on the length of the section instead of relying
7268 // on CGF.getTypeSize(E->getType()).
7269 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7270 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7271 OAE->getBase()->IgnoreParenImpCasts())
7272 .getCanonicalType();
7273
7274 // If there is no length associated with the expression and lower bound is
7275 // not specified too, that means we are using the whole length of the
7276 // base.
7277 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7278 !OAE->getLowerBound())
7279 return CGF.getTypeSize(BaseTy);
7280
7281 llvm::Value *ElemSize;
7282 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
7283 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
7284 } else {
7285 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
7286 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7286, __PRETTY_FUNCTION__))
;
7287 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7288 }
7289
7290 // If we don't have a length at this point, that is because we have an
7291 // array section with a single element.
7292 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7293 return ElemSize;
7294
7295 if (const Expr *LenExpr = OAE->getLength()) {
7296 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7297 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7298 CGF.getContext().getSizeType(),
7299 LenExpr->getExprLoc());
7300 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7301 }
7302 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&((!OAE->getLength() && OAE->getColonLocFirst().
isValid() && OAE->getLowerBound() && "expected array_section[lb:]."
) ? static_cast<void> (0) : __assert_fail ("!OAE->getLength() && OAE->getColonLocFirst().isValid() && OAE->getLowerBound() && \"expected array_section[lb:].\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7303, __PRETTY_FUNCTION__))
7303 OAE->getLowerBound() && "expected array_section[lb:].")((!OAE->getLength() && OAE->getColonLocFirst().
isValid() && OAE->getLowerBound() && "expected array_section[lb:]."
) ? static_cast<void> (0) : __assert_fail ("!OAE->getLength() && OAE->getColonLocFirst().isValid() && OAE->getLowerBound() && \"expected array_section[lb:].\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7303, __PRETTY_FUNCTION__))
;
7304 // Size = sizetype - lb * elemtype;
7305 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7306 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7307 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7308 CGF.getContext().getSizeType(),
7309 OAE->getLowerBound()->getExprLoc());
7310 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7311 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7312 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7313 LengthVal = CGF.Builder.CreateSelect(
7314 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7315 return LengthVal;
7316 }
7317 return CGF.getTypeSize(ExprTy);
7318 }
7319
7320 /// Return the corresponding bits for a given map clause modifier. Add
7321 /// a flag marking the map as a pointer if requested. Add a flag marking the
7322 /// map as the first one of a series of maps that relate to the same map
7323 /// expression.
7324 OpenMPOffloadMappingFlags getMapTypeBits(
7325 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7326 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit,
7327 bool AddPtrFlag, bool AddIsTargetParamFlag, bool IsNonContiguous) const {
7328 OpenMPOffloadMappingFlags Bits =
7329 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
7330 switch (MapType) {
7331 case OMPC_MAP_alloc:
7332 case OMPC_MAP_release:
7333 // alloc and release is the default behavior in the runtime library, i.e.
7334 // if we don't pass any bits alloc/release that is what the runtime is
7335 // going to do. Therefore, we don't need to signal anything for these two
7336 // type modifiers.
7337 break;
7338 case OMPC_MAP_to:
7339 Bits |= OMP_MAP_TO;
7340 break;
7341 case OMPC_MAP_from:
7342 Bits |= OMP_MAP_FROM;
7343 break;
7344 case OMPC_MAP_tofrom:
7345 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
7346 break;
7347 case OMPC_MAP_delete:
7348 Bits |= OMP_MAP_DELETE;
7349 break;
7350 case OMPC_MAP_unknown:
7351 llvm_unreachable("Unexpected map type!")::llvm::llvm_unreachable_internal("Unexpected map type!", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7351)
;
7352 }
7353 if (AddPtrFlag)
7354 Bits |= OMP_MAP_PTR_AND_OBJ;
7355 if (AddIsTargetParamFlag)
7356 Bits |= OMP_MAP_TARGET_PARAM;
7357 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7358 != MapModifiers.end())
7359 Bits |= OMP_MAP_ALWAYS;
7360 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7361 != MapModifiers.end())
7362 Bits |= OMP_MAP_CLOSE;
7363 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_present) !=
7364 MapModifiers.end() ||
7365 llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present) !=
7366 MotionModifiers.end())
7367 Bits |= OMP_MAP_PRESENT;
7368 if (IsNonContiguous)
7369 Bits |= OMP_MAP_NON_CONTIG;
7370 return Bits;
7371 }
7372
7373 /// Return true if the provided expression is a final array section. A
7374 /// final array section, is one whose length can't be proved to be one.
7375 bool isFinalArraySectionExpression(const Expr *E) const {
7376 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
7377
7378 // It is not an array section and therefore not a unity-size one.
7379 if (!OASE)
7380 return false;
7381
7382 // An array section with no colon always refer to a single element.
7383 if (OASE->getColonLocFirst().isInvalid())
7384 return false;
7385
7386 const Expr *Length = OASE->getLength();
7387
7388 // If we don't have a length we have to check if the array has size 1
7389 // for this dimension. Also, we should always expect a length if the
7390 // base type is pointer.
7391 if (!Length) {
7392 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7393 OASE->getBase()->IgnoreParenImpCasts())
7394 .getCanonicalType();
7395 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
7396 return ATy->getSize().getSExtValue() != 1;
7397 // If we don't have a constant dimension length, we have to consider
7398 // the current section as having any size, so it is not necessarily
7399 // unitary. If it happen to be unity size, that's user fault.
7400 return true;
7401 }
7402
7403 // Check if the length evaluates to 1.
7404 Expr::EvalResult Result;
7405 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
7406 return true; // Can have more that size 1.
7407
7408 llvm::APSInt ConstLength = Result.Val.getInt();
7409 return ConstLength.getSExtValue() != 1;
7410 }
7411
7412 /// Generate the base pointers, section pointers, sizes, map type bits, and
7413 /// user-defined mappers (all included in \a CombinedInfo) for the provided
7414 /// map type, map or motion modifiers, and expression components.
7415 /// \a IsFirstComponent should be set to true if the provided set of
7416 /// components is the first associated with a capture.
7417 void generateInfoForComponentList(
7418 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7419 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7420 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
7421 MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct,
7422 bool IsFirstComponentList, bool IsImplicit,
7423 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false,
7424 const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr,
7425 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7426 OverlappedElements = llvm::None) const {
7427 // The following summarizes what has to be generated for each map and the
7428 // types below. The generated information is expressed in this order:
7429 // base pointer, section pointer, size, flags
7430 // (to add to the ones that come from the map type and modifier).
7431 //
7432 // double d;
7433 // int i[100];
7434 // float *p;
7435 //
7436 // struct S1 {
7437 // int i;
7438 // float f[50];
7439 // }
7440 // struct S2 {
7441 // int i;
7442 // float f[50];
7443 // S1 s;
7444 // double *p;
7445 // struct S2 *ps;
7446 // int &ref;
7447 // }
7448 // S2 s;
7449 // S2 *ps;
7450 //
7451 // map(d)
7452 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
7453 //
7454 // map(i)
7455 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
7456 //
7457 // map(i[1:23])
7458 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
7459 //
7460 // map(p)
7461 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
7462 //
7463 // map(p[1:24])
7464 // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ
7465 // in unified shared memory mode or for local pointers
7466 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
7467 //
7468 // map(s)
7469 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
7470 //
7471 // map(s.i)
7472 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
7473 //
7474 // map(s.s.f)
7475 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
7476 //
7477 // map(s.p)
7478 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
7479 //
7480 // map(to: s.p[:22])
7481 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7482 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7483 // &(s.p), &(s.p[0]), 22*sizeof(double),
7484 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7485 // (*) alloc space for struct members, only this is a target parameter
7486 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7487 // optimizes this entry out, same in the examples below)
7488 // (***) map the pointee (map: to)
7489 //
7490 // map(to: s.ref)
7491 // &s, &(s.ref), sizeof(int*), TARGET_PARAM (*)
7492 // &s, &(s.ref), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7493 // (*) alloc space for struct members, only this is a target parameter
7494 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7495 // optimizes this entry out, same in the examples below)
7496 // (***) map the pointee (map: to)
7497 //
7498 // map(s.ps)
7499 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
7500 //
7501 // map(from: s.ps->s.i)
7502 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7503 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7504 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7505 //
7506 // map(to: s.ps->ps)
7507 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7508 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7509 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
7510 //
7511 // map(s.ps->ps->ps)
7512 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7513 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7514 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7515 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
7516 //
7517 // map(to: s.ps->ps->s.f[:22])
7518 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7519 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7520 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7521 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7522 //
7523 // map(ps)
7524 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
7525 //
7526 // map(ps->i)
7527 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
7528 //
7529 // map(ps->s.f)
7530 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
7531 //
7532 // map(from: ps->p)
7533 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
7534 //
7535 // map(to: ps->p[:22])
7536 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7537 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7538 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
7539 //
7540 // map(ps->ps)
7541 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
7542 //
7543 // map(from: ps->ps->s.i)
7544 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7545 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7546 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7547 //
7548 // map(from: ps->ps->ps)
7549 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7550 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7551 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7552 //
7553 // map(ps->ps->ps->ps)
7554 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7555 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7556 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7557 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
7558 //
7559 // map(to: ps->ps->ps->s.f[:22])
7560 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7561 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7562 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7563 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7564 //
7565 // map(to: s.f[:22]) map(from: s.p[:33])
7566 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7567 // sizeof(double*) (**), TARGET_PARAM
7568 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7569 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7570 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7571 // (*) allocate contiguous space needed to fit all mapped members even if
7572 // we allocate space for members not mapped (in this example,
7573 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7574 // them as well because they fall between &s.f[0] and &s.p)
7575 //
7576 // map(from: s.f[:22]) map(to: ps->p[:33])
7577 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7578 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7579 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7580 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7581 // (*) the struct this entry pertains to is the 2nd element in the list of
7582 // arguments, hence MEMBER_OF(2)
7583 //
7584 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7585 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7586 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7587 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7588 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7589 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7590 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7591 // (*) the struct this entry pertains to is the 4th element in the list
7592 // of arguments, hence MEMBER_OF(4)
7593
7594 // Track if the map information being generated is the first for a capture.
7595 bool IsCaptureFirstInfo = IsFirstComponentList;
7596 // When the variable is on a declare target link or in a to clause with
7597 // unified memory, a reference is needed to hold the host/device address
7598 // of the variable.
7599 bool RequiresReference = false;
7600
7601 // Scan the components from the base to the complete expression.
7602 auto CI = Components.rbegin();
7603 auto CE = Components.rend();
7604 auto I = CI;
7605
7606 // Track if the map information being generated is the first for a list of
7607 // components.
7608 bool IsExpressionFirstInfo = true;
7609 bool FirstPointerInComplexData = false;
7610 Address BP = Address::invalid();
7611 const Expr *AssocExpr = I->getAssociatedExpression();
7612 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
1
Assuming 'AssocExpr' is not a 'ArraySubscriptExpr'
7613 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
2
Assuming 'AssocExpr' is not a 'OMPArraySectionExpr'
7614 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
3
Assuming 'AssocExpr' is not a 'OMPArrayShapingExpr'
7615
7616 if (isa<MemberExpr>(AssocExpr)) {
4
Assuming 'AssocExpr' is a 'MemberExpr'
5
Taking true branch
7617 // The base is the 'this' pointer. The content of the pointer is going
7618 // to be the base of the field being mapped.
7619 BP = CGF.LoadCXXThisAddress();
7620 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7621 (OASE &&
7622 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7623 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
7624 } else if (OAShE &&
7625 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) {
7626 BP = Address(
7627 CGF.EmitScalarExpr(OAShE->getBase()),
7628 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType()));
7629 } else {
7630 // The base is the reference to the variable.
7631 // BP = &Var.
7632 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
7633 if (const auto *VD =
7634 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7635 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7636 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7637 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7638 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7639 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7640 RequiresReference = true;
7641 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
7642 }
7643 }
7644 }
7645
7646 // If the variable is a pointer and is being dereferenced (i.e. is not
7647 // the last component), the base has to be the pointer itself, not its
7648 // reference. References are ignored for mapping purposes.
7649 QualType Ty =
7650 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7651 if (Ty->isAnyPointerType() && std::next(I) != CE) {
7652 // No need to generate individual map information for the pointer, it
7653 // can be associated with the combined storage if shared memory mode is
7654 // active or the base declaration is not global variable.
7655 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7656 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
7657 !VD || VD->hasLocalStorage())
7658 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
7659 else
7660 FirstPointerInComplexData = true;
7661 ++I;
7662 }
7663 }
7664
7665 // Track whether a component of the list should be marked as MEMBER_OF some
7666 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7667 // in a component list should be marked as MEMBER_OF, all subsequent entries
7668 // do not belong to the base struct. E.g.
7669 // struct S2 s;
7670 // s.ps->ps->ps->f[:]
7671 // (1) (2) (3) (4)
7672 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7673 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7674 // is the pointee of ps(2) which is not member of struct s, so it should not
7675 // be marked as such (it is still PTR_AND_OBJ).
7676 // The variable is initialized to false so that PTR_AND_OBJ entries which
7677 // are not struct members are not considered (e.g. array of pointers to
7678 // data).
7679 bool ShouldBeMemberOf = false;
7680
7681 // Variable keeping track of whether or not we have encountered a component
7682 // in the component list which is a member expression. Useful when we have a
7683 // pointer or a final array section, in which case it is the previous
7684 // component in the list which tells us whether we have a member expression.
7685 // E.g. X.f[:]
7686 // While processing the final array section "[:]" it is "f" which tells us
7687 // whether we are dealing with a member of a declared struct.
7688 const MemberExpr *EncounteredME = nullptr;
7689
7690 // Track for the total number of dimension. Start from one for the dummy
7691 // dimension.
7692 uint64_t DimSize = 1;
7693
7694 bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous;
7695 bool IsPrevMemberReference = false;
7696
7697 for (; I != CE; ++I) {
6
Calling 'operator!=<const clang::OMPClauseMappableExprCommon::MappableComponent *>'
12
Returning from 'operator!=<const clang::OMPClauseMappableExprCommon::MappableComponent *>'
13
Loop condition is false. Execution continues on line 8004
7698 // If the current component is member of a struct (parent struct) mark it.
7699 if (!EncounteredME) {
7700 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7701 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7702 // as MEMBER_OF the parent struct.
7703 if (EncounteredME) {
7704 ShouldBeMemberOf = true;
7705 // Do not emit as complex pointer if this is actually not array-like
7706 // expression.
7707 if (FirstPointerInComplexData) {
7708 QualType Ty = std::prev(I)
7709 ->getAssociatedDeclaration()
7710 ->getType()
7711 .getNonReferenceType();
7712 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
7713 FirstPointerInComplexData = false;
7714 }
7715 }
7716 }
7717
7718 auto Next = std::next(I);
7719
7720 // We need to generate the addresses and sizes if this is the last
7721 // component, if the component is a pointer or if it is an array section
7722 // whose length can't be proved to be one. If this is a pointer, it
7723 // becomes the base address for the following components.
7724
7725 // A final array section, is one whose length can't be proved to be one.
7726 // If the map item is non-contiguous then we don't treat any array section
7727 // as final array section.
7728 bool IsFinalArraySection =
7729 !IsNonContiguous &&
7730 isFinalArraySectionExpression(I->getAssociatedExpression());
7731
7732 // If we have a declaration for the mapping use that, otherwise use
7733 // the base declaration of the map clause.
7734 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
7735 ? I->getAssociatedDeclaration()
7736 : BaseDecl;
7737
7738 // Get information on whether the element is a pointer. Have to do a
7739 // special treatment for array sections given that they are built-in
7740 // types.
7741 const auto *OASE =
7742 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7743 const auto *OAShE =
7744 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
7745 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
7746 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7747 bool IsPointer =
7748 OAShE ||
7749 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7750 .getCanonicalType()
7751 ->isAnyPointerType()) ||
7752 I->getAssociatedExpression()->getType()->isAnyPointerType();
7753 bool IsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) &&
7754 MapDecl &&
7755 MapDecl->getType()->isLValueReferenceType();
7756 bool IsNonDerefPointer = IsPointer && !UO && !BO && !IsNonContiguous;
7757
7758 if (OASE)
7759 ++DimSize;
7760
7761 if (Next == CE || IsMemberReference || IsNonDerefPointer ||
7762 IsFinalArraySection) {
7763 // If this is not the last component, we expect the pointer to be
7764 // associated with an array expression or member expression.
7765 assert((Next == CE ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression
()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression
()) || isa<UnaryOperator>(Next->getAssociatedExpression
()) || isa<BinaryOperator>(Next->getAssociatedExpression
())) && "Unexpected expression") ? static_cast<void
> (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7772, __PRETTY_FUNCTION__))
7766 isa<MemberExpr>(Next->getAssociatedExpression()) ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression
()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression
()) || isa<UnaryOperator>(Next->getAssociatedExpression
()) || isa<BinaryOperator>(Next->getAssociatedExpression
())) && "Unexpected expression") ? static_cast<void
> (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7772, __PRETTY_FUNCTION__))
7767 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression
()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression
()) || isa<UnaryOperator>(Next->getAssociatedExpression
()) || isa<BinaryOperator>(Next->getAssociatedExpression
())) && "Unexpected expression") ? static_cast<void
> (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7772, __PRETTY_FUNCTION__))
7768 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression
()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression
()) || isa<UnaryOperator>(Next->getAssociatedExpression
()) || isa<BinaryOperator>(Next->getAssociatedExpression
())) && "Unexpected expression") ? static_cast<void
> (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7772, __PRETTY_FUNCTION__))
7769 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression
()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression
()) || isa<UnaryOperator>(Next->getAssociatedExpression
()) || isa<BinaryOperator>(Next->getAssociatedExpression
())) && "Unexpected expression") ? static_cast<void
> (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7772, __PRETTY_FUNCTION__))
7770 isa<UnaryOperator>(Next->getAssociatedExpression()) ||(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression
()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression
()) || isa<UnaryOperator>(Next->getAssociatedExpression
()) || isa<BinaryOperator>(Next->getAssociatedExpression
())) && "Unexpected expression") ? static_cast<void
> (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7772, __PRETTY_FUNCTION__))
7771 isa<BinaryOperator>(Next->getAssociatedExpression())) &&(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression
()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression
()) || isa<UnaryOperator>(Next->getAssociatedExpression
()) || isa<BinaryOperator>(Next->getAssociatedExpression
())) && "Unexpected expression") ? static_cast<void
> (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7772, __PRETTY_FUNCTION__))
7772 "Unexpected expression")(((Next == CE || isa<MemberExpr>(Next->getAssociatedExpression
()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression
()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression
()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression
()) || isa<UnaryOperator>(Next->getAssociatedExpression
()) || isa<BinaryOperator>(Next->getAssociatedExpression
())) && "Unexpected expression") ? static_cast<void
> (0) : __assert_fail ("(Next == CE || isa<MemberExpr>(Next->getAssociatedExpression()) || isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || isa<UnaryOperator>(Next->getAssociatedExpression()) || isa<BinaryOperator>(Next->getAssociatedExpression())) && \"Unexpected expression\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7772, __PRETTY_FUNCTION__))
;
7773
7774 Address LB = Address::invalid();
7775 Address LowestElem = Address::invalid();
7776 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
7777 const MemberExpr *E) {
7778 const Expr *BaseExpr = E->getBase();
7779 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a
7780 // scalar.
7781 LValue BaseLV;
7782 if (E->isArrow()) {
7783 LValueBaseInfo BaseInfo;
7784 TBAAAccessInfo TBAAInfo;
7785 Address Addr =
7786 CGF.EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo);
7787 QualType PtrTy = BaseExpr->getType()->getPointeeType();
7788 BaseLV = CGF.MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo);
7789 } else {
7790 BaseLV = CGF.EmitOMPSharedLValue(BaseExpr);
7791 }
7792 return BaseLV;
7793 };
7794 if (OAShE) {
7795 LowestElem = LB = Address(CGF.EmitScalarExpr(OAShE->getBase()),
7796 CGF.getContext().getTypeAlignInChars(
7797 OAShE->getBase()->getType()));
7798 } else if (IsMemberReference) {
7799 const auto *ME = cast<MemberExpr>(I->getAssociatedExpression());
7800 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7801 LowestElem = CGF.EmitLValueForFieldInitialization(
7802 BaseLVal, cast<FieldDecl>(MapDecl))
7803 .getAddress(CGF);
7804 LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType())
7805 .getAddress(CGF);
7806 } else {
7807 LowestElem = LB =
7808 CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
7809 .getAddress(CGF);
7810 }
7811
7812 // If this component is a pointer inside the base struct then we don't
7813 // need to create any entry for it - it will be combined with the object
7814 // it is pointing to into a single PTR_AND_OBJ entry.
7815 bool IsMemberPointerOrAddr =
7816 EncounteredME &&
7817 (((IsPointer || ForDeviceAddr) &&
7818 I->getAssociatedExpression() == EncounteredME) ||
7819 (IsPrevMemberReference && !IsPointer) ||
7820 (IsMemberReference && Next != CE &&
7821 !Next->getAssociatedExpression()->getType()->isPointerType()));
7822 if (!OverlappedElements.empty() && Next == CE) {
7823 // Handle base element with the info for overlapped elements.
7824 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7824, __PRETTY_FUNCTION__))
;
7825 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7826, __PRETTY_FUNCTION__))
7826 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7826, __PRETTY_FUNCTION__))
;
7827 // Mark the whole struct as the struct that requires allocation on the
7828 // device.
7829 PartialStruct.LowestElem = {0, LowestElem};
7830 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7831 I->getAssociatedExpression()->getType());
7832 Address HB = CGF.Builder.CreateConstGEP(
7833 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LowestElem,
7834 CGF.VoidPtrTy),
7835 TypeSize.getQuantity() - 1);
7836 PartialStruct.HighestElem = {
7837 std::numeric_limits<decltype(
7838 PartialStruct.HighestElem.first)>::max(),
7839 HB};
7840 PartialStruct.Base = BP;
7841 PartialStruct.LB = LB;
7842 assert(((PartialStruct.PreliminaryMapData.BasePointers.empty() &&
"Overlapped elements must be used only once for the variable."
) ? static_cast<void> (0) : __assert_fail ("PartialStruct.PreliminaryMapData.BasePointers.empty() && \"Overlapped elements must be used only once for the variable.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7844, __PRETTY_FUNCTION__))
7843 PartialStruct.PreliminaryMapData.BasePointers.empty() &&((PartialStruct.PreliminaryMapData.BasePointers.empty() &&
"Overlapped elements must be used only once for the variable."
) ? static_cast<void> (0) : __assert_fail ("PartialStruct.PreliminaryMapData.BasePointers.empty() && \"Overlapped elements must be used only once for the variable.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7844, __PRETTY_FUNCTION__))
7844 "Overlapped elements must be used only once for the variable.")((PartialStruct.PreliminaryMapData.BasePointers.empty() &&
"Overlapped elements must be used only once for the variable."
) ? static_cast<void> (0) : __assert_fail ("PartialStruct.PreliminaryMapData.BasePointers.empty() && \"Overlapped elements must be used only once for the variable.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7844, __PRETTY_FUNCTION__))
;
7845 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
7846 // Emit data for non-overlapped data.
7847 OpenMPOffloadMappingFlags Flags =
7848 OMP_MAP_MEMBER_OF |
7849 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
7850 /*AddPtrFlag=*/false,
7851 /*AddIsTargetParamFlag=*/false, IsNonContiguous);
7852 llvm::Value *Size = nullptr;
7853 // Do bitcopy of all non-overlapped structure elements.
7854 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7855 Component : OverlappedElements) {
7856 Address ComponentLB = Address::invalid();
7857 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7858 Component) {
7859 if (const ValueDecl *VD = MC.getAssociatedDeclaration()) {
7860 const auto *FD = dyn_cast<FieldDecl>(VD);
7861 if (FD && FD->getType()->isLValueReferenceType()) {
7862 const auto *ME =
7863 cast<MemberExpr>(MC.getAssociatedExpression());
7864 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7865 ComponentLB =
7866 CGF.EmitLValueForFieldInitialization(BaseLVal, FD)
7867 .getAddress(CGF);
7868 } else {
7869 ComponentLB =
7870 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7871 .getAddress(CGF);
7872 }
7873 Size = CGF.Builder.CreatePtrDiff(
7874 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7875 CGF.EmitCastToVoidPtr(LB.getPointer()));
7876 break;
7877 }
7878 }
7879 assert(Size && "Failed to determine structure size")((Size && "Failed to determine structure size") ? static_cast
<void> (0) : __assert_fail ("Size && \"Failed to determine structure size\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 7879, __PRETTY_FUNCTION__))
;
7880 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7881 CombinedInfo.BasePointers.push_back(BP.getPointer());
7882 CombinedInfo.Pointers.push_back(LB.getPointer());
7883 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
7884 Size, CGF.Int64Ty, /*isSigned=*/true));
7885 CombinedInfo.Types.push_back(Flags);
7886 CombinedInfo.Mappers.push_back(nullptr);
7887 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7888 : 1);
7889 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
7890 }
7891 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7892 CombinedInfo.BasePointers.push_back(BP.getPointer());
7893 CombinedInfo.Pointers.push_back(LB.getPointer());
7894 Size = CGF.Builder.CreatePtrDiff(
7895 CGF.Builder.CreateConstGEP(HB, 1).getPointer(),
7896 CGF.EmitCastToVoidPtr(LB.getPointer()));
7897 CombinedInfo.Sizes.push_back(
7898 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
7899 CombinedInfo.Types.push_back(Flags);
7900 CombinedInfo.Mappers.push_back(nullptr);
7901 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7902 : 1);
7903 break;
7904 }
7905 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
7906 if (!IsMemberPointerOrAddr ||
7907 (Next == CE && MapType != OMPC_MAP_unknown)) {
7908 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7909 CombinedInfo.BasePointers.push_back(BP.getPointer());
7910 CombinedInfo.Pointers.push_back(LB.getPointer());
7911 CombinedInfo.Sizes.push_back(
7912 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
7913 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
7914 : 1);
7915
7916 // If Mapper is valid, the last component inherits the mapper.
7917 bool HasMapper = Mapper && Next == CE;
7918 CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr);
7919
7920 // We need to add a pointer flag for each map that comes from the
7921 // same expression except for the first one. We also need to signal
7922 // this map is the first one that relates with the current capture
7923 // (there is a set of entries for each capture).
7924 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
7925 MapType, MapModifiers, MotionModifiers, IsImplicit,
7926 !IsExpressionFirstInfo || RequiresReference ||
7927 FirstPointerInComplexData || IsMemberReference,
7928 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
7929
7930 if (!IsExpressionFirstInfo || IsMemberReference) {
7931 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
7932 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
7933 if (IsPointer || (IsMemberReference && Next != CE))
7934 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
7935 OMP_MAP_DELETE | OMP_MAP_CLOSE);
7936
7937 if (ShouldBeMemberOf) {
7938 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7939 // should be later updated with the correct value of MEMBER_OF.
7940 Flags |= OMP_MAP_MEMBER_OF;
7941 // From now on, all subsequent PTR_AND_OBJ entries should not be
7942 // marked as MEMBER_OF.
7943 ShouldBeMemberOf = false;
7944 }
7945 }
7946
7947 CombinedInfo.Types.push_back(Flags);
7948 }
7949
7950 // If we have encountered a member expression so far, keep track of the
7951 // mapped member. If the parent is "*this", then the value declaration
7952 // is nullptr.
7953 if (EncounteredME) {
7954 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl());
7955 unsigned FieldIndex = FD->getFieldIndex();
7956
7957 // Update info about the lowest and highest elements for this struct
7958 if (!PartialStruct.Base.isValid()) {
7959 PartialStruct.LowestElem = {FieldIndex, LowestElem};
7960 if (IsFinalArraySection) {
7961 Address HB =
7962 CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false)
7963 .getAddress(CGF);
7964 PartialStruct.HighestElem = {FieldIndex, HB};
7965 } else {
7966 PartialStruct.HighestElem = {FieldIndex, LowestElem};
7967 }
7968 PartialStruct.Base = BP;
7969 PartialStruct.LB = BP;
7970 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7971 PartialStruct.LowestElem = {FieldIndex, LowestElem};
7972 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7973 PartialStruct.HighestElem = {FieldIndex, LowestElem};
7974 }
7975 }
7976
7977 // Need to emit combined struct for array sections.
7978 if (IsFinalArraySection || IsNonContiguous)
7979 PartialStruct.IsArraySection = true;
7980
7981 // If we have a final array section, we are done with this expression.
7982 if (IsFinalArraySection)
7983 break;
7984
7985 // The pointer becomes the base for the next element.
7986 if (Next != CE)
7987 BP = IsMemberReference ? LowestElem : LB;
7988
7989 IsExpressionFirstInfo = false;
7990 IsCaptureFirstInfo = false;
7991 FirstPointerInComplexData = false;
7992 IsPrevMemberReference = IsMemberReference;
7993 } else if (FirstPointerInComplexData) {
7994 QualType Ty = Components.rbegin()
7995 ->getAssociatedDeclaration()
7996 ->getType()
7997 .getNonReferenceType();
7998 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
7999 FirstPointerInComplexData = false;
8000 }
8001 }
8002 // If ran into the whole component - allocate the space for the whole
8003 // record.
8004 if (!EncounteredME
13.1
'EncounteredME' is null
13.1
'EncounteredME' is null
)
14
Taking true branch
8005 PartialStruct.HasCompleteRecord = true;
8006
8007 if (!IsNonContiguous)
15
Assuming 'IsNonContiguous' is true
16
Taking false branch
8008 return;
8009
8010 const ASTContext &Context = CGF.getContext();
8011
8012 // For supporting stride in array section, we need to initialize the first
8013 // dimension size as 1, first offset as 0, and first count as 1
8014 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 0)};
8015 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)};
8016 MapValuesArrayTy CurStrides;
8017 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)};
8018 uint64_t ElementTypeSize;
17
'ElementTypeSize' declared without an initial value
8019
8020 // Collect Size information for each dimension and get the element size as
8021 // the first Stride. For example, for `int arr[10][10]`, the DimSizes
8022 // should be [10, 10] and the first stride is 4 btyes.
8023 for (const OMPClauseMappableExprCommon::MappableComponent &Component :
18
Assuming '__begin2' is equal to '__end2'
8024 Components) {
8025 const Expr *AssocExpr = Component.getAssociatedExpression();
8026 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
8027
8028 if (!OASE)
8029 continue;
8030
8031 QualType Ty = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
8032 auto *CAT = Context.getAsConstantArrayType(Ty);
8033 auto *VAT = Context.getAsVariableArrayType(Ty);
8034
8035 // We need all the dimension size except for the last dimension.
8036 assert((VAT || CAT || &Component == &*Components.begin()) &&(((VAT || CAT || &Component == &*Components.begin()) &&
"Should be either ConstantArray or VariableArray if not the "
"first Component") ? static_cast<void> (0) : __assert_fail
("(VAT || CAT || &Component == &*Components.begin()) && \"Should be either ConstantArray or VariableArray if not the \" \"first Component\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8038, __PRETTY_FUNCTION__))
8037 "Should be either ConstantArray or VariableArray if not the "(((VAT || CAT || &Component == &*Components.begin()) &&
"Should be either ConstantArray or VariableArray if not the "
"first Component") ? static_cast<void> (0) : __assert_fail
("(VAT || CAT || &Component == &*Components.begin()) && \"Should be either ConstantArray or VariableArray if not the \" \"first Component\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8038, __PRETTY_FUNCTION__))
8038 "first Component")(((VAT || CAT || &Component == &*Components.begin()) &&
"Should be either ConstantArray or VariableArray if not the "
"first Component") ? static_cast<void> (0) : __assert_fail
("(VAT || CAT || &Component == &*Components.begin()) && \"Should be either ConstantArray or VariableArray if not the \" \"first Component\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8038, __PRETTY_FUNCTION__))
;
8039
8040 // Get element size if CurStrides is empty.
8041 if (CurStrides.empty()) {
8042 const Type *ElementType = nullptr;
8043 if (CAT)
8044 ElementType = CAT->getElementType().getTypePtr();
8045 else if (VAT)
8046 ElementType = VAT->getElementType().getTypePtr();
8047 else
8048 assert(&Component == &*Components.begin() &&((&Component == &*Components.begin() && "Only expect pointer (non CAT or VAT) when this is the "
"first Component") ? static_cast<void> (0) : __assert_fail
("&Component == &*Components.begin() && \"Only expect pointer (non CAT or VAT) when this is the \" \"first Component\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8050, __PRETTY_FUNCTION__))
8049 "Only expect pointer (non CAT or VAT) when this is the "((&Component == &*Components.begin() && "Only expect pointer (non CAT or VAT) when this is the "
"first Component") ? static_cast<void> (0) : __assert_fail
("&Component == &*Components.begin() && \"Only expect pointer (non CAT or VAT) when this is the \" \"first Component\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8050, __PRETTY_FUNCTION__))
8050 "first Component")((&Component == &*Components.begin() && "Only expect pointer (non CAT or VAT) when this is the "
"first Component") ? static_cast<void> (0) : __assert_fail
("&Component == &*Components.begin() && \"Only expect pointer (non CAT or VAT) when this is the \" \"first Component\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8050, __PRETTY_FUNCTION__))
;
8051 // If ElementType is null, then it means the base is a pointer
8052 // (neither CAT nor VAT) and we'll attempt to get ElementType again
8053 // for next iteration.
8054 if (ElementType) {
8055 // For the case that having pointer as base, we need to remove one
8056 // level of indirection.
8057 if (&Component != &*Components.begin())
8058 ElementType = ElementType->getPointeeOrArrayElementType();
8059 ElementTypeSize =
8060 Context.getTypeSizeInChars(ElementType).getQuantity();
8061 CurStrides.push_back(
8062 llvm::ConstantInt::get(CGF.Int64Ty, ElementTypeSize));
8063 }
8064 }
8065 // Get dimension value except for the last dimension since we don't need
8066 // it.
8067 if (DimSizes.size() < Components.size() - 1) {
8068 if (CAT)
8069 DimSizes.push_back(llvm::ConstantInt::get(
8070 CGF.Int64Ty, CAT->getSize().getZExtValue()));
8071 else if (VAT)
8072 DimSizes.push_back(CGF.Builder.CreateIntCast(
8073 CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty,
8074 /*IsSigned=*/false));
8075 }
8076 }
8077
8078 // Skip the dummy dimension since we have already have its information.
8079 auto DI = DimSizes.begin() + 1;
8080 // Product of dimension.
8081 llvm::Value *DimProd =
8082 llvm::ConstantInt::get(CGF.CGM.Int64Ty, ElementTypeSize);
19
2nd function call argument is an uninitialized value
8083
8084 // Collect info for non-contiguous. Notice that offset, count, and stride
8085 // are only meaningful for array-section, so we insert a null for anything
8086 // other than array-section.
8087 // Also, the size of offset, count, and stride are not the same as
8088 // pointers, base_pointers, sizes, or dims. Instead, the size of offset,
8089 // count, and stride are the same as the number of non-contiguous
8090 // declaration in target update to/from clause.
8091 for (const OMPClauseMappableExprCommon::MappableComponent &Component :
8092 Components) {
8093 const Expr *AssocExpr = Component.getAssociatedExpression();
8094
8095 if (const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8096 llvm::Value *Offset = CGF.Builder.CreateIntCast(
8097 CGF.EmitScalarExpr(AE->getIdx()), CGF.Int64Ty,
8098 /*isSigned=*/false);
8099 CurOffsets.push_back(Offset);
8100 CurCounts.push_back(llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/1));
8101 CurStrides.push_back(CurStrides.back());
8102 continue;
8103 }
8104
8105 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
8106
8107 if (!OASE)
8108 continue;
8109
8110 // Offset
8111 const Expr *OffsetExpr = OASE->getLowerBound();
8112 llvm::Value *Offset = nullptr;
8113 if (!OffsetExpr) {
8114 // If offset is absent, then we just set it to zero.
8115 Offset = llvm::ConstantInt::get(CGF.Int64Ty, 0);
8116 } else {
8117 Offset = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(OffsetExpr),
8118 CGF.Int64Ty,
8119 /*isSigned=*/false);
8120 }
8121 CurOffsets.push_back(Offset);
8122
8123 // Count
8124 const Expr *CountExpr = OASE->getLength();
8125 llvm::Value *Count = nullptr;
8126 if (!CountExpr) {
8127 // In Clang, once a high dimension is an array section, we construct all
8128 // the lower dimension as array section, however, for case like
8129 // arr[0:2][2], Clang construct the inner dimension as an array section
8130 // but it actually is not in an array section form according to spec.
8131 if (!OASE->getColonLocFirst().isValid() &&
8132 !OASE->getColonLocSecond().isValid()) {
8133 Count = llvm::ConstantInt::get(CGF.Int64Ty, 1);
8134 } else {
8135 // OpenMP 5.0, 2.1.5 Array Sections, Description.
8136 // When the length is absent it defaults to ⌈(size −
8137 // lower-bound)/stride⌉, where size is the size of the array
8138 // dimension.
8139 const Expr *StrideExpr = OASE->getStride();
8140 llvm::Value *Stride =
8141 StrideExpr
8142 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr),
8143 CGF.Int64Ty, /*isSigned=*/false)
8144 : nullptr;
8145 if (Stride)
8146 Count = CGF.Builder.CreateUDiv(
8147 CGF.Builder.CreateNUWSub(*DI, Offset), Stride);
8148 else
8149 Count = CGF.Builder.CreateNUWSub(*DI, Offset);
8150 }
8151 } else {
8152 Count = CGF.EmitScalarExpr(CountExpr);
8153 }
8154 Count = CGF.Builder.CreateIntCast(Count, CGF.Int64Ty, /*isSigned=*/false);
8155 CurCounts.push_back(Count);
8156
8157 // Stride_n' = Stride_n * (D_0 * D_1 ... * D_n-1) * Unit size
8158 // Take `int arr[5][5][5]` and `arr[0:2:2][1:2:1][0:2:2]` as an example:
8159 // Offset Count Stride
8160 // D0 0 1 4 (int) <- dummy dimension
8161 // D1 0 2 8 (2 * (1) * 4)
8162 // D2 1 2 20 (1 * (1 * 5) * 4)
8163 // D3 0 2 200 (2 * (1 * 5 * 4) * 4)
8164 const Expr *StrideExpr = OASE->getStride();
8165 llvm::Value *Stride =
8166 StrideExpr
8167 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr),
8168 CGF.Int64Ty, /*isSigned=*/false)
8169 : nullptr;
8170 DimProd = CGF.Builder.CreateNUWMul(DimProd, *(DI - 1));
8171 if (Stride)
8172 CurStrides.push_back(CGF.Builder.CreateNUWMul(DimProd, Stride));
8173 else
8174 CurStrides.push_back(DimProd);
8175 if (DI != DimSizes.end())
8176 ++DI;
8177 }
8178
8179 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8180 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8181 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8182 }
8183
8184 /// Return the adjusted map modifiers if the declaration a capture refers to
8185 /// appears in a first-private clause. This is expected to be used only with
8186 /// directives that start with 'target'.
8187 MappableExprsHandler::OpenMPOffloadMappingFlags
8188 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
8189 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8189, __PRETTY_FUNCTION__))
;
8190
8191 // A first private variable captured by reference will use only the
8192 // 'private ptr' and 'map to' flag. Return the right flags if the captured
8193 // declaration is known as first-private in this handler.
8194 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
8195 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
8196 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
8197 return MappableExprsHandler::OMP_MAP_ALWAYS |
8198 MappableExprsHandler::OMP_MAP_TO;
8199 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
8200 return MappableExprsHandler::OMP_MAP_TO |
8201 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
8202 return MappableExprsHandler::OMP_MAP_PRIVATE |
8203 MappableExprsHandler::OMP_MAP_TO;
8204 }
8205 return MappableExprsHandler::OMP_MAP_TO |
8206 MappableExprsHandler::OMP_MAP_FROM;
8207 }
8208
8209 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
8210 // Rotate by getFlagMemberOffset() bits.
8211 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
8212 << getFlagMemberOffset());
8213 }
8214
8215 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
8216 OpenMPOffloadMappingFlags MemberOfFlag) {
8217 // If the entry is PTR_AND_OBJ but has not been marked with the special
8218 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
8219 // marked as MEMBER_OF.
8220 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
8221 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
8222 return;
8223
8224 // Reset the placeholder value to prepare the flag for the assignment of the
8225 // proper MEMBER_OF value.
8226 Flags &= ~OMP_MAP_MEMBER_OF;
8227 Flags |= MemberOfFlag;
8228 }
8229
8230 void getPlainLayout(const CXXRecordDecl *RD,
8231 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8232 bool AsBase) const {
8233 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
8234
8235 llvm::StructType *St =
8236 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
8237
8238 unsigned NumElements = St->getNumElements();
8239 llvm::SmallVector<
8240 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8241 RecordLayout(NumElements);
8242
8243 // Fill bases.
8244 for (const auto &I : RD->bases()) {
8245 if (I.isVirtual())
8246 continue;
8247 const auto *Base = I.getType()->getAsCXXRecordDecl();
8248 // Ignore empty bases.
8249 if (Base->isEmpty() || CGF.getContext()
8250 .getASTRecordLayout(Base)
8251 .getNonVirtualSize()
8252 .isZero())
8253 continue;
8254
8255 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
8256 RecordLayout[FieldIndex] = Base;
8257 }
8258 // Fill in virtual bases.
8259 for (const auto &I : RD->vbases()) {
8260 const auto *Base = I.getType()->getAsCXXRecordDecl();
8261 // Ignore empty bases.
8262 if (Base->isEmpty())
8263 continue;
8264 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
8265 if (RecordLayout[FieldIndex])
8266 continue;
8267 RecordLayout[FieldIndex] = Base;
8268 }
8269 // Fill in all the fields.
8270 assert(!RD->isUnion() && "Unexpected union.")((!RD->isUnion() && "Unexpected union.") ? static_cast
<void> (0) : __assert_fail ("!RD->isUnion() && \"Unexpected union.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8270, __PRETTY_FUNCTION__))
;
8271 for (const auto *Field : RD->fields()) {
8272 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
8273 // will fill in later.)
8274 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
8275 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
8276 RecordLayout[FieldIndex] = Field;
8277 }
8278 }
8279 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8280 &Data : RecordLayout) {
8281 if (Data.isNull())
8282 continue;
8283 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
8284 getPlainLayout(Base, Layout, /*AsBase=*/true);
8285 else
8286 Layout.push_back(Data.get<const FieldDecl *>());
8287 }
8288 }
8289
8290 /// Generate all the base pointers, section pointers, sizes, map types, and
8291 /// mappers for the extracted mappable expressions (all included in \a
8292 /// CombinedInfo). Also, for each item that relates with a device pointer, a
8293 /// pair of the relevant declaration and index where it occurs is appended to
8294 /// the device pointers info array.
8295 void generateAllInfoForClauses(
8296 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8297 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8298 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const {
8299 // We have to process the component lists that relate with the same
8300 // declaration in a single chunk so that we can generate the map flags
8301 // correctly. Therefore, we organize all lists in a map.
8302 enum MapKind { Present, Allocs, Other, Total };
8303 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8304 SmallVector<SmallVector<MapInfo, 8>, 4>>
8305 Info;
8306
8307 // Helper function to fill the information map for the different supported
8308 // clauses.
8309 auto &&InfoGen =
8310 [&Info, &SkipVarSet](
8311 const ValueDecl *D, MapKind Kind,
8312 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8313 OpenMPMapClauseKind MapType,
8314 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8315 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8316 bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper,
8317 const Expr *VarRef = nullptr, bool ForDeviceAddr = false) {
8318 if (SkipVarSet.contains(D))
8319 return;
8320 auto It = Info.find(D);
8321 if (It == Info.end())
8322 It = Info
8323 .insert(std::make_pair(
8324 D, SmallVector<SmallVector<MapInfo, 8>, 4>(Total)))
8325 .first;
8326 It->second[Kind].emplace_back(
8327 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8328 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8329 };
8330
8331 for (const auto *Cl : Clauses) {
8332 const auto *C = dyn_cast<OMPMapClause>(Cl);
8333 if (!C)
8334 continue;
8335 MapKind Kind = Other;
8336 if (!C->getMapTypeModifiers().empty() &&
8337 llvm::any_of(C->getMapTypeModifiers(), [](OpenMPMapModifierKind K) {
8338 return K == OMPC_MAP_MODIFIER_present;
8339 }))
8340 Kind = Present;
8341 else if (C->getMapType() == OMPC_MAP_alloc)
8342 Kind = Allocs;
8343 const auto *EI = C->getVarRefs().begin();
8344 for (const auto L : C->component_lists()) {
8345 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr;
8346 InfoGen(std::get<0>(L), Kind, std::get<1>(L), C->getMapType(),
8347 C->getMapTypeModifiers(), llvm::None,
8348 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L),
8349 E);
8350 ++EI;
8351 }
8352 }
8353 for (const auto *Cl : Clauses) {
8354 const auto *C = dyn_cast<OMPToClause>(Cl);
8355 if (!C)
8356 continue;
8357 MapKind Kind = Other;
8358 if (!C->getMotionModifiers().empty() &&
8359 llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) {
8360 return K == OMPC_MOTION_MODIFIER_present;
8361 }))
8362 Kind = Present;
8363 const auto *EI = C->getVarRefs().begin();
8364 for (const auto L : C->component_lists()) {
8365 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, llvm::None,
8366 C->getMotionModifiers(), /*ReturnDevicePointer=*/false,
8367 C->isImplicit(), std::get<2>(L), *EI);
8368 ++EI;
8369 }
8370 }
8371 for (const auto *Cl : Clauses) {
8372 const auto *C = dyn_cast<OMPFromClause>(Cl);
8373 if (!C)
8374 continue;
8375 MapKind Kind = Other;
8376 if (!C->getMotionModifiers().empty() &&
8377 llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) {
8378 return K == OMPC_MOTION_MODIFIER_present;
8379 }))
8380 Kind = Present;
8381 const auto *EI = C->getVarRefs().begin();
8382 for (const auto L : C->component_lists()) {
8383 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, llvm::None,
8384 C->getMotionModifiers(), /*ReturnDevicePointer=*/false,
8385 C->isImplicit(), std::get<2>(L), *EI);
8386 ++EI;
8387 }
8388 }
8389
8390 // Look at the use_device_ptr clause information and mark the existing map
8391 // entries as such. If there is no map information for an entry in the
8392 // use_device_ptr list, we create one with map type 'alloc' and zero size
8393 // section. It is the user fault if that was not mapped before. If there is
8394 // no map information and the pointer is a struct member, then we defer the
8395 // emission of that entry until the whole struct has been processed.
8396 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8397 SmallVector<DeferredDevicePtrEntryTy, 4>>
8398 DeferredInfo;
8399 MapCombinedInfoTy UseDevicePtrCombinedInfo;
8400
8401 for (const auto *Cl : Clauses) {
8402 const auto *C = dyn_cast<OMPUseDevicePtrClause>(Cl);
8403 if (!C)
8404 continue;
8405 for (const auto L : C->component_lists()) {
8406 OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
8407 std::get<1>(L);
8408 assert(!Components.empty() &&((!Components.empty() && "Not expecting empty list of components!"
) ? static_cast<void> (0) : __assert_fail ("!Components.empty() && \"Not expecting empty list of components!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8409, __PRETTY_FUNCTION__))
8409 "Not expecting empty list of components!")((!Components.empty() && "Not expecting empty list of components!"
) ? static_cast<void> (0) : __assert_fail ("!Components.empty() && \"Not expecting empty list of components!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8409, __PRETTY_FUNCTION__))
;
8410 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
8411 VD = cast<ValueDecl>(VD->getCanonicalDecl());
8412 const Expr *IE = Components.back().getAssociatedExpression();
8413 // If the first component is a member expression, we have to look into
8414 // 'this', which maps to null in the map of map information. Otherwise
8415 // look directly for the information.
8416 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8417
8418 // We potentially have map information for this declaration already.
8419 // Look for the first set of components that refer to it.
8420 if (It != Info.end()) {
8421 bool Found = false;
8422 for (auto &Data : It->second) {
8423 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) {
8424 return MI.Components.back().getAssociatedDeclaration() == VD;
8425 });
8426 // If we found a map entry, signal that the pointer has to be
8427 // returned and move on to the next declaration. Exclude cases where
8428 // the base pointer is mapped as array subscript, array section or
8429 // array shaping. The base address is passed as a pointer to base in
8430 // this case and cannot be used as a base for use_device_ptr list
8431 // item.
8432 if (CI != Data.end()) {
8433 auto PrevCI = std::next(CI->Components.rbegin());
8434 const auto *VarD = dyn_cast<VarDecl>(VD);
8435 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8436 isa<MemberExpr>(IE) ||
8437 !VD->getType().getNonReferenceType()->isPointerType() ||
8438 PrevCI == CI->Components.rend() ||
8439 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
8440 VarD->hasLocalStorage()) {
8441 CI->ReturnDevicePointer = true;
8442 Found = true;
8443 break;
8444 }
8445 }
8446 }
8447 if (Found)
8448 continue;
8449 }
8450
8451 // We didn't find any match in our map information - generate a zero
8452 // size array section - if the pointer is a struct member we defer this
8453 // action until the whole struct has been processed.
8454 if (isa<MemberExpr>(IE)) {
8455 // Insert the pointer into Info to be processed by
8456 // generateInfoForComponentList. Because it is a member pointer
8457 // without a pointee, no entry will be generated for it, therefore
8458 // we need to generate one after the whole struct has been processed.
8459 // Nonetheless, generateInfoForComponentList must be called to take
8460 // the pointer into account for the calculation of the range of the
8461 // partial struct.
8462 InfoGen(nullptr, Other, Components, OMPC_MAP_unknown, llvm::None,
8463 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(),
8464 nullptr);
8465 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false);
8466 } else {
8467 llvm::Value *Ptr =
8468 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
8469 UseDevicePtrCombinedInfo.Exprs.push_back(VD);
8470 UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD);
8471 UseDevicePtrCombinedInfo.Pointers.push_back(Ptr);
8472 UseDevicePtrCombinedInfo.Sizes.push_back(
8473 llvm::Constant::getNullValue(CGF.Int64Ty));
8474 UseDevicePtrCombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM);
8475 UseDevicePtrCombinedInfo.Mappers.push_back(nullptr);
8476 }
8477 }
8478 }
8479
8480 // Look at the use_device_addr clause information and mark the existing map
8481 // entries as such. If there is no map information for an entry in the
8482 // use_device_addr list, we create one with map type 'alloc' and zero size
8483 // section. It is the user fault if that was not mapped before. If there is
8484 // no map information and the pointer is a struct member, then we defer the
8485 // emission of that entry until the whole struct has been processed.
8486 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8487 for (const auto *Cl : Clauses) {
8488 const auto *C = dyn_cast<OMPUseDeviceAddrClause>(Cl);
8489 if (!C)
8490 continue;
8491 for (const auto L : C->component_lists()) {
8492 assert(!std::get<1>(L).empty() &&((!std::get<1>(L).empty() && "Not expecting empty list of components!"
) ? static_cast<void> (0) : __assert_fail ("!std::get<1>(L).empty() && \"Not expecting empty list of components!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8493, __PRETTY_FUNCTION__))
8493 "Not expecting empty list of components!")((!std::get<1>(L).empty() && "Not expecting empty list of components!"
) ? static_cast<void> (0) : __assert_fail ("!std::get<1>(L).empty() && \"Not expecting empty list of components!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8493, __PRETTY_FUNCTION__))
;
8494 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
8495 if (!Processed.insert(VD).second)
8496 continue;
8497 VD = cast<ValueDecl>(VD->getCanonicalDecl());
8498 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
8499 // If the first component is a member expression, we have to look into
8500 // 'this', which maps to null in the map of map information. Otherwise
8501 // look directly for the information.
8502 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8503
8504 // We potentially have map information for this declaration already.
8505 // Look for the first set of components that refer to it.
8506 if (It != Info.end()) {
8507 bool Found = false;
8508 for (auto &Data : It->second) {
8509 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) {
8510 return MI.Components.back().getAssociatedDeclaration() == VD;
8511 });
8512 // If we found a map entry, signal that the pointer has to be
8513 // returned and move on to the next declaration.
8514 if (CI != Data.end()) {
8515 CI->ReturnDevicePointer = true;
8516 Found = true;
8517 break;
8518 }
8519 }
8520 if (Found)
8521 continue;
8522 }
8523
8524 // We didn't find any match in our map information - generate a zero
8525 // size array section - if the pointer is a struct member we defer this
8526 // action until the whole struct has been processed.
8527 if (isa<MemberExpr>(IE)) {
8528 // Insert the pointer into Info to be processed by
8529 // generateInfoForComponentList. Because it is a member pointer
8530 // without a pointee, no entry will be generated for it, therefore
8531 // we need to generate one after the whole struct has been processed.
8532 // Nonetheless, generateInfoForComponentList must be called to take
8533 // the pointer into account for the calculation of the range of the
8534 // partial struct.
8535 InfoGen(nullptr, Other, std::get<1>(L), OMPC_MAP_unknown, llvm::None,
8536 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(),
8537 nullptr, nullptr, /*ForDeviceAddr=*/true);
8538 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true);
8539 } else {
8540 llvm::Value *Ptr;
8541 if (IE->isGLValue())
8542 Ptr = CGF.EmitLValue(IE).getPointer(CGF);
8543 else
8544 Ptr = CGF.EmitScalarExpr(IE);
8545 CombinedInfo.Exprs.push_back(VD);
8546 CombinedInfo.BasePointers.emplace_back(Ptr, VD);
8547 CombinedInfo.Pointers.push_back(Ptr);
8548 CombinedInfo.Sizes.push_back(
8549 llvm::Constant::getNullValue(CGF.Int64Ty));
8550 CombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM);
8551 CombinedInfo.Mappers.push_back(nullptr);
8552 }
8553 }
8554 }
8555
8556 for (const auto &Data : Info) {
8557 StructRangeInfoTy PartialStruct;
8558 // Temporary generated information.
8559 MapCombinedInfoTy CurInfo;
8560 const Decl *D = Data.first;
8561 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
8562 for (const auto &M : Data.second) {
8563 for (const MapInfo &L : M) {
8564 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8565, __PRETTY_FUNCTION__))
8565 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8565, __PRETTY_FUNCTION__))
;
8566
8567 // Remember the current base pointer index.
8568 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
8569 CurInfo.NonContigInfo.IsNonContiguous =
8570 L.Components.back().isNonContiguous();
8571 generateInfoForComponentList(
8572 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
8573 CurInfo, PartialStruct, /*IsFirstComponentList=*/false,
8574 L.IsImplicit, L.Mapper, L.ForDeviceAddr, VD, L.VarRef);
8575
8576 // If this entry relates with a device pointer, set the relevant
8577 // declaration and add the 'return pointer' flag.
8578 if (L.ReturnDevicePointer) {
8579 assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx &&((CurInfo.BasePointers.size() > CurrentBasePointersIdx &&
"Unexpected number of mapped base pointers.") ? static_cast<
void> (0) : __assert_fail ("CurInfo.BasePointers.size() > CurrentBasePointersIdx && \"Unexpected number of mapped base pointers.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8580, __PRETTY_FUNCTION__))
8580 "Unexpected number of mapped base pointers.")((CurInfo.BasePointers.size() > CurrentBasePointersIdx &&
"Unexpected number of mapped base pointers.") ? static_cast<
void> (0) : __assert_fail ("CurInfo.BasePointers.size() > CurrentBasePointersIdx && \"Unexpected number of mapped base pointers.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8580, __PRETTY_FUNCTION__))
;
8581
8582 const ValueDecl *RelevantVD =
8583 L.Components.back().getAssociatedDeclaration();
8584 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8585, __PRETTY_FUNCTION__))
8585 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8585, __PRETTY_FUNCTION__))
;
8586
8587 CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl(
8588 RelevantVD);
8589 CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
8590 }
8591 }
8592 }
8593
8594 // Append any pending zero-length pointers which are struct members and
8595 // used with use_device_ptr or use_device_addr.
8596 auto CI = DeferredInfo.find(Data.first);
8597 if (CI != DeferredInfo.end()) {
8598 for (const DeferredDevicePtrEntryTy &L : CI->second) {
8599 llvm::Value *BasePtr;
8600 llvm::Value *Ptr;
8601 if (L.ForDeviceAddr) {
8602 if (L.IE->isGLValue())
8603 Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
8604 else
8605 Ptr = this->CGF.EmitScalarExpr(L.IE);
8606 BasePtr = Ptr;
8607 // Entry is RETURN_PARAM. Also, set the placeholder value
8608 // MEMBER_OF=FFFF so that the entry is later updated with the
8609 // correct value of MEMBER_OF.
8610 CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF);
8611 } else {
8612 BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
8613 Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE),
8614 L.IE->getExprLoc());
8615 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the
8616 // placeholder value MEMBER_OF=FFFF so that the entry is later
8617 // updated with the correct value of MEMBER_OF.
8618 CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8619 OMP_MAP_MEMBER_OF);
8620 }
8621 CurInfo.Exprs.push_back(L.VD);
8622 CurInfo.BasePointers.emplace_back(BasePtr, L.VD);
8623 CurInfo.Pointers.push_back(Ptr);
8624 CurInfo.Sizes.push_back(
8625 llvm::Constant::getNullValue(this->CGF.Int64Ty));
8626 CurInfo.Mappers.push_back(nullptr);
8627 }
8628 }
8629 // If there is an entry in PartialStruct it means we have a struct with
8630 // individual members mapped. Emit an extra combined entry.
8631 if (PartialStruct.Base.isValid()) {
8632 CurInfo.NonContigInfo.Dims.push_back(0);
8633 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD);
8634 }
8635
8636 // We need to append the results of this capture to what we already
8637 // have.
8638 CombinedInfo.append(CurInfo);
8639 }
8640 // Append data for use_device_ptr clauses.
8641 CombinedInfo.append(UseDevicePtrCombinedInfo);
8642 }
8643
8644public:
8645 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
8646 : CurDir(&Dir), CGF(CGF) {
8647 // Extract firstprivate clause information.
8648 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
8649 for (const auto *D : C->varlists())
8650 FirstPrivateDecls.try_emplace(
8651 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
8652 // Extract implicit firstprivates from uses_allocators clauses.
8653 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
8654 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
8655 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
8656 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
8657 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
8658 /*Implicit=*/true);
8659 else if (const auto *VD = dyn_cast<VarDecl>(
8660 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
8661 ->getDecl()))
8662 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true);
8663 }
8664 }
8665 // Extract device pointer clause information.
8666 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
8667 for (auto L : C->component_lists())
8668 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
8669 }
8670
8671 /// Constructor for the declare mapper directive.
8672 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
8673 : CurDir(&Dir), CGF(CGF) {}
8674
8675 /// Generate code for the combined entry if we have a partially mapped struct
8676 /// and take care of the mapping flags of the arguments corresponding to
8677 /// individual struct members.
8678 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
8679 MapFlagsArrayTy &CurTypes,
8680 const StructRangeInfoTy &PartialStruct,
8681 const ValueDecl *VD = nullptr,
8682 bool NotTargetParams = true) const {
8683 if (CurTypes.size() == 1 &&
8684 ((CurTypes.back() & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF) &&
8685 !PartialStruct.IsArraySection)
8686 return;
8687 Address LBAddr = PartialStruct.LowestElem.second;
8688 Address HBAddr = PartialStruct.HighestElem.second;
8689 if (PartialStruct.HasCompleteRecord) {
8690 LBAddr = PartialStruct.LB;
8691 HBAddr = PartialStruct.LB;
8692 }
8693 CombinedInfo.Exprs.push_back(VD);
8694 // Base is the base of the struct
8695 CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer());
8696 // Pointer is the address of the lowest element
8697 llvm::Value *LB = LBAddr.getPointer();
8698 CombinedInfo.Pointers.push_back(LB);
8699 // There should not be a mapper for a combined entry.
8700 CombinedInfo.Mappers.push_back(nullptr);
8701 // Size is (addr of {highest+1} element) - (addr of lowest element)
8702 llvm::Value *HB = HBAddr.getPointer();
8703 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
8704 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
8705 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
8706 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
8707 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
8708 /*isSigned=*/false);
8709 CombinedInfo.Sizes.push_back(Size);
8710 // Map type is always TARGET_PARAM, if generate info for captures.
8711 CombinedInfo.Types.push_back(NotTargetParams ? OMP_MAP_NONE
8712 : OMP_MAP_TARGET_PARAM);
8713 // If any element has the present modifier, then make sure the runtime
8714 // doesn't attempt to allocate the struct.
8715 if (CurTypes.end() !=
8716 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) {
8717 return Type & OMP_MAP_PRESENT;
8718 }))
8719 CombinedInfo.Types.back() |= OMP_MAP_PRESENT;
8720 // Remove TARGET_PARAM flag from the first element
8721 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
8722
8723 // All other current entries will be MEMBER_OF the combined entry
8724 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8725 // 0xFFFF in the MEMBER_OF field).
8726 OpenMPOffloadMappingFlags MemberOfFlag =
8727 getMemberOfFlag(CombinedInfo.BasePointers.size() - 1);
8728 for (auto &M : CurTypes)
8729 setCorrectMemberOfFlag(M, MemberOfFlag);
8730 }
8731
8732 /// Generate all the base pointers, section pointers, sizes, map types, and
8733 /// mappers for the extracted mappable expressions (all included in \a
8734 /// CombinedInfo). Also, for each item that relates with a device pointer, a
8735 /// pair of the relevant declaration and index where it occurs is appended to
8736 /// the device pointers info array.
8737 void generateAllInfo(
8738 MapCombinedInfoTy &CombinedInfo,
8739 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8740 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const {
8741 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8742, __PRETTY_FUNCTION__))
8742 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8742, __PRETTY_FUNCTION__))
;
8743 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8744 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, SkipVarSet);
8745 }
8746
8747 /// Generate all the base pointers, section pointers, sizes, map types, and
8748 /// mappers for the extracted map clauses of user-defined mapper (all included
8749 /// in \a CombinedInfo).
8750 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const {
8751 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8752, __PRETTY_FUNCTION__))
8752 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8752, __PRETTY_FUNCTION__))
;
8753 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8754 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo);
8755 }
8756
8757 /// Emit capture info for lambdas for variables captured by reference.
8758 void generateInfoForLambdaCaptures(
8759 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8760 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
8761 const auto *RD = VD->getType()
8762 .getCanonicalType()
8763 .getNonReferenceType()
8764 ->getAsCXXRecordDecl();
8765 if (!RD || !RD->isLambda())
8766 return;
8767 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8768 LValue VDLVal = CGF.MakeAddrLValue(
8769 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8770 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8771 FieldDecl *ThisCapture = nullptr;
8772 RD->getCaptureFields(Captures, ThisCapture);
8773 if (ThisCapture) {
8774 LValue ThisLVal =
8775 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
8776 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
8777 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
8778 VDLVal.getPointer(CGF));
8779 CombinedInfo.Exprs.push_back(VD);
8780 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
8781 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
8782 CombinedInfo.Sizes.push_back(
8783 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8784 CGF.Int64Ty, /*isSigned=*/true));
8785 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
8786 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8787 CombinedInfo.Mappers.push_back(nullptr);
8788 }
8789 for (const LambdaCapture &LC : RD->captures()) {
8790 if (!LC.capturesVariable())
8791 continue;
8792 const VarDecl *VD = LC.getCapturedVar();
8793 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8794 continue;
8795 auto It = Captures.find(VD);
8796 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8796, __PRETTY_FUNCTION__))
;
8797 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
8798 if (LC.getCaptureKind() == LCK_ByRef) {
8799 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8800 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8801 VDLVal.getPointer(CGF));
8802 CombinedInfo.Exprs.push_back(VD);
8803 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
8804 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
8805 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
8806 CGF.getTypeSize(
8807 VD->getType().getCanonicalType().getNonReferenceType()),
8808 CGF.Int64Ty, /*isSigned=*/true));
8809 } else {
8810 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
8811 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8812 VDLVal.getPointer(CGF));
8813 CombinedInfo.Exprs.push_back(VD);
8814 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
8815 CombinedInfo.Pointers.push_back(VarRVal.getScalarVal());
8816 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8817 }
8818 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
8819 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8820 CombinedInfo.Mappers.push_back(nullptr);
8821 }
8822 }
8823
8824 /// Set correct indices for lambdas captures.
8825 void adjustMemberOfForLambdaCaptures(
8826 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8827 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8828 MapFlagsArrayTy &Types) const {
8829 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8830 // Set correct member_of idx for all implicit lambda captures.
8831 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
8832 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8833 continue;
8834 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8835 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8835, __PRETTY_FUNCTION__))
;
8836 int TgtIdx = -1;
8837 for (unsigned J = I; J > 0; --J) {
8838 unsigned Idx = J - 1;
8839 if (Pointers[Idx] != BasePtr)
8840 continue;
8841 TgtIdx = Idx;
8842 break;
8843 }
8844 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8844, __PRETTY_FUNCTION__))
;
8845 // All other current entries will be MEMBER_OF the combined entry
8846 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8847 // 0xFFFF in the MEMBER_OF field).
8848 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8849 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8850 }
8851 }
8852
8853 /// Generate the base pointers, section pointers, sizes, map types, and
8854 /// mappers associated to a given capture (all included in \a CombinedInfo).
8855 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
8856 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
8857 StructRangeInfoTy &PartialStruct) const {
8858 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8859, __PRETTY_FUNCTION__))
8859 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8859, __PRETTY_FUNCTION__))
;
8860
8861 // We need to know when we generating information for the first component
8862 const ValueDecl *VD = Cap->capturesThis()
8863 ? nullptr
8864 : Cap->getCapturedVar()->getCanonicalDecl();
8865
8866 // If this declaration appears in a is_device_ptr clause we just have to
8867 // pass the pointer by value. If it is a reference to a declaration, we just
8868 // pass its value.
8869 if (DevPointersMap.count(VD)) {
8870 CombinedInfo.Exprs.push_back(VD);
8871 CombinedInfo.BasePointers.emplace_back(Arg, VD);
8872 CombinedInfo.Pointers.push_back(Arg);
8873 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
8874 CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty,
8875 /*isSigned=*/true));
8876 CombinedInfo.Types.push_back(
8877 (Cap->capturesVariable() ? OMP_MAP_TO : OMP_MAP_LITERAL) |
8878 OMP_MAP_TARGET_PARAM);
8879 CombinedInfo.Mappers.push_back(nullptr);
8880 return;
8881 }
8882
8883 using MapData =
8884 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
8885 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool,
8886 const ValueDecl *, const Expr *>;
8887 SmallVector<MapData, 4> DeclComponentLists;
8888 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8889, __PRETTY_FUNCTION__))
8889 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8889, __PRETTY_FUNCTION__))
;
8890 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8891 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
8892 const auto *EI = C->getVarRefs().begin();
8893 for (const auto L : C->decl_component_lists(VD)) {
8894 const ValueDecl *VDecl, *Mapper;
8895 // The Expression is not correct if the mapping is implicit
8896 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr;
8897 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8898 std::tie(VDecl, Components, Mapper) = L;
8899 assert(VDecl == VD && "We got information for the wrong declaration??")((VDecl == VD && "We got information for the wrong declaration??"
) ? static_cast<void> (0) : __assert_fail ("VDecl == VD && \"We got information for the wrong declaration??\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8899, __PRETTY_FUNCTION__))
;
8900 assert(!Components.empty() &&((!Components.empty() && "Not expecting declaration with no component lists."
) ? static_cast<void> (0) : __assert_fail ("!Components.empty() && \"Not expecting declaration with no component lists.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8901, __PRETTY_FUNCTION__))
8901 "Not expecting declaration with no component lists.")((!Components.empty() && "Not expecting declaration with no component lists."
) ? static_cast<void> (0) : __assert_fail ("!Components.empty() && \"Not expecting declaration with no component lists.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 8901, __PRETTY_FUNCTION__))
;
8902 DeclComponentLists.emplace_back(Components, C->getMapType(),
8903 C->getMapTypeModifiers(),
8904 C->isImplicit(), Mapper, E);
8905 ++EI;
8906 }
8907 }
8908 llvm::stable_sort(DeclComponentLists, [](const MapData &LHS,
8909 const MapData &RHS) {
8910 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
8911 OpenMPMapClauseKind MapType = std::get<1>(RHS);
8912 bool HasPresent = !MapModifiers.empty() &&
8913 llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) {
8914 return K == clang::OMPC_MAP_MODIFIER_present;
8915 });
8916 bool HasAllocs = MapType == OMPC_MAP_alloc;
8917 MapModifiers = std::get<2>(RHS);
8918 MapType = std::get<1>(LHS);
8919 bool HasPresentR =
8920 !MapModifiers.empty() &&
8921 llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) {
8922 return K == clang::OMPC_MAP_MODIFIER_present;
8923 });
8924 bool HasAllocsR = MapType == OMPC_MAP_alloc;
8925 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
8926 });
8927
8928 // Find overlapping elements (including the offset from the base element).
8929 llvm::SmallDenseMap<
8930 const MapData *,
8931 llvm::SmallVector<
8932 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8933 4>
8934 OverlappedData;
8935 size_t Count = 0;
8936 for (const MapData &L : DeclComponentLists) {
8937 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8938 OpenMPMapClauseKind MapType;
8939 ArrayRef<OpenMPMapModifierKind> MapModifiers;
8940 bool IsImplicit;
8941 const ValueDecl *Mapper;
8942 const Expr *VarRef;
8943 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
8944 L;
8945 ++Count;
8946 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8947 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
8948 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
8949 VarRef) = L1;
8950 auto CI = Components.rbegin();
8951 auto CE = Components.rend();
8952 auto SI = Components1.rbegin();
8953 auto SE = Components1.rend();
8954 for (; CI != CE && SI != SE; ++CI, ++SI) {
8955 if (CI->getAssociatedExpression()->getStmtClass() !=
8956 SI->getAssociatedExpression()->getStmtClass())
8957 break;
8958 // Are we dealing with different variables/fields?
8959 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8960 break;
8961 }
8962 // Found overlapping if, at least for one component, reached the head
8963 // of the components list.
8964 if (CI == CE || SI == SE) {
8965 // Ignore it if it is the same component.
8966 if (CI == CE && SI == SE)
8967 continue;
8968 const auto It = (SI == SE) ? CI : SI;
8969 // If one component is a pointer and another one is a kind of
8970 // dereference of this pointer (array subscript, section, dereference,
8971 // etc.), it is not an overlapping.
8972 if (!isa<MemberExpr>(It->getAssociatedExpression()) ||
8973 std::prev(It)
8974 ->getAssociatedExpression()
8975 ->getType()
8976 ->isPointerType())
8977 continue;
8978 const MapData &BaseData = CI == CE ? L : L1;
8979 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8980 SI == SE ? Components : Components1;
8981 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8982 OverlappedElements.getSecond().push_back(SubData);
8983 }
8984 }
8985 }
8986 // Sort the overlapped elements for each item.
8987 llvm::SmallVector<const FieldDecl *, 4> Layout;
8988 if (!OverlappedData.empty()) {
8989 const Type *BaseType = VD->getType().getCanonicalType().getTypePtr();
8990 const Type *OrigType = BaseType->getPointeeOrArrayElementType();
8991 while (BaseType != OrigType) {
8992 BaseType = OrigType->getCanonicalTypeInternal().getTypePtr();
8993 OrigType = BaseType->getPointeeOrArrayElementType();
8994 }
8995
8996 if (const auto *CRD = BaseType->getAsCXXRecordDecl())
8997 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8998 else {
8999 const auto *RD = BaseType->getAsRecordDecl();
9000 Layout.append(RD->field_begin(), RD->field_end());
9001 }
9002 }
9003 for (auto &Pair : OverlappedData) {
9004 llvm::stable_sort(
9005 Pair.getSecond(),
9006 [&Layout](
9007 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
9008 OMPClauseMappableExprCommon::MappableExprComponentListRef
9009 Second) {
9010 auto CI = First.rbegin();
9011 auto CE = First.rend();
9012 auto SI = Second.rbegin();
9013 auto SE = Second.rend();
9014 for (; CI != CE && SI != SE; ++CI, ++SI) {
9015 if (CI->getAssociatedExpression()->getStmtClass() !=
9016 SI->getAssociatedExpression()->getStmtClass())
9017 break;
9018 // Are we dealing with different variables/fields?
9019 if (CI->getAssociatedDeclaration() !=
9020 SI->getAssociatedDeclaration())
9021 break;
9022 }
9023
9024 // Lists contain the same elements.
9025 if (CI == CE && SI == SE)
9026 return false;
9027
9028 // List with less elements is less than list with more elements.
9029 if (CI == CE || SI == SE)
9030 return CI == CE;
9031
9032 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
9033 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
9034 if (FD1->getParent() == FD2->getParent())
9035 return FD1->getFieldIndex() < FD2->getFieldIndex();
9036 const auto It =
9037 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
9038 return FD == FD1 || FD == FD2;
9039 });
9040 return *It == FD1;
9041 });
9042 }
9043
9044 // Associated with a capture, because the mapping flags depend on it.
9045 // Go through all of the elements with the overlapped elements.
9046 bool IsFirstComponentList = true;
9047 for (const auto &Pair : OverlappedData) {
9048 const MapData &L = *Pair.getFirst();
9049 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
9050 OpenMPMapClauseKind MapType;
9051 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9052 bool IsImplicit;
9053 const ValueDecl *Mapper;
9054 const Expr *VarRef;
9055 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9056 L;
9057 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
9058 OverlappedComponents = Pair.getSecond();
9059 generateInfoForComponentList(
9060 MapType, MapModifiers, llvm::None, Components, CombinedInfo,
9061 PartialStruct, IsFirstComponentList, IsImplicit, Mapper,
9062 /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents);
9063 IsFirstComponentList = false;
9064 }
9065 // Go through other elements without overlapped elements.
9066 for (const MapData &L : DeclComponentLists) {
9067 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
9068 OpenMPMapClauseKind MapType;
9069 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9070 bool IsImplicit;
9071 const ValueDecl *Mapper;
9072 const Expr *VarRef;
9073 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9074 L;
9075 auto It = OverlappedData.find(&L);
9076 if (It == OverlappedData.end())
9077 generateInfoForComponentList(MapType, MapModifiers, llvm::None,
9078 Components, CombinedInfo, PartialStruct,
9079 IsFirstComponentList, IsImplicit, Mapper,
9080 /*ForDeviceAddr=*/false, VD, VarRef);
9081 IsFirstComponentList = false;
9082 }
9083 }
9084
9085 /// Generate the default map information for a given capture \a CI,
9086 /// record field declaration \a RI and captured value \a CV.
9087 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
9088 const FieldDecl &RI, llvm::Value *CV,
9089 MapCombinedInfoTy &CombinedInfo) const {
9090 bool IsImplicit = true;
9091 // Do the default mapping.
9092 if (CI.capturesThis()) {
9093 CombinedInfo.Exprs.push_back(nullptr);
9094 CombinedInfo.BasePointers.push_back(CV);
9095 CombinedInfo.Pointers.push_back(CV);
9096 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
9097 CombinedInfo.Sizes.push_back(
9098 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
9099 CGF.Int64Ty, /*isSigned=*/true));
9100 // Default map type.
9101 CombinedInfo.Types.push_back(OMP_MAP_TO | OMP_MAP_FROM);
9102 } else if (CI.capturesVariableByCopy()) {
9103 const VarDecl *VD = CI.getCapturedVar();
9104 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl());
9105 CombinedInfo.BasePointers.push_back(CV);
9106 CombinedInfo.Pointers.push_back(CV);
9107 if (!RI.getType()->isAnyPointerType()) {
9108 // We have to signal to the runtime captures passed by value that are
9109 // not pointers.
9110 CombinedInfo.Types.push_back(OMP_MAP_LITERAL);
9111 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
9112 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
9113 } else {
9114 // Pointers are implicitly mapped with a zero size and no flags
9115 // (other than first map that is added for all implicit maps).
9116 CombinedInfo.Types.push_back(OMP_MAP_NONE);
9117 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
9118 }
9119 auto I = FirstPrivateDecls.find(VD);
9120 if (I != FirstPrivateDecls.end())
9121 IsImplicit = I->getSecond();
9122 } else {
9123 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9123, __PRETTY_FUNCTION__))
;
9124 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
9125 QualType ElementType = PtrTy->getPointeeType();
9126 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
9127 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
9128 // The default map type for a scalar/complex type is 'to' because by
9129 // default the value doesn't have to be retrieved. For an aggregate
9130 // type, the default is 'tofrom'.
9131 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
9132 const VarDecl *VD = CI.getCapturedVar();
9133 auto I = FirstPrivateDecls.find(VD);
9134 if (I != FirstPrivateDecls.end() &&
9135 VD->getType().isConstant(CGF.getContext())) {
9136 llvm::Constant *Addr =
9137 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
9138 // Copy the value of the original variable to the new global copy.
9139 CGF.Builder.CreateMemCpy(
9140 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF),
9141 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
9142 CombinedInfo.Sizes.back(), /*IsVolatile=*/false);
9143 // Use new global variable as the base pointers.
9144 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl());
9145 CombinedInfo.BasePointers.push_back(Addr);
9146 CombinedInfo.Pointers.push_back(Addr);
9147 } else {
9148 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl());
9149 CombinedInfo.BasePointers.push_back(CV);
9150 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
9151 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
9152 CV, ElementType, CGF.getContext().getDeclAlign(VD),
9153 AlignmentSource::Decl));
9154 CombinedInfo.Pointers.push_back(PtrAddr.getPointer());
9155 } else {
9156 CombinedInfo.Pointers.push_back(CV);
9157 }
9158 }
9159 if (I != FirstPrivateDecls.end())
9160 IsImplicit = I->getSecond();
9161 }
9162 // Every default map produces a single argument which is a target parameter.
9163 CombinedInfo.Types.back() |= OMP_MAP_TARGET_PARAM;
9164
9165 // Add flag stating this is an implicit map.
9166 if (IsImplicit)
9167 CombinedInfo.Types.back() |= OMP_MAP_IMPLICIT;
9168
9169 // No user-defined mapper for default mapping.
9170 CombinedInfo.Mappers.push_back(nullptr);
9171 }
9172};
9173} // anonymous namespace
9174
9175static void emitNonContiguousDescriptor(
9176 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
9177 CGOpenMPRuntime::TargetDataInfo &Info) {
9178 CodeGenModule &CGM = CGF.CGM;
9179 MappableExprsHandler::MapCombinedInfoTy::StructNonContiguousInfo
9180 &NonContigInfo = CombinedInfo.NonContigInfo;
9181
9182 // Build an array of struct descriptor_dim and then assign it to
9183 // offload_args.
9184 //
9185 // struct descriptor_dim {
9186 // uint64_t offset;
9187 // uint64_t count;
9188 // uint64_t stride
9189 // };
9190 ASTContext &C = CGF.getContext();
9191 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9192 RecordDecl *RD;
9193 RD = C.buildImplicitRecord("descriptor_dim");
9194 RD->startDefinition();
9195 addFieldToRecordDecl(C, RD, Int64Ty);
9196 addFieldToRecordDecl(C, RD, Int64Ty);
9197 addFieldToRecordDecl(C, RD, Int64Ty);
9198 RD->completeDefinition();
9199 QualType DimTy = C.getRecordType(RD);
9200
9201 enum { OffsetFD = 0, CountFD, StrideFD };
9202 // We need two index variable here since the size of "Dims" is the same as the
9203 // size of Components, however, the size of offset, count, and stride is equal
9204 // to the size of base declaration that is non-contiguous.
9205 for (unsigned I = 0, L = 0, E = NonContigInfo.Dims.size(); I < E; ++I) {
9206 // Skip emitting ir if dimension size is 1 since it cannot be
9207 // non-contiguous.
9208 if (NonContigInfo.Dims[I] == 1)
9209 continue;
9210 llvm::APInt Size(/*numBits=*/32, NonContigInfo.Dims[I]);
9211 QualType ArrayTy =
9212 C.getConstantArrayType(DimTy, Size, nullptr, ArrayType::Normal, 0);
9213 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
9214 for (unsigned II = 0, EE = NonContigInfo.Dims[I]; II < EE; ++II) {
9215 unsigned RevIdx = EE - II - 1;
9216 LValue DimsLVal = CGF.MakeAddrLValue(
9217 CGF.Builder.CreateConstArrayGEP(DimsAddr, II), DimTy);
9218 // Offset
9219 LValue OffsetLVal = CGF.EmitLValueForField(
9220 DimsLVal, *std::next(RD->field_begin(), OffsetFD));
9221 CGF.EmitStoreOfScalar(NonContigInfo.Offsets[L][RevIdx], OffsetLVal);
9222 // Count
9223 LValue CountLVal = CGF.EmitLValueForField(
9224 DimsLVal, *std::next(RD->field_begin(), CountFD));
9225 CGF.EmitStoreOfScalar(NonContigInfo.Counts[L][RevIdx], CountLVal);
9226 // Stride
9227 LValue StrideLVal = CGF.EmitLValueForField(
9228 DimsLVal, *std::next(RD->field_begin(), StrideFD));
9229 CGF.EmitStoreOfScalar(NonContigInfo.Strides[L][RevIdx], StrideLVal);
9230 }
9231 // args[I] = &dims
9232 Address DAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
9233 DimsAddr, CGM.Int8PtrTy);
9234 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
9235 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
9236 Info.PointersArray, 0, I);
9237 Address PAddr(P, CGF.getPointerAlign());
9238 CGF.Builder.CreateStore(DAddr.getPointer(), PAddr);
9239 ++L;
9240 }
9241}
9242
9243/// Emit a string constant containing the names of the values mapped to the
9244/// offloading runtime library.
9245llvm::Constant *
9246emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder,
9247 MappableExprsHandler::MappingExprInfo &MapExprs) {
9248 llvm::Constant *SrcLocStr;
9249 if (!MapExprs.getMapDecl()) {
9250 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr();
9251 } else {
9252 std::string ExprName = "";
9253 if (MapExprs.getMapExpr()) {
9254 PrintingPolicy P(CGF.getContext().getLangOpts());
9255 llvm::raw_string_ostream OS(ExprName);
9256 MapExprs.getMapExpr()->printPretty(OS, nullptr, P);
9257 OS.flush();
9258 } else {
9259 ExprName = MapExprs.getMapDecl()->getNameAsString();
9260 }
9261
9262 SourceLocation Loc = MapExprs.getMapDecl()->getLocation();
9263 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
9264 const char *FileName = PLoc.getFilename();
9265 unsigned Line = PLoc.getLine();
9266 unsigned Column = PLoc.getColumn();
9267 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FileName, ExprName.c_str(),
9268 Line, Column);
9269 }
9270 return SrcLocStr;
9271}
9272
9273/// Emit the arrays used to pass the captures and map information to the
9274/// offloading runtime library. If there is no map or capture information,
9275/// return nullptr by reference.
9276static void emitOffloadingArrays(
9277 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
9278 CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder,
9279 bool IsNonContiguous = false) {
9280 CodeGenModule &CGM = CGF.CGM;
9281 ASTContext &Ctx = CGF.getContext();
9282
9283 // Reset the array information.
9284 Info.clearArrayInfo();
9285 Info.NumberOfPtrs = CombinedInfo.BasePointers.size();
9286
9287 if (Info.NumberOfPtrs) {
9288 // Detect if we have any capture size requiring runtime evaluation of the
9289 // size so that a constant array could be eventually used.
9290 bool hasRuntimeEvaluationCaptureSize = false;
9291 for (llvm::Value *S : CombinedInfo.Sizes)
9292 if (!isa<llvm::Constant>(S)) {
9293 hasRuntimeEvaluationCaptureSize = true;
9294 break;
9295 }
9296
9297 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
9298 QualType PointerArrayType = Ctx.getConstantArrayType(
9299 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
9300 /*IndexTypeQuals=*/0);
9301
9302 Info.BasePointersArray =
9303 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
9304 Info.PointersArray =
9305 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
9306 Address MappersArray =
9307 CGF.CreateMemTemp(PointerArrayType, ".offload_mappers");
9308 Info.MappersArray = MappersArray.getPointer();
9309
9310 // If we don't have any VLA types or other types that require runtime
9311 // evaluation, we can use a constant array for the map sizes, otherwise we
9312 // need to fill up the arrays as we do for the pointers.
9313 QualType Int64Ty =
9314 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9315 if (hasRuntimeEvaluationCaptureSize) {
9316 QualType SizeArrayType = Ctx.getConstantArrayType(
9317 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
9318 /*IndexTypeQuals=*/0);
9319 Info.SizesArray =
9320 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
9321 } else {
9322 // We expect all the sizes to be constant, so we collect them to create
9323 // a constant array.
9324 SmallVector<llvm::Constant *, 16> ConstSizes;
9325 for (unsigned I = 0, E = CombinedInfo.Sizes.size(); I < E; ++I) {
9326 if (IsNonContiguous &&
9327 (CombinedInfo.Types[I] & MappableExprsHandler::OMP_MAP_NON_CONTIG)) {
9328 ConstSizes.push_back(llvm::ConstantInt::get(
9329 CGF.Int64Ty, CombinedInfo.NonContigInfo.Dims[I]));
9330 } else {
9331 ConstSizes.push_back(cast<llvm::Constant>(CombinedInfo.Sizes[I]));
9332 }
9333 }
9334
9335 auto *SizesArrayInit = llvm::ConstantArray::get(
9336 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
9337 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
9338 auto *SizesArrayGbl = new llvm::GlobalVariable(
9339 CGM.getModule(), SizesArrayInit->getType(),
9340 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
9341 SizesArrayInit, Name);
9342 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
9343 Info.SizesArray = SizesArrayGbl;
9344 }
9345
9346 // The map types are always constant so we don't need to generate code to
9347 // fill arrays. Instead, we create an array constant.
9348 SmallVector<uint64_t, 4> Mapping(CombinedInfo.Types.size(), 0);
9349 llvm::copy(CombinedInfo.Types, Mapping.begin());
9350 llvm::Constant *MapTypesArrayInit =
9351 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
9352 std::string MaptypesName =
9353 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
9354 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
9355 CGM.getModule(), MapTypesArrayInit->getType(),
9356 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
9357 MapTypesArrayInit, MaptypesName);
9358 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
9359 Info.MapTypesArray = MapTypesArrayGbl;
9360
9361 // The information types are only built if there is debug information
9362 // requested.
9363 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) {
9364 Info.MapNamesArray = llvm::Constant::getNullValue(
9365 llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo());
9366 } else {
9367 auto fillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
9368 return emitMappingInformation(CGF, OMPBuilder, MapExpr);
9369 };
9370 SmallVector<llvm::Constant *, 4> InfoMap(CombinedInfo.Exprs.size());
9371 llvm::transform(CombinedInfo.Exprs, InfoMap.begin(), fillInfoMap);
9372
9373 llvm::Constant *MapNamesArrayInit = llvm::ConstantArray::get(
9374 llvm::ArrayType::get(
9375 llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo(),
9376 CombinedInfo.Exprs.size()),
9377 InfoMap);
9378 auto *MapNamesArrayGbl = new llvm::GlobalVariable(
9379 CGM.getModule(), MapNamesArrayInit->getType(),
9380 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
9381 MapNamesArrayInit,
9382 CGM.getOpenMPRuntime().getName({"offload_mapnames"}));
9383 Info.MapNamesArray = MapNamesArrayGbl;
9384 }
9385
9386 // If there's a present map type modifier, it must not be applied to the end
9387 // of a region, so generate a separate map type array in that case.
9388 if (Info.separateBeginEndCalls()) {
9389 bool EndMapTypesDiffer = false;
9390 for (uint64_t &Type : Mapping) {
9391 if (Type & MappableExprsHandler::OMP_MAP_PRESENT) {
9392 Type &= ~MappableExprsHandler::OMP_MAP_PRESENT;
9393 EndMapTypesDiffer = true;
9394 }
9395 }
9396 if (EndMapTypesDiffer) {
9397 MapTypesArrayInit =
9398 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
9399 MaptypesName = CGM.getOpenMPRuntime().getName({"offload_maptypes"});
9400 MapTypesArrayGbl = new llvm::GlobalVariable(
9401 CGM.getModule(), MapTypesArrayInit->getType(),
9402 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
9403 MapTypesArrayInit, MaptypesName);
9404 MapTypesArrayGbl->setUnnamedAddr(
9405 llvm::GlobalValue::UnnamedAddr::Global);
9406 Info.MapTypesArrayEnd = MapTypesArrayGbl;
9407 }
9408 }
9409
9410 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
9411 llvm::Value *BPVal = *CombinedInfo.BasePointers[I];
9412 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
9413 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
9414 Info.BasePointersArray, 0, I);
9415 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
9416 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
9417 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
9418 CGF.Builder.CreateStore(BPVal, BPAddr);
9419
9420 if (Info.requiresDevicePointerInfo())
9421 if (const ValueDecl *DevVD =
9422 CombinedInfo.BasePointers[I].getDevicePtrDecl())
9423 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
9424
9425 llvm::Value *PVal = CombinedInfo.Pointers[I];
9426 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
9427 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
9428 Info.PointersArray, 0, I);
9429 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
9430 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
9431 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
9432 CGF.Builder.CreateStore(PVal, PAddr);
9433
9434 if (hasRuntimeEvaluationCaptureSize) {
9435 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
9436 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
9437 Info.SizesArray,
9438 /*Idx0=*/0,
9439 /*Idx1=*/I);
9440 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
9441 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(CombinedInfo.Sizes[I],
9442 CGM.Int64Ty,
9443 /*isSigned=*/true),
9444 SAddr);
9445 }
9446
9447 // Fill up the mapper array.
9448 llvm::Value *MFunc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
9449 if (CombinedInfo.Mappers[I]) {
9450 MFunc = CGM.getOpenMPRuntime().getOrCreateUserDefinedMapperFunc(
9451 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
9452 MFunc = CGF.Builder.CreatePointerCast(MFunc, CGM.VoidPtrTy);
9453 Info.HasMapper = true;
9454 }
9455 Address MAddr = CGF.Builder.CreateConstArrayGEP(MappersArray, I);
9456 CGF.Builder.CreateStore(MFunc, MAddr);
9457 }
9458 }
9459
9460 if (!IsNonContiguous || CombinedInfo.NonContigInfo.Offsets.empty() ||
9461 Info.NumberOfPtrs == 0)
9462 return;
9463
9464 emitNonContiguousDescriptor(CGF, CombinedInfo, Info);
9465}
9466
9467namespace {
9468/// Additional arguments for emitOffloadingArraysArgument function.
9469struct ArgumentsOptions {
9470 bool ForEndCall = false;
9471 ArgumentsOptions() = default;
9472 ArgumentsOptions(bool ForEndCall) : ForEndCall(ForEndCall) {}
9473};
9474} // namespace
9475
9476/// Emit the arguments to be passed to the runtime library based on the
9477/// arrays of base pointers, pointers, sizes, map types, and mappers. If
9478/// ForEndCall, emit map types to be passed for the end of the region instead of
9479/// the beginning.
9480static void emitOffloadingArraysArgument(
9481 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
9482 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
9483 llvm::Value *&MapTypesArrayArg, llvm::Value *&MapNamesArrayArg,
9484 llvm::Value *&MappersArrayArg, CGOpenMPRuntime::TargetDataInfo &Info,
9485 const ArgumentsOptions &Options = ArgumentsOptions()) {
9486 assert((!Options.ForEndCall || Info.separateBeginEndCalls()) &&(((!Options.ForEndCall || Info.separateBeginEndCalls()) &&
"expected region end call to runtime only when end call is separate"
) ? static_cast<void> (0) : __assert_fail ("(!Options.ForEndCall || Info.separateBeginEndCalls()) && \"expected region end call to runtime only when end call is separate\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9487, __PRETTY_FUNCTION__))
9487 "expected region end call to runtime only when end call is separate")(((!Options.ForEndCall || Info.separateBeginEndCalls()) &&
"expected region end call to runtime only when end call is separate"
) ? static_cast<void> (0) : __assert_fail ("(!Options.ForEndCall || Info.separateBeginEndCalls()) && \"expected region end call to runtime only when end call is separate\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9487, __PRETTY_FUNCTION__))
;
9488 CodeGenModule &CGM = CGF.CGM;
9489 if (Info.NumberOfPtrs) {
9490 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
9491 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
9492 Info.BasePointersArray,
9493 /*Idx0=*/0, /*Idx1=*/0);
9494 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
9495 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
9496 Info.PointersArray,
9497 /*Idx0=*/0,
9498 /*Idx1=*/0);
9499 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
9500 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
9501 /*Idx0=*/0, /*Idx1=*/0);
9502 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
9503 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
9504 Options.ForEndCall && Info.MapTypesArrayEnd ? Info.MapTypesArrayEnd
9505 : Info.MapTypesArray,
9506 /*Idx0=*/0,
9507 /*Idx1=*/0);
9508
9509 // Only emit the mapper information arrays if debug information is
9510 // requested.
9511 if (CGF.CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo)
9512 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
9513 else
9514 MapNamesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
9515 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
9516 Info.MapNamesArray,
9517 /*Idx0=*/0,
9518 /*Idx1=*/0);
9519 // If there is no user-defined mapper, set the mapper array to nullptr to
9520 // avoid an unnecessary data privatization
9521 if (!Info.HasMapper)
9522 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
9523 else
9524 MappersArrayArg =
9525 CGF.Builder.CreatePointerCast(Info.MappersArray, CGM.VoidPtrPtrTy);
9526 } else {
9527 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
9528 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
9529 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
9530 MapTypesArrayArg =
9531 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
9532 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
9533 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
9534 }
9535}
9536
9537/// Check for inner distribute directive.
9538static const OMPExecutableDirective *
9539getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
9540 const auto *CS = D.getInnermostCapturedStmt();
9541 const auto *Body =
9542 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
9543 const Stmt *ChildStmt =
9544 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
9545
9546 if (const auto *NestedDir =
9547 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
9548 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
9549 switch (D.getDirectiveKind()) {
9550 case OMPD_target:
9551 if (isOpenMPDistributeDirective(DKind))
9552 return NestedDir;
9553 if (DKind == OMPD_teams) {
9554 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
9555 /*IgnoreCaptured=*/true);
9556 if (!Body)
9557 return nullptr;
9558 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
9559 if (const auto *NND =
9560 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
9561 DKind = NND->getDirectiveKind();
9562 if (isOpenMPDistributeDirective(DKind))
9563 return NND;
9564 }
9565 }
9566 return nullptr;
9567 case OMPD_target_teams:
9568 if (isOpenMPDistributeDirective(DKind))
9569 return NestedDir;
9570 return nullptr;
9571 case OMPD_target_parallel:
9572 case OMPD_target_simd:
9573 case OMPD_target_parallel_for:
9574 case OMPD_target_parallel_for_simd:
9575 return nullptr;
9576 case OMPD_target_teams_distribute:
9577 case OMPD_target_teams_distribute_simd:
9578 case OMPD_target_teams_distribute_parallel_for:
9579 case OMPD_target_teams_distribute_parallel_for_simd:
9580 case OMPD_parallel:
9581 case OMPD_for:
9582 case OMPD_parallel_for:
9583 case OMPD_parallel_master:
9584 case OMPD_parallel_sections:
9585 case OMPD_for_simd:
9586 case OMPD_parallel_for_simd:
9587 case OMPD_cancel:
9588 case OMPD_cancellation_point:
9589 case OMPD_ordered:
9590 case OMPD_threadprivate:
9591 case OMPD_allocate:
9592 case OMPD_task:
9593 case OMPD_simd:
9594 case OMPD_tile:
9595 case OMPD_sections:
9596 case OMPD_section:
9597 case OMPD_single:
9598 case OMPD_master:
9599 case OMPD_critical:
9600 case OMPD_taskyield:
9601 case OMPD_barrier:
9602 case OMPD_taskwait:
9603 case OMPD_taskgroup:
9604 case OMPD_atomic:
9605 case OMPD_flush:
9606 case OMPD_depobj:
9607 case OMPD_scan:
9608 case OMPD_teams:
9609 case OMPD_target_data:
9610 case OMPD_target_exit_data:
9611 case OMPD_target_enter_data:
9612 case OMPD_distribute:
9613 case OMPD_distribute_simd:
9614 case OMPD_distribute_parallel_for:
9615 case OMPD_distribute_parallel_for_simd:
9616 case OMPD_teams_distribute:
9617 case OMPD_teams_distribute_simd:
9618 case OMPD_teams_distribute_parallel_for:
9619 case OMPD_teams_distribute_parallel_for_simd:
9620 case OMPD_target_update:
9621 case OMPD_declare_simd:
9622 case OMPD_declare_variant:
9623 case OMPD_begin_declare_variant:
9624 case OMPD_end_declare_variant:
9625 case OMPD_declare_target:
9626 case OMPD_end_declare_target:
9627 case OMPD_declare_reduction:
9628 case OMPD_declare_mapper:
9629 case OMPD_taskloop:
9630 case OMPD_taskloop_simd:
9631 case OMPD_master_taskloop:
9632 case OMPD_master_taskloop_simd:
9633 case OMPD_parallel_master_taskloop:
9634 case OMPD_parallel_master_taskloop_simd:
9635 case OMPD_requires:
9636 case OMPD_unknown:
9637 default:
9638 llvm_unreachable("Unexpected directive.")::llvm::llvm_unreachable_internal("Unexpected directive.", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9638)
;
9639 }
9640 }
9641
9642 return nullptr;
9643}
9644
9645/// Emit the user-defined mapper function. The code generation follows the
9646/// pattern in the example below.
9647/// \code
9648/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
9649/// void *base, void *begin,
9650/// int64_t size, int64_t type,
9651/// void *name = nullptr) {
9652/// // Allocate space for an array section first or add a base/begin for
9653/// // pointer dereference.
9654/// if ((size > 1 || (base != begin && maptype.IsPtrAndObj)) &&
9655/// !maptype.IsDelete)
9656/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
9657/// size*sizeof(Ty), clearToFromMember(type));
9658/// // Map members.
9659/// for (unsigned i = 0; i < size; i++) {
9660/// // For each component specified by this mapper:
9661/// for (auto c : begin[i]->all_components) {
9662/// if (c.hasMapper())
9663/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
9664/// c.arg_type, c.arg_name);
9665/// else
9666/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
9667/// c.arg_begin, c.arg_size, c.arg_type,
9668/// c.arg_name);
9669/// }
9670/// }
9671/// // Delete the array section.
9672/// if (size > 1 && maptype.IsDelete)
9673/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
9674/// size*sizeof(Ty), clearToFromMember(type));
9675/// }
9676/// \endcode
9677void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
9678 CodeGenFunction *CGF) {
9679 if (UDMMap.count(D) > 0)
9680 return;
9681 ASTContext &C = CGM.getContext();
9682 QualType Ty = D->getType();
9683 QualType PtrTy = C.getPointerType(Ty).withRestrict();
9684 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
9685 auto *MapperVarDecl =
9686 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
9687 SourceLocation Loc = D->getLocation();
9688 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
9689
9690 // Prepare mapper function arguments and attributes.
9691 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
9692 C.VoidPtrTy, ImplicitParamDecl::Other);
9693 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
9694 ImplicitParamDecl::Other);
9695 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
9696 C.VoidPtrTy, ImplicitParamDecl::Other);
9697 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
9698 ImplicitParamDecl::Other);
9699 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
9700 ImplicitParamDecl::Other);
9701 ImplicitParamDecl NameArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
9702 ImplicitParamDecl::Other);
9703 FunctionArgList Args;
9704 Args.push_back(&HandleArg);
9705 Args.push_back(&BaseArg);
9706 Args.push_back(&BeginArg);
9707 Args.push_back(&SizeArg);
9708 Args.push_back(&TypeArg);
9709 Args.push_back(&NameArg);
9710 const CGFunctionInfo &FnInfo =
9711 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
9712 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
9713 SmallString<64> TyStr;
9714 llvm::raw_svector_ostream Out(TyStr);
9715 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
9716 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
9717 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
9718 Name, &CGM.getModule());
9719 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
9720 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
9721 // Start the mapper function code generation.
9722 CodeGenFunction MapperCGF(CGM);
9723 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
9724 // Compute the starting and end addresses of array elements.
9725 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
9726 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
9727 C.getPointerType(Int64Ty), Loc);
9728 // Prepare common arguments for array initiation and deletion.
9729 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
9730 MapperCGF.GetAddrOfLocalVar(&HandleArg),
9731 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9732 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
9733 MapperCGF.GetAddrOfLocalVar(&BaseArg),
9734 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9735 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
9736 MapperCGF.GetAddrOfLocalVar(&BeginArg),
9737 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9738 // Convert the size in bytes into the number of array elements.
9739 Size = MapperCGF.Builder.CreateExactUDiv(
9740 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9741 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
9742 BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy));
9743 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
9744 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
9745 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
9746 C.getPointerType(Int64Ty), Loc);
9747 llvm::Value *MapName = MapperCGF.EmitLoadOfScalar(
9748 MapperCGF.GetAddrOfLocalVar(&NameArg),
9749 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9750
9751 // Emit array initiation if this is an array section and \p MapType indicates
9752 // that memory allocation is required.
9753 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
9754 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9755 MapName, ElementSize, HeadBB, /*IsInit=*/true);
9756
9757 // Emit a for loop to iterate through SizeArg of elements and map all of them.
9758
9759 // Emit the loop header block.
9760 MapperCGF.EmitBlock(HeadBB);
9761 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
9762 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
9763 // Evaluate whether the initial condition is satisfied.
9764 llvm::Value *IsEmpty =
9765 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
9766 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
9767 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
9768
9769 // Emit the loop body block.
9770 MapperCGF.EmitBlock(BodyBB);
9771 llvm::BasicBlock *LastBB = BodyBB;
9772 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
9773 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
9774 PtrPHI->addIncoming(PtrBegin, EntryBB);
9775 Address PtrCurrent =
9776 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
9777 .getAlignment()
9778 .alignmentOfArrayElement(ElementSize));
9779 // Privatize the declared variable of mapper to be the current array element.
9780 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
9781 Scope.addPrivate(MapperVarDecl, [PtrCurrent]() { return PtrCurrent; });
9782 (void)Scope.Privatize();
9783
9784 // Get map clause information. Fill up the arrays with all mapped variables.
9785 MappableExprsHandler::MapCombinedInfoTy Info;
9786 MappableExprsHandler MEHandler(*D, MapperCGF);
9787 MEHandler.generateAllInfoForMapper(Info);
9788
9789 // Call the runtime API __tgt_mapper_num_components to get the number of
9790 // pre-existing components.
9791 llvm::Value *OffloadingArgs[] = {Handle};
9792 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
9793 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
9794 OMPRTL___tgt_mapper_num_components),
9795 OffloadingArgs);
9796 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
9797 PreviousSize,
9798 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
9799
9800 // Fill up the runtime mapper handle for all components.
9801 for (unsigned I = 0; I < Info.BasePointers.size(); ++I) {
9802 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
9803 *Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9804 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
9805 Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9806 llvm::Value *CurSizeArg = Info.Sizes[I];
9807 llvm::Value *CurNameArg =
9808 (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo)
9809 ? llvm::ConstantPointerNull::get(CGM.VoidPtrTy)
9810 : emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]);
9811
9812 // Extract the MEMBER_OF field from the map type.
9813 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(Info.Types[I]);
9814 llvm::Value *MemberMapType =
9815 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
9816
9817 // Combine the map type inherited from user-defined mapper with that
9818 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
9819 // bits of the \a MapType, which is the input argument of the mapper
9820 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
9821 // bits of MemberMapType.
9822 // [OpenMP 5.0], 1.2.6. map-type decay.
9823 // | alloc | to | from | tofrom | release | delete
9824 // ----------------------------------------------------------
9825 // alloc | alloc | alloc | alloc | alloc | release | delete
9826 // to | alloc | to | alloc | to | release | delete
9827 // from | alloc | alloc | from | from | release | delete
9828 // tofrom | alloc | to | from | tofrom | release | delete
9829 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9830 MapType,
9831 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9832 MappableExprsHandler::OMP_MAP_FROM));
9833 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9834 llvm::BasicBlock *AllocElseBB =
9835 MapperCGF.createBasicBlock("omp.type.alloc.else");
9836 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9837 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9838 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9839 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9840 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9841 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9842 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9843 MapperCGF.EmitBlock(AllocBB);
9844 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9845 MemberMapType,
9846 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9847 MappableExprsHandler::OMP_MAP_FROM)));
9848 MapperCGF.Builder.CreateBr(EndBB);
9849 MapperCGF.EmitBlock(AllocElseBB);
9850 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9851 LeftToFrom,
9852 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9853 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9854 // In case of to, clear OMP_MAP_FROM.
9855 MapperCGF.EmitBlock(ToBB);
9856 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9857 MemberMapType,
9858 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9859 MapperCGF.Builder.CreateBr(EndBB);
9860 MapperCGF.EmitBlock(ToElseBB);
9861 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9862 LeftToFrom,
9863 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9864 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9865 // In case of from, clear OMP_MAP_TO.
9866 MapperCGF.EmitBlock(FromBB);
9867 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9868 MemberMapType,
9869 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9870 // In case of tofrom, do nothing.
9871 MapperCGF.EmitBlock(EndBB);
9872 LastBB = EndBB;
9873 llvm::PHINode *CurMapType =
9874 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9875 CurMapType->addIncoming(AllocMapType, AllocBB);
9876 CurMapType->addIncoming(ToMapType, ToBB);
9877 CurMapType->addIncoming(FromMapType, FromBB);
9878 CurMapType->addIncoming(MemberMapType, ToElseBB);
9879
9880 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9881 CurSizeArg, CurMapType, CurNameArg};
9882 if (Info.Mappers[I]) {
9883 // Call the corresponding mapper function.
9884 llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc(
9885 cast<OMPDeclareMapperDecl>(Info.Mappers[I]));
9886 assert(MapperFunc && "Expect a valid mapper function is available.")((MapperFunc && "Expect a valid mapper function is available."
) ? static_cast<void> (0) : __assert_fail ("MapperFunc && \"Expect a valid mapper function is available.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 9886, __PRETTY_FUNCTION__))
;
9887 MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs);
9888 } else {
9889 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9890 // data structure.
9891 MapperCGF.EmitRuntimeCall(
9892 OMPBuilder.getOrCreateRuntimeFunction(
9893 CGM.getModule(), OMPRTL___tgt_push_mapper_component),
9894 OffloadingArgs);
9895 }
9896 }
9897
9898 // Update the pointer to point to the next element that needs to be mapped,
9899 // and check whether we have mapped all elements.
9900 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9901 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9902 PtrPHI->addIncoming(PtrNext, LastBB);
9903 llvm::Value *IsDone =
9904 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9905 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9906 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9907
9908 MapperCGF.EmitBlock(ExitBB);
9909 // Emit array deletion if this is an array section and \p MapType indicates
9910 // that deletion is required.
9911 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9912 MapName, ElementSize, DoneBB, /*IsInit=*/false);
9913
9914 // Emit the function exit block.
9915 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9916 MapperCGF.FinishFunction();
9917 UDMMap.try_emplace(D, Fn);
9918 if (CGF) {
9919 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9920 Decls.second.push_back(D);
9921 }
9922}
9923
9924/// Emit the array initialization or deletion portion for user-defined mapper
9925/// code generation. First, it evaluates whether an array section is mapped and
9926/// whether the \a MapType instructs to delete this section. If \a IsInit is
9927/// true, and \a MapType indicates to not delete this array, array
9928/// initialization code is generated. If \a IsInit is false, and \a MapType
9929/// indicates to not this array, array deletion code is generated.
9930void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9931 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9932 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9933 llvm::Value *MapName, CharUnits ElementSize, llvm::BasicBlock *ExitBB,
9934 bool IsInit) {
9935 StringRef Prefix = IsInit ? ".init" : ".del";
9936
9937 // Evaluate if this is an array section.
9938 llvm::BasicBlock *BodyBB =
9939 MapperCGF.createBasicBlock(getName({"omp.array", Prefix}));
9940 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGT(
9941 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9942 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9943 MapType,
9944 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9945 llvm::Value *DeleteCond;
9946 llvm::Value *Cond;
9947 if (IsInit) {
9948 // base != begin?
9949 llvm::Value *BaseIsBegin = MapperCGF.Builder.CreateIsNotNull(
9950 MapperCGF.Builder.CreatePtrDiff(Base, Begin));
9951 // IsPtrAndObj?
9952 llvm::Value *PtrAndObjBit = MapperCGF.Builder.CreateAnd(
9953 MapType,
9954 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_PTR_AND_OBJ));
9955 PtrAndObjBit = MapperCGF.Builder.CreateIsNotNull(PtrAndObjBit);
9956 BaseIsBegin = MapperCGF.Builder.CreateAnd(BaseIsBegin, PtrAndObjBit);
9957 Cond = MapperCGF.Builder.CreateOr(IsArray, BaseIsBegin);
9958 DeleteCond = MapperCGF.Builder.CreateIsNull(
9959 DeleteBit, getName({"omp.array", Prefix, ".delete"}));
9960 } else {
9961 Cond = IsArray;
9962 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9963 DeleteBit, getName({"omp.array", Prefix, ".delete"}));
9964 }
9965 Cond = MapperCGF.Builder.CreateAnd(Cond, DeleteCond);
9966 MapperCGF.Builder.CreateCondBr(Cond, BodyBB, ExitBB);
9967
9968 MapperCGF.EmitBlock(BodyBB);
9969 // Get the array size by multiplying element size and element number (i.e., \p
9970 // Size).
9971 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9972 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9973 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9974 // memory allocation/deletion purpose only.
9975 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9976 MapType,
9977 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9978 MappableExprsHandler::OMP_MAP_FROM |
9979 MappableExprsHandler::OMP_MAP_MEMBER_OF)));
9980
9981 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9982 // data structure.
9983 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin,
9984 ArraySize, MapTypeArg, MapName};
9985 MapperCGF.EmitRuntimeCall(
9986 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
9987 OMPRTL___tgt_push_mapper_component),
9988 OffloadingArgs);
9989}
9990
9991llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc(
9992 const OMPDeclareMapperDecl *D) {
9993 auto I = UDMMap.find(D);
9994 if (I != UDMMap.end())
9995 return I->second;
9996 emitUserDefinedMapper(D);
9997 return UDMMap.lookup(D);
9998}
9999
10000void CGOpenMPRuntime::emitTargetNumIterationsCall(
10001 CodeGenFunction &CGF, const OMPExecutableDirective &D,
10002 llvm::Value *DeviceID,
10003 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
10004 const OMPLoopDirective &D)>
10005 SizeEmitter) {
10006 OpenMPDirectiveKind Kind = D.getDirectiveKind();
10007 const OMPExecutableDirective *TD = &D;
10008 // Get nested teams distribute kind directive, if any.
10009 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
10010 TD = getNestedDistributeDirective(CGM.getContext(), D);
10011 if (!TD)
10012 return;
10013 const auto *LD = cast<OMPLoopDirective>(TD);
10014 auto &&CodeGen = [LD, DeviceID, SizeEmitter, &D, this](CodeGenFunction &CGF,
10015 PrePostActionTy &) {
10016 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
10017 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
10018 llvm::Value *Args[] = {RTLoc, DeviceID, NumIterations};
10019 CGF.EmitRuntimeCall(
10020 OMPBuilder.getOrCreateRuntimeFunction(
10021 CGM.getModule(), OMPRTL___kmpc_push_target_tripcount_mapper),
10022 Args);
10023 }
10024 };
10025 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
10026}
10027
10028void CGOpenMPRuntime::emitTargetCall(
10029 CodeGenFunction &CGF, const OMPExecutableDirective &D,
10030 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
10031 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device,
10032 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
10033 const OMPLoopDirective &D)>
10034 SizeEmitter) {
10035 if (!CGF.HaveInsertPoint())
10036 return;
10037
10038 assert(OutlinedFn && "Invalid outlined function!")((OutlinedFn && "Invalid outlined function!") ? static_cast
<void> (0) : __assert_fail ("OutlinedFn && \"Invalid outlined function!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10038, __PRETTY_FUNCTION__))
;
10039
10040 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() ||
10041 D.hasClausesOfKind<OMPNowaitClause>();
10042 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
10043 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
10044 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
10045 PrePostActionTy &) {
10046 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
10047 };
10048 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
10049
10050 CodeGenFunction::OMPTargetDataInfo InputInfo;
10051 llvm::Value *MapTypesArray = nullptr;
10052 llvm::Value *MapNamesArray = nullptr;
10053 // Fill up the pointer arrays and transfer execution to the device.
10054 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
10055 &MapTypesArray, &MapNamesArray, &CS, RequiresOuterTask,
10056 &CapturedVars,
10057 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
10058 if (Device.getInt() == OMPC_DEVICE_ancestor) {
10059 // Reverse offloading is not supported, so just execute on the host.
10060 if (RequiresOuterTask) {
10061 CapturedVars.clear();
10062 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
10063 }
10064 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
10065 return;
10066 }
10067
10068 // On top of the arrays that were filled up, the target offloading call
10069 // takes as arguments the device id as well as the host pointer. The host
10070 // pointer is used by the runtime library to identify the current target
10071 // region, so it only has to be unique and not necessarily point to
10072 // anything. It could be the pointer to the outlined function that
10073 // implements the target region, but we aren't using that so that the
10074 // compiler doesn't need to keep that, and could therefore inline the host
10075 // function if proven worthwhile during optimization.
10076
10077 // From this point on, we need to have an ID of the target region defined.
10078 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10078, __PRETTY_FUNCTION__))
;
10079
10080 // Emit device ID if any.
10081 llvm::Value *DeviceID;
10082 if (Device.getPointer()) {
10083 assert((Device.getInt() == OMPC_DEVICE_unknown ||(((Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() ==
OMPC_DEVICE_device_num) && "Expected device_num modifier."
) ? static_cast<void> (0) : __assert_fail ("(Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() == OMPC_DEVICE_device_num) && \"Expected device_num modifier.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10085, __PRETTY_FUNCTION__))
10084 Device.getInt() == OMPC_DEVICE_device_num) &&(((Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() ==
OMPC_DEVICE_device_num) && "Expected device_num modifier."
) ? static_cast<void> (0) : __assert_fail ("(Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() == OMPC_DEVICE_device_num) && \"Expected device_num modifier.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10085, __PRETTY_FUNCTION__))
10085 "Expected device_num modifier.")(((Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() ==
OMPC_DEVICE_device_num) && "Expected device_num modifier."
) ? static_cast<void> (0) : __assert_fail ("(Device.getInt() == OMPC_DEVICE_unknown || Device.getInt() == OMPC_DEVICE_device_num) && \"Expected device_num modifier.\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10085, __PRETTY_FUNCTION__))
;
10086 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer());
10087 DeviceID =
10088 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true);
10089 } else {
10090 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10091 }
10092
10093 // Emit the number of elements in the offloading arrays.
10094 llvm::Value *PointerNum =
10095 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
10096
10097 // Return value of the runtime offloading call.
10098 llvm::Value *Return;
10099
10100 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
10101 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
10102
10103 // Source location for the ident struct
10104 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
10105
10106 // Emit tripcount for the target loop-based directive.
10107 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
10108
10109 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
10110 // The target region is an outlined function launched by the runtime
10111 // via calls __tgt_target() or __tgt_target_teams().
10112 //
10113 // __tgt_target() launches a target region with one team and one thread,
10114 // executing a serial region. This master thread may in turn launch
10115 // more threads within its team upon encountering a parallel region,
10116 // however, no additional teams can be launched on the device.
10117 //
10118 // __tgt_target_teams() launches a target region with one or more teams,
10119 // each with one or more threads. This call is required for target
10120 // constructs such as:
10121 // 'target teams'
10122 // 'target' / 'teams'
10123 // 'target teams distribute parallel for'
10124 // 'target parallel'
10125 // and so on.
10126 //
10127 // Note that on the host and CPU targets, the runtime implementation of
10128 // these calls simply call the outlined function without forking threads.
10129 // The outlined functions themselves have runtime calls to
10130 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
10131 // the compiler in emitTeamsCall() and emitParallelCall().
10132 //
10133 // In contrast, on the NVPTX target, the implementation of
10134 // __tgt_target_teams() launches a GPU kernel with the requested number
10135 // of teams and threads so no additional calls to the runtime are required.
10136 if (NumTeams) {
10137 // If we have NumTeams defined this means that we have an enclosed teams
10138 // region. Therefore we also expect to have NumThreads defined. These two
10139 // values should be defined in the presence of a teams directive,
10140 // regardless of having any clauses associated. If the user is using teams
10141 // but no clauses, these two values will be the default that should be
10142 // passed to the runtime library - a 32-bit integer with the value zero.
10143 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10144, __PRETTY_FUNCTION__))
10144 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10144, __PRETTY_FUNCTION__))
;
10145 llvm::Value *OffloadingArgs[] = {RTLoc,
10146 DeviceID,
10147 OutlinedFnID,
10148 PointerNum,
10149 InputInfo.BasePointersArray.getPointer(),
10150 InputInfo.PointersArray.getPointer(),
10151 InputInfo.SizesArray.getPointer(),
10152 MapTypesArray,
10153 MapNamesArray,
10154 InputInfo.MappersArray.getPointer(),
10155 NumTeams,
10156 NumThreads};
10157 Return = CGF.EmitRuntimeCall(
10158 OMPBuilder.getOrCreateRuntimeFunction(
10159 CGM.getModule(), HasNowait
10160 ? OMPRTL___tgt_target_teams_nowait_mapper
10161 : OMPRTL___tgt_target_teams_mapper),
10162 OffloadingArgs);
10163 } else {
10164 llvm::Value *OffloadingArgs[] = {RTLoc,
10165 DeviceID,
10166 OutlinedFnID,
10167 PointerNum,
10168 InputInfo.BasePointersArray.getPointer(),
10169 InputInfo.PointersArray.getPointer(),
10170 InputInfo.SizesArray.getPointer(),
10171 MapTypesArray,
10172 MapNamesArray,
10173 InputInfo.MappersArray.getPointer()};
10174 Return = CGF.EmitRuntimeCall(
10175 OMPBuilder.getOrCreateRuntimeFunction(
10176 CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper
10177 : OMPRTL___tgt_target_mapper),
10178 OffloadingArgs);
10179 }
10180
10181 // Check the error code and execute the host version if required.
10182 llvm::BasicBlock *OffloadFailedBlock =
10183 CGF.createBasicBlock("omp_offload.failed");
10184 llvm::BasicBlock *OffloadContBlock =
10185 CGF.createBasicBlock("omp_offload.cont");
10186 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
10187 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
10188
10189 CGF.EmitBlock(OffloadFailedBlock);
10190 if (RequiresOuterTask) {
10191 CapturedVars.clear();
10192 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
10193 }
10194 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
10195 CGF.EmitBranch(OffloadContBlock);
10196
10197 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
10198 };
10199
10200 // Notify that the host version must be executed.
10201 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
10202 RequiresOuterTask](CodeGenFunction &CGF,
10203 PrePostActionTy &) {
10204 if (RequiresOuterTask) {
10205 CapturedVars.clear();
10206 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
10207 }
10208 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
10209 };
10210
10211 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
10212 &MapNamesArray, &CapturedVars, RequiresOuterTask,
10213 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
10214 // Fill up the arrays with all the captured variables.
10215 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10216
10217 // Get mappable expression information.
10218 MappableExprsHandler MEHandler(D, CGF);
10219 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10220 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10221
10222 auto RI = CS.getCapturedRecordDecl()->field_begin();
10223 auto *CV = CapturedVars.begin();
10224 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
10225 CE = CS.capture_end();
10226 CI != CE; ++CI, ++RI, ++CV) {
10227 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10228 MappableExprsHandler::StructRangeInfoTy PartialStruct;
10229
10230 // VLA sizes are passed to the outlined region by copy and do not have map
10231 // information associated.
10232 if (CI->capturesVariableArrayType()) {
10233 CurInfo.Exprs.push_back(nullptr);
10234 CurInfo.BasePointers.push_back(*CV);
10235 CurInfo.Pointers.push_back(*CV);
10236 CurInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
10237 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
10238 // Copy to the device as an argument. No need to retrieve it.
10239 CurInfo.Types.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
10240 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
10241 MappableExprsHandler::OMP_MAP_IMPLICIT);
10242 CurInfo.Mappers.push_back(nullptr);
10243 } else {
10244 // If we have any information in the map clause, we use it, otherwise we
10245 // just do a default mapping.
10246 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct);
10247 if (!CI->capturesThis())
10248 MappedVarSet.insert(CI->getCapturedVar());
10249 else
10250 MappedVarSet.insert(nullptr);
10251 if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid())
10252 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10253 // Generate correct mapping for variables captured by reference in
10254 // lambdas.
10255 if (CI->capturesVariable())
10256 MEHandler.generateInfoForLambdaCaptures(CI->getCapturedVar(), *CV,
10257 CurInfo, LambdaPointers);
10258 }
10259 // We expect to have at least an element of information for this capture.
10260 assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) &&(((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid
()) && "Non-existing map pointer for capture!") ? static_cast
<void> (0) : __assert_fail ("(!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) && \"Non-existing map pointer for capture!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10261, __PRETTY_FUNCTION__))
10261 "Non-existing map pointer for capture!")(((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid
()) && "Non-existing map pointer for capture!") ? static_cast
<void> (0) : __assert_fail ("(!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) && \"Non-existing map pointer for capture!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10261, __PRETTY_FUNCTION__))
;
10262 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&((CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
CurInfo.BasePointers.size() == CurInfo.Types.size() &&
CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
"Inconsistent map information sizes!") ? static_cast<void
> (0) : __assert_fail ("CurInfo.BasePointers.size() == CurInfo.Pointers.size() && CurInfo.BasePointers.size() == CurInfo.Sizes.size() && CurInfo.BasePointers.size() == CurInfo.Types.size() && CurInfo.BasePointers.size() == CurInfo.Mappers.size() && \"Inconsistent map information sizes!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10266, __PRETTY_FUNCTION__))
10263 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&((CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
CurInfo.BasePointers.size() == CurInfo.Types.size() &&
CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
"Inconsistent map information sizes!") ? static_cast<void
> (0) : __assert_fail ("CurInfo.BasePointers.size() == CurInfo.Pointers.size() && CurInfo.BasePointers.size() == CurInfo.Sizes.size() && CurInfo.BasePointers.size() == CurInfo.Types.size() && CurInfo.BasePointers.size() == CurInfo.Mappers.size() && \"Inconsistent map information sizes!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10266, __PRETTY_FUNCTION__))
10264 CurInfo.BasePointers.size() == CurInfo.Types.size() &&((CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
CurInfo.BasePointers.size() == CurInfo.Types.size() &&
CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
"Inconsistent map information sizes!") ? static_cast<void
> (0) : __assert_fail ("CurInfo.BasePointers.size() == CurInfo.Pointers.size() && CurInfo.BasePointers.size() == CurInfo.Sizes.size() && CurInfo.BasePointers.size() == CurInfo.Types.size() && CurInfo.BasePointers.size() == CurInfo.Mappers.size() && \"Inconsistent map information sizes!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10266, __PRETTY_FUNCTION__))
10265 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&((CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
CurInfo.BasePointers.size() == CurInfo.Types.size() &&
CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
"Inconsistent map information sizes!") ? static_cast<void
> (0) : __assert_fail ("CurInfo.BasePointers.size() == CurInfo.Pointers.size() && CurInfo.BasePointers.size() == CurInfo.Sizes.size() && CurInfo.BasePointers.size() == CurInfo.Types.size() && CurInfo.BasePointers.size() == CurInfo.Mappers.size() && \"Inconsistent map information sizes!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10266, __PRETTY_FUNCTION__))
10266 "Inconsistent map information sizes!")((CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
CurInfo.BasePointers.size() == CurInfo.Types.size() &&
CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
"Inconsistent map information sizes!") ? static_cast<void
> (0) : __assert_fail ("CurInfo.BasePointers.size() == CurInfo.Pointers.size() && CurInfo.BasePointers.size() == CurInfo.Sizes.size() && CurInfo.BasePointers.size() == CurInfo.Types.size() && CurInfo.BasePointers.size() == CurInfo.Mappers.size() && \"Inconsistent map information sizes!\""
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10266, __PRETTY_FUNCTION__))
;
10267
10268 // If there is an entry in PartialStruct it means we have a struct with
10269 // individual members mapped. Emit an extra combined entry.
10270 if (PartialStruct.Base.isValid()) {
10271 CombinedInfo.append(PartialStruct.PreliminaryMapData);
10272 MEHandler.emitCombinedEntry(
10273 CombinedInfo, CurInfo.Types, PartialStruct, nullptr,
10274 !PartialStruct.PreliminaryMapData.BasePointers.empty());
10275 }
10276
10277 // We need to append the results of this capture to what we already have.
10278 CombinedInfo.append(CurInfo);
10279 }
10280 // Adjust MEMBER_OF flags for the lambdas captures.
10281 MEHandler.adjustMemberOfForLambdaCaptures(
10282 LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers,
10283 CombinedInfo.Types);
10284 // Map any list items in a map clause that were not captures because they
10285 // weren't referenced within the construct.
10286 MEHandler.generateAllInfo(CombinedInfo, MappedVarSet);
10287
10288 TargetDataInfo Info;
10289 // Fill up the arrays and create the arguments.
10290 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder);
10291 emitOffloadingArraysArgument(
10292 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray,
10293 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info,
10294 {/*ForEndTask=*/false});
10295
10296 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10297 InputInfo.BasePointersArray =
10298 Address(Info.BasePointersArray, CGM.getPointerAlign());
10299 InputInfo.PointersArray =
10300 Address(Info.PointersArray, CGM.getPointerAlign());
10301 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
10302 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign());
10303 MapTypesArray = Info.MapTypesArray;
10304 MapNamesArray = Info.MapNamesArray;
10305 if (RequiresOuterTask)
10306 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10307 else
10308 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
10309 };
10310
10311 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
10312 CodeGenFunction &CGF, PrePostActionTy &) {
10313 if (RequiresOuterTask) {
10314 CodeGenFunction::OMPTargetDataInfo InputInfo;
10315 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
10316 } else {
10317 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
10318 }
10319 };
10320
10321 // If we have a target function ID it means that we need to support
10322 // offloading, otherwise, just execute on the host. We need to execute on host
10323 // regardless of the conditional in the if clause if, e.g., the user do not
10324 // specify target triples.
10325 if (OutlinedFnID) {
10326 if (IfCond) {
10327 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
10328 } else {
10329 RegionCodeGenTy ThenRCG(TargetThenGen);
10330 ThenRCG(CGF);
10331 }
10332 } else {
10333 RegionCodeGenTy ElseRCG(TargetElseGen);
10334 ElseRCG(CGF);
10335 }
10336}
10337
10338void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
10339 StringRef ParentName) {
10340 if (!S)
10341 return;
10342
10343 // Codegen OMP target directives that offload compute to the device.
10344 bool RequiresDeviceCodegen =
10345 isa<OMPExecutableDirective>(S) &&
10346 isOpenMPTargetExecutionDirective(
10347 cast<OMPExecutableDirective>(S)->getDirectiveKind());
10348
10349 if (RequiresDeviceCodegen) {
10350 const auto &E = *cast<OMPExecutableDirective>(S);
10351 unsigned DeviceID;
10352 unsigned FileID;
10353 unsigned Line;
10354 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
10355 FileID, Line);
10356
10357 // Is this a target region that should not be emitted as an entry point? If
10358 // so just signal we are done with this target region.
10359 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
10360 ParentName, Line))
10361 return;
10362
10363 switch (E.getDirectiveKind()) {
10364 case OMPD_target:
10365 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
10366 cast<OMPTargetDirective>(E));
10367 break;
10368 case OMPD_target_parallel:
10369 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
10370 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
10371 break;
10372 case OMPD_target_teams:
10373 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
10374 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
10375 break;
10376 case OMPD_target_teams_distribute:
10377 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
10378 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
10379 break;
10380 case OMPD_target_teams_distribute_simd:
10381 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
10382 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
10383 break;
10384 case OMPD_target_parallel_for:
10385 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
10386 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
10387 break;
10388 case OMPD_target_parallel_for_simd:
10389 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
10390 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
10391 break;
10392 case OMPD_target_simd:
10393 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
10394 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
10395 break;
10396 case OMPD_target_teams_distribute_parallel_for:
10397 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
10398 CGM, ParentName,
10399 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
10400 break;
10401 case OMPD_target_teams_distribute_parallel_for_simd:
10402 CodeGenFunction::
10403 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
10404 CGM, ParentName,
10405 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
10406 break;
10407 case OMPD_parallel:
10408 case OMPD_for:
10409 case OMPD_parallel_for:
10410 case OMPD_parallel_master:
10411 case OMPD_parallel_sections:
10412 case OMPD_for_simd:
10413 case OMPD_parallel_for_simd:
10414 case OMPD_cancel:
10415 case OMPD_cancellation_point:
10416 case OMPD_ordered:
10417 case OMPD_threadprivate:
10418 case OMPD_allocate:
10419 case OMPD_task:
10420 case OMPD_simd:
10421 case OMPD_tile:
10422 case OMPD_sections:
10423 case OMPD_section:
10424 case OMPD_single:
10425 case OMPD_master:
10426 case OMPD_critical:
10427 case OMPD_taskyield:
10428 case OMPD_barrier:
10429 case OMPD_taskwait:
10430 case OMPD_taskgroup:
10431 case OMPD_atomic:
10432 case OMPD_flush:
10433 case OMPD_depobj:
10434 case OMPD_scan:
10435 case OMPD_teams:
10436 case OMPD_target_data:
10437 case OMPD_target_exit_data:
10438 case OMPD_target_enter_data:
10439 case OMPD_distribute:
10440 case OMPD_distribute_simd:
10441 case OMPD_distribute_parallel_for:
10442 case OMPD_distribute_parallel_for_simd:
10443 case OMPD_teams_distribute:
10444 case OMPD_teams_distribute_simd:
10445 case OMPD_teams_distribute_parallel_for:
10446 case OMPD_teams_distribute_parallel_for_simd:
10447 case OMPD_target_update:
10448 case OMPD_declare_simd:
10449 case OMPD_declare_variant:
10450 case OMPD_begin_declare_variant:
10451 case OMPD_end_declare_variant:
10452 case OMPD_declare_target:
10453 case OMPD_end_declare_target:
10454 case OMPD_declare_reduction:
10455 case OMPD_declare_mapper:
10456 case OMPD_taskloop:
10457 case OMPD_taskloop_simd:
10458 case OMPD_master_taskloop:
10459 case OMPD_master_taskloop_simd:
10460 case OMPD_parallel_master_taskloop:
10461 case OMPD_parallel_master_taskloop_simd:
10462 case OMPD_requires:
10463 case OMPD_unknown:
10464 default:
10465 llvm_unreachable("Unknown target directive for OpenMP device codegen.")::llvm::llvm_unreachable_internal("Unknown target directive for OpenMP device codegen."
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10465)
;
10466 }
10467 return;
10468 }
10469
10470 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
10471 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
10472 return;
10473
10474 scanForTargetRegionsFunctions(E->getRawStmt(), ParentName);
10475 return;
10476 }
10477
10478 // If this is a lambda function, look into its body.
10479 if (const auto *L = dyn_cast<LambdaExpr>(S))
10480 S = L->getBody();
10481
10482 // Keep looking for target regions recursively.
10483 for (const Stmt *II : S->children())
10484 scanForTargetRegionsFunctions(II, ParentName);
10485}
10486
10487bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
10488 // If emitting code for the host, we do not process FD here. Instead we do
10489 // the normal code generation.
10490 if (!CGM.getLangOpts().OpenMPIsDevice) {
10491 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
10492 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
10493 OMPDeclareTargetDeclAttr::getDeviceType(FD);
10494 // Do not emit device_type(nohost) functions for the host.
10495 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
10496 return true;
10497 }
10498 return false;
10499 }
10500
10501 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
10502 // Try to detect target regions in the function.
10503 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
10504 StringRef Name = CGM.getMangledName(GD);
10505 scanForTargetRegionsFunctions(FD->getBody(), Name);
10506 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
10507 OMPDeclareTargetDeclAttr::getDeviceType(FD);
10508 // Do not emit device_type(nohost) functions for the host.
10509 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
10510 return true;
10511 }
10512
10513 // Do not to emit function if it is not marked as declare target.
10514 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
10515 AlreadyEmittedTargetDecls.count(VD) == 0;
10516}
10517
10518bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
10519 if (!CGM.getLangOpts().OpenMPIsDevice)
10520 return false;
10521
10522 // Check if there are Ctors/Dtors in this declaration and look for target
10523 // regions in it. We use the complete variant to produce the kernel name
10524 // mangling.
10525 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
10526 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
10527 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
10528 StringRef ParentName =
10529 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
10530 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
10531 }
10532 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
10533 StringRef ParentName =
10534 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
10535 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
10536 }
10537 }
10538
10539 // Do not to emit variable if it is not marked as declare target.
10540 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10541 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
10542 cast<VarDecl>(GD.getDecl()));
10543 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
10544 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
10545 HasRequiresUnifiedSharedMemory)) {
10546 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
10547 return true;
10548 }
10549 return false;
10550}
10551
10552llvm::Constant *
10553CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
10554 const VarDecl *VD) {
10555 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10556, __PRETTY_FUNCTION__))
10556 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10556, __PRETTY_FUNCTION__))
;
10557 StringRef VarName;
10558 llvm::Constant *Addr;
10559 llvm::GlobalValue::LinkageTypes Linkage;
10560 QualType Ty = VD->getType();
10561 SmallString<128> Buffer;
10562 {
10563 unsigned DeviceID;
10564 unsigned FileID;
10565 unsigned Line;
10566 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
10567 FileID, Line);
10568 llvm::raw_svector_ostream OS(Buffer);
10569 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
10570 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
10571 VarName = OS.str();
10572 }
10573 Linkage = llvm::GlobalValue::InternalLinkage;
10574 Addr =
10575 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
10576 getDefaultFirstprivateAddressSpace());
10577 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
10578 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
10579 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
10580 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
10581 VarName, Addr, VarSize,
10582 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
10583 return Addr;
10584}
10585
10586void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
10587 llvm::Constant *Addr) {
10588 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
10589 !CGM.getLangOpts().OpenMPIsDevice)
10590 return;
10591 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10592 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10593 if (!Res) {
10594 if (CGM.getLangOpts().OpenMPIsDevice) {
10595 // Register non-target variables being emitted in device code (debug info
10596 // may cause this).
10597 StringRef VarName = CGM.getMangledName(VD);
10598 EmittedNonTargetVariables.try_emplace(VarName, Addr);
10599 }
10600 return;
10601 }
10602 // Register declare target variables.
10603 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
10604 StringRef VarName;
10605 CharUnits VarSize;
10606 llvm::GlobalValue::LinkageTypes Linkage;
10607
10608 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
10609 !HasRequiresUnifiedSharedMemory) {
10610 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
10611 VarName = CGM.getMangledName(VD);
10612 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
10613 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
10614 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10614, __PRETTY_FUNCTION__))
;
10615 } else {
10616 VarSize = CharUnits::Zero();
10617 }
10618 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
10619 // Temp solution to prevent optimizations of the internal variables.
10620 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
10621 std::string RefName = getName({VarName, "ref"});
10622 if (!CGM.GetGlobalValue(RefName)) {
10623 llvm::Constant *AddrRef =
10624 getOrCreateInternalVariable(Addr->getType(), RefName);
10625 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
10626 GVAddrRef->setConstant(/*Val=*/true);
10627 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
10628 GVAddrRef->setInitializer(Addr);
10629 CGM.addCompilerUsedGlobal(GVAddrRef);
10630 }
10631 }
10632 } else {
10633 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10636, __PRETTY_FUNCTION__))
10634 (*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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10636, __PRETTY_FUNCTION__))
10635 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10636, __PRETTY_FUNCTION__))
10636 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10636, __PRETTY_FUNCTION__))
;
10637 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
10638 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
10639 else
10640 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
10641
10642 if (CGM.getLangOpts().OpenMPIsDevice) {
10643 VarName = Addr->getName();
10644 Addr = nullptr;
10645 } else {
10646 VarName = getAddrOfDeclareTargetVar(VD).getName();
10647 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
10648 }
10649 VarSize = CGM.getPointerSize();
10650 Linkage = llvm::GlobalValue::WeakAnyLinkage;
10651 }
10652
10653 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
10654 VarName, Addr, VarSize, Flags, Linkage);
10655}
10656
10657bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
10658 if (isa<FunctionDecl>(GD.getDecl()) ||
10659 isa<OMPDeclareReductionDecl>(GD.getDecl()))
10660 return emitTargetFunctions(GD);
10661
10662 return emitTargetGlobalVariable(GD);
10663}
10664
10665void CGOpenMPRuntime::emitDeferredTargetDecls() const {
10666 for (const VarDecl *VD : DeferredGlobalVariables) {
10667 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10668 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10669 if (!Res)
10670 continue;
10671 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
10672 !HasRequiresUnifiedSharedMemory) {
10673 CGM.EmitGlobal(VD);
10674 } else {
10675 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10678, __PRETTY_FUNCTION__))
10676 (*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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10678, __PRETTY_FUNCTION__))
10677 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10678, __PRETTY_FUNCTION__))
10678 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10678, __PRETTY_FUNCTION__))
;
10679 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
10680 }
10681 }
10682}
10683
10684void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
10685 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
10686 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10687, __PRETTY_FUNCTION__))
10687 " 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10687, __PRETTY_FUNCTION__))
;
10688}
10689
10690void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) {
10691 for (const OMPClause *Clause : D->clauselists()) {
10692 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
10693 HasRequiresUnifiedSharedMemory = true;
10694 } else if (const auto *AC =
10695 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
10696 switch (AC->getAtomicDefaultMemOrderKind()) {
10697 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
10698 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease;
10699 break;
10700 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
10701 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent;
10702 break;
10703 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
10704 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic;
10705 break;
10706 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown:
10707 break;
10708 }
10709 }
10710 }
10711}
10712
10713llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const {
10714 return RequiresAtomicOrdering;
10715}
10716
10717bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
10718 LangAS &AS) {
10719 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
10720 return false;
10721 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
10722 switch(A->getAllocatorType()) {
10723 case OMPAllocateDeclAttr::OMPNullMemAlloc:
10724 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
10725 // Not supported, fallback to the default mem space.
10726 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
10727 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
10728 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
10729 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
10730 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
10731 case OMPAllocateDeclAttr::OMPConstMemAlloc:
10732 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
10733 AS = LangAS::Default;
10734 return true;
10735 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
10736 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10737)
10737 "static storage.")::llvm::llvm_unreachable_internal("Expected predefined allocator for the variables with the "
"static storage.", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10737)
;
10738 }
10739 return false;
10740}
10741
10742bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
10743 return HasRequiresUnifiedSharedMemory;
10744}
10745
10746CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
10747 CodeGenModule &CGM)
10748 : CGM(CGM) {
10749 if (CGM.getLangOpts().OpenMPIsDevice) {
10750 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
10751 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
10752 }
10753}
10754
10755CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
10756 if (CGM.getLangOpts().OpenMPIsDevice)
10757 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
10758}
10759
10760bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
10761 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
10762 return true;
10763
10764 const auto *D = cast<FunctionDecl>(GD.getDecl());
10765 // Do not to emit function if it is marked as declare target as it was already
10766 // emitted.
10767 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
10768 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) {
10769 if (auto *F = dyn_cast_or_null<llvm::Function>(
10770 CGM.GetGlobalValue(CGM.getMangledName(GD))))
10771 return !F->isDeclaration();
10772 return false;
10773 }
10774 return true;
10775 }
10776
10777 return !AlreadyEmittedTargetDecls.insert(D).second;
10778}
10779
10780llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
10781 // If we don't have entries or if we are emitting code for the device, we
10782 // don't need to do anything.
10783 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
10784 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
10785 (OffloadEntriesInfoManager.empty() &&
10786 !HasEmittedDeclareTargetRegion &&
10787 !HasEmittedTargetRegion))
10788 return nullptr;
10789
10790 // Create and register the function that handles the requires directives.
10791 ASTContext &C = CGM.getContext();
10792
10793 llvm::Function *RequiresRegFn;
10794 {
10795 CodeGenFunction CGF(CGM);
10796 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
10797 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
10798 std::string ReqName = getName({"omp_offloading", "requires_reg"});
10799 RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI);
10800 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
10801 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
10802 // TODO: check for other requires clauses.
10803 // The requires directive takes effect only when a target region is
10804 // present in the compilation unit. Otherwise it is ignored and not
10805 // passed to the runtime. This avoids the runtime from throwing an error
10806 // for mismatching requires clauses across compilation units that don't
10807 // contain at least 1 target region.
10808 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10811, __PRETTY_FUNCTION__))
10809 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10811, __PRETTY_FUNCTION__))
10810 !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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10811, __PRETTY_FUNCTION__))
10811 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10811, __PRETTY_FUNCTION__))
;
10812 if (HasRequiresUnifiedSharedMemory)
10813 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
10814 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
10815 CGM.getModule(), OMPRTL___tgt_register_requires),
10816 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
10817 CGF.FinishFunction();
10818 }
10819 return RequiresRegFn;
10820}
10821
10822void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
10823 const OMPExecutableDirective &D,
10824 SourceLocation Loc,
10825 llvm::Function *OutlinedFn,
10826 ArrayRef<llvm::Value *> CapturedVars) {
10827 if (!CGF.HaveInsertPoint())
10828 return;
10829
10830 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
10831 CodeGenFunction::RunCleanupsScope Scope(CGF);
10832
10833 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
10834 llvm::Value *Args[] = {
10835 RTLoc,
10836 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
10837 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
10838 llvm::SmallVector<llvm::Value *, 16> RealArgs;
10839 RealArgs.append(std::begin(Args), std::end(Args));
10840 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
10841
10842 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction(
10843 CGM.getModule(), OMPRTL___kmpc_fork_teams);
10844 CGF.EmitRuntimeCall(RTLFn, RealArgs);
10845}
10846
10847void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
10848 const Expr *NumTeams,
10849 const Expr *ThreadLimit,
10850 SourceLocation Loc) {
10851 if (!CGF.HaveInsertPoint())
10852 return;
10853
10854 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
10855
10856 llvm::Value *NumTeamsVal =
10857 NumTeams
10858 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
10859 CGF.CGM.Int32Ty, /* isSigned = */ true)
10860 : CGF.Builder.getInt32(0);
10861
10862 llvm::Value *ThreadLimitVal =
10863 ThreadLimit
10864 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
10865 CGF.CGM.Int32Ty, /* isSigned = */ true)
10866 : CGF.Builder.getInt32(0);
10867
10868 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
10869 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
10870 ThreadLimitVal};
10871 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
10872 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
10873 PushNumTeamsArgs);
10874}
10875
10876void CGOpenMPRuntime::emitTargetDataCalls(
10877 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10878 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
10879 if (!CGF.HaveInsertPoint())
10880 return;
10881
10882 // Action used to replace the default codegen action and turn privatization
10883 // off.
10884 PrePostActionTy NoPrivAction;
10885
10886 // Generate the code for the opening of the data environment. Capture all the
10887 // arguments of the runtime call by reference because they are used in the
10888 // closing of the region.
10889 auto &&BeginThenGen = [this, &D, Device, &Info,
10890 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
10891 // Fill up the arrays with all the mapped variables.
10892 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10893
10894 // Get map clause information.
10895 MappableExprsHandler MEHandler(D, CGF);
10896 MEHandler.generateAllInfo(CombinedInfo);
10897
10898 // Fill up the arrays and create the arguments.
10899 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder,
10900 /*IsNonContiguous=*/true);
10901
10902 llvm::Value *BasePointersArrayArg = nullptr;
10903 llvm::Value *PointersArrayArg = nullptr;
10904 llvm::Value *SizesArrayArg = nullptr;
10905 llvm::Value *MapTypesArrayArg = nullptr;
10906 llvm::Value *MapNamesArrayArg = nullptr;
10907 llvm::Value *MappersArrayArg = nullptr;
10908 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
10909 SizesArrayArg, MapTypesArrayArg,
10910 MapNamesArrayArg, MappersArrayArg, Info);
10911
10912 // Emit device ID if any.
10913 llvm::Value *DeviceID = nullptr;
10914 if (Device) {
10915 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10916 CGF.Int64Ty, /*isSigned=*/true);
10917 } else {
10918 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10919 }
10920
10921 // Emit the number of elements in the offloading arrays.
10922 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
10923 //
10924 // Source location for the ident struct
10925 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
10926
10927 llvm::Value *OffloadingArgs[] = {RTLoc,
10928 DeviceID,
10929 PointerNum,
10930 BasePointersArrayArg,
10931 PointersArrayArg,
10932 SizesArrayArg,
10933 MapTypesArrayArg,
10934 MapNamesArrayArg,
10935 MappersArrayArg};
10936 CGF.EmitRuntimeCall(
10937 OMPBuilder.getOrCreateRuntimeFunction(
10938 CGM.getModule(), OMPRTL___tgt_target_data_begin_mapper),
10939 OffloadingArgs);
10940
10941 // If device pointer privatization is required, emit the body of the region
10942 // here. It will have to be duplicated: with and without privatization.
10943 if (!Info.CaptureDeviceAddrMap.empty())
10944 CodeGen(CGF);
10945 };
10946
10947 // Generate code for the closing of the data region.
10948 auto &&EndThenGen = [this, Device, &Info, &D](CodeGenFunction &CGF,
10949 PrePostActionTy &) {
10950 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 10950, __PRETTY_FUNCTION__))
;
10951
10952 llvm::Value *BasePointersArrayArg = nullptr;
10953 llvm::Value *PointersArrayArg = nullptr;
10954 llvm::Value *SizesArrayArg = nullptr;
10955 llvm::Value *MapTypesArrayArg = nullptr;
10956 llvm::Value *MapNamesArrayArg = nullptr;
10957 llvm::Value *MappersArrayArg = nullptr;
10958 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
10959 SizesArrayArg, MapTypesArrayArg,
10960 MapNamesArrayArg, MappersArrayArg, Info,
10961 {/*ForEndCall=*/true});
10962
10963 // Emit device ID if any.
10964 llvm::Value *DeviceID = nullptr;
10965 if (Device) {
10966 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
10967 CGF.Int64Ty, /*isSigned=*/true);
10968 } else {
10969 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10970 }
10971
10972 // Emit the number of elements in the offloading arrays.
10973 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
10974
10975 // Source location for the ident struct
10976 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
10977
10978 llvm::Value *OffloadingArgs[] = {RTLoc,
10979 DeviceID,
10980 PointerNum,
10981 BasePointersArrayArg,
10982 PointersArrayArg,
10983 SizesArrayArg,
10984 MapTypesArrayArg,
10985 MapNamesArrayArg,
10986 MappersArrayArg};
10987 CGF.EmitRuntimeCall(
10988 OMPBuilder.getOrCreateRuntimeFunction(
10989 CGM.getModule(), OMPRTL___tgt_target_data_end_mapper),
10990 OffloadingArgs);
10991 };
10992
10993 // If we need device pointer privatization, we need to emit the body of the
10994 // region with no privatization in the 'else' branch of the conditional.
10995 // Otherwise, we don't have to do anything.
10996 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10997 PrePostActionTy &) {
10998 if (!Info.CaptureDeviceAddrMap.empty()) {
10999 CodeGen.setAction(NoPrivAction);
11000 CodeGen(CGF);
11001 }
11002 };
11003
11004 // We don't have to do anything to close the region if the if clause evaluates
11005 // to false.
11006 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
11007
11008 if (IfCond) {
11009 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
11010 } else {
11011 RegionCodeGenTy RCG(BeginThenGen);
11012 RCG(CGF);
11013 }
11014
11015 // If we don't require privatization of device pointers, we emit the body in
11016 // between the runtime calls. This avoids duplicating the body code.
11017 if (Info.CaptureDeviceAddrMap.empty()) {
11018 CodeGen.setAction(NoPrivAction);
11019 CodeGen(CGF);
11020 }
11021
11022 if (IfCond) {
11023 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen);
11024 } else {
11025 RegionCodeGenTy RCG(EndThenGen);
11026 RCG(CGF);
11027 }
11028}
11029
11030void CGOpenMPRuntime::emitTargetDataStandAloneCall(
11031 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11032 const Expr *Device) {
11033 if (!CGF.HaveInsertPoint())
11034 return;
11035
11036 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11039, __PRETTY_FUNCTION__))
11037 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11039, __PRETTY_FUNCTION__))
11038 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11039, __PRETTY_FUNCTION__))
11039 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11039, __PRETTY_FUNCTION__))
;
11040
11041 CodeGenFunction::OMPTargetDataInfo InputInfo;
11042 llvm::Value *MapTypesArray = nullptr;
11043 llvm::Value *MapNamesArray = nullptr;
11044 // Generate the code for the opening of the data environment.
11045 auto &&ThenGen = [this, &D, Device, &InputInfo, &MapTypesArray,
11046 &MapNamesArray](CodeGenFunction &CGF, PrePostActionTy &) {
11047 // Emit device ID if any.
11048 llvm::Value *DeviceID = nullptr;
11049 if (Device) {
11050 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
11051 CGF.Int64Ty, /*isSigned=*/true);
11052 } else {
11053 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
11054 }
11055
11056 // Emit the number of elements in the offloading arrays.
11057 llvm::Constant *PointerNum =
11058 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
11059
11060 // Source location for the ident struct
11061 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc());
11062
11063 llvm::Value *OffloadingArgs[] = {RTLoc,
11064 DeviceID,
11065 PointerNum,
11066 InputInfo.BasePointersArray.getPointer(),
11067 InputInfo.PointersArray.getPointer(),
11068 InputInfo.SizesArray.getPointer(),
11069 MapTypesArray,
11070 MapNamesArray,
11071 InputInfo.MappersArray.getPointer()};
11072
11073 // Select the right runtime function call for each standalone
11074 // directive.
11075 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
11076 RuntimeFunction RTLFn;
11077 switch (D.getDirectiveKind()) {
11078 case OMPD_target_enter_data:
11079 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11080 : OMPRTL___tgt_target_data_begin_mapper;
11081 break;
11082 case OMPD_target_exit_data:
11083 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11084 : OMPRTL___tgt_target_data_end_mapper;
11085 break;
11086 case OMPD_target_update:
11087 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11088 : OMPRTL___tgt_target_data_update_mapper;
11089 break;
11090 case OMPD_parallel:
11091 case OMPD_for:
11092 case OMPD_parallel_for:
11093 case OMPD_parallel_master:
11094 case OMPD_parallel_sections:
11095 case OMPD_for_simd:
11096 case OMPD_parallel_for_simd:
11097 case OMPD_cancel:
11098 case OMPD_cancellation_point:
11099 case OMPD_ordered:
11100 case OMPD_threadprivate:
11101 case OMPD_allocate:
11102 case OMPD_task:
11103 case OMPD_simd:
11104 case OMPD_tile:
11105 case OMPD_sections:
11106 case OMPD_section:
11107 case OMPD_single:
11108 case OMPD_master:
11109 case OMPD_critical:
11110 case OMPD_taskyield:
11111 case OMPD_barrier:
11112 case OMPD_taskwait:
11113 case OMPD_taskgroup:
11114 case OMPD_atomic:
11115 case OMPD_flush:
11116 case OMPD_depobj:
11117 case OMPD_scan:
11118 case OMPD_teams:
11119 case OMPD_target_data:
11120 case OMPD_distribute:
11121 case OMPD_distribute_simd:
11122 case OMPD_distribute_parallel_for:
11123 case OMPD_distribute_parallel_for_simd:
11124 case OMPD_teams_distribute:
11125 case OMPD_teams_distribute_simd:
11126 case OMPD_teams_distribute_parallel_for:
11127 case OMPD_teams_distribute_parallel_for_simd:
11128 case OMPD_declare_simd:
11129 case OMPD_declare_variant:
11130 case OMPD_begin_declare_variant:
11131 case OMPD_end_declare_variant:
11132 case OMPD_declare_target:
11133 case OMPD_end_declare_target:
11134 case OMPD_declare_reduction:
11135 case OMPD_declare_mapper:
11136 case OMPD_taskloop:
11137 case OMPD_taskloop_simd:
11138 case OMPD_master_taskloop:
11139 case OMPD_master_taskloop_simd:
11140 case OMPD_parallel_master_taskloop:
11141 case OMPD_parallel_master_taskloop_simd:
11142 case OMPD_target:
11143 case OMPD_target_simd:
11144 case OMPD_target_teams_distribute:
11145 case OMPD_target_teams_distribute_simd:
11146 case OMPD_target_teams_distribute_parallel_for:
11147 case OMPD_target_teams_distribute_parallel_for_simd:
11148 case OMPD_target_teams:
11149 case OMPD_target_parallel:
11150 case OMPD_target_parallel_for:
11151 case OMPD_target_parallel_for_simd:
11152 case OMPD_requires:
11153 case OMPD_unknown:
11154 default:
11155 llvm_unreachable("Unexpected standalone target data directive.")::llvm::llvm_unreachable_internal("Unexpected standalone target data directive."
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11155)
;
11156 break;
11157 }
11158 CGF.EmitRuntimeCall(
11159 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), RTLFn),
11160 OffloadingArgs);
11161 };
11162
11163 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11164 &MapNamesArray](CodeGenFunction &CGF,
11165 PrePostActionTy &) {
11166 // Fill up the arrays with all the mapped variables.
11167 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11168
11169 // Get map clause information.
11170 MappableExprsHandler MEHandler(D, CGF);
11171 MEHandler.generateAllInfo(CombinedInfo);
11172
11173 TargetDataInfo Info;
11174 // Fill up the arrays and create the arguments.
11175 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder,
11176 /*IsNonContiguous=*/true);
11177 bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() ||
11178 D.hasClausesOfKind<OMPNowaitClause>();
11179 emitOffloadingArraysArgument(
11180 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray,
11181 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info,
11182 {/*ForEndTask=*/false});
11183 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
11184 InputInfo.BasePointersArray =
11185 Address(Info.BasePointersArray, CGM.getPointerAlign());
11186 InputInfo.PointersArray =
11187 Address(Info.PointersArray, CGM.getPointerAlign());
11188 InputInfo.SizesArray =
11189 Address(Info.SizesArray, CGM.getPointerAlign());
11190 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign());
11191 MapTypesArray = Info.MapTypesArray;
11192 MapNamesArray = Info.MapNamesArray;
11193 if (RequiresOuterTask)
11194 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
11195 else
11196 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
11197 };
11198
11199 if (IfCond) {
11200 emitIfClause(CGF, IfCond, TargetThenGen,
11201 [](CodeGenFunction &CGF, PrePostActionTy &) {});
11202 } else {
11203 RegionCodeGenTy ThenRCG(TargetThenGen);
11204 ThenRCG(CGF);
11205 }
11206}
11207
11208namespace {
11209 /// Kind of parameter in a function with 'declare simd' directive.
11210 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
11211 /// Attribute set of the parameter.
11212 struct ParamAttrTy {
11213 ParamKindTy Kind = Vector;
11214 llvm::APSInt StrideOrArg;
11215 llvm::APSInt Alignment;
11216 };
11217} // namespace
11218
11219static unsigned evaluateCDTSize(const FunctionDecl *FD,
11220 ArrayRef<ParamAttrTy> ParamAttrs) {
11221 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
11222 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
11223 // of that clause. The VLEN value must be power of 2.
11224 // In other case the notion of the function`s "characteristic data type" (CDT)
11225 // is used to compute the vector length.
11226 // CDT is defined in the following order:
11227 // a) For non-void function, the CDT is the return type.
11228 // b) If the function has any non-uniform, non-linear parameters, then the
11229 // CDT is the type of the first such parameter.
11230 // c) If the CDT determined by a) or b) above is struct, union, or class
11231 // type which is pass-by-value (except for the type that maps to the
11232 // built-in complex data type), the characteristic data type is int.
11233 // d) If none of the above three cases is applicable, the CDT is int.
11234 // The VLEN is then determined based on the CDT and the size of vector
11235 // register of that ISA for which current vector version is generated. The
11236 // VLEN is computed using the formula below:
11237 // VLEN = sizeof(vector_register) / sizeof(CDT),
11238 // where vector register size specified in section 3.2.1 Registers and the
11239 // Stack Frame of original AMD64 ABI document.
11240 QualType RetType = FD->getReturnType();
11241 if (RetType.isNull())
11242 return 0;
11243 ASTContext &C = FD->getASTContext();
11244 QualType CDT;
11245 if (!RetType.isNull() && !RetType->isVoidType()) {
11246 CDT = RetType;
11247 } else {
11248 unsigned Offset = 0;
11249 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11250 if (ParamAttrs[Offset].Kind == Vector)
11251 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
11252 ++Offset;
11253 }
11254 if (CDT.isNull()) {
11255 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
11256 if (ParamAttrs[I + Offset].Kind == Vector) {
11257 CDT = FD->getParamDecl(I)->getType();
11258 break;
11259 }
11260 }
11261 }
11262 }
11263 if (CDT.isNull())
11264 CDT = C.IntTy;
11265 CDT = CDT->getCanonicalTypeUnqualified();
11266 if (CDT->isRecordType() || CDT->isUnionType())
11267 CDT = C.IntTy;
11268 return C.getTypeSize(CDT);
11269}
11270
11271static void
11272emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
11273 const llvm::APSInt &VLENVal,
11274 ArrayRef<ParamAttrTy> ParamAttrs,
11275 OMPDeclareSimdDeclAttr::BranchStateTy State) {
11276 struct ISADataTy {
11277 char ISA;
11278 unsigned VecRegSize;
11279 };
11280 ISADataTy ISAData[] = {
11281 {
11282 'b', 128
11283 }, // SSE
11284 {
11285 'c', 256
11286 }, // AVX
11287 {
11288 'd', 256
11289 }, // AVX2
11290 {
11291 'e', 512
11292 }, // AVX512
11293 };
11294 llvm::SmallVector<char, 2> Masked;
11295 switch (State) {
11296 case OMPDeclareSimdDeclAttr::BS_Undefined:
11297 Masked.push_back('N');
11298 Masked.push_back('M');
11299 break;
11300 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11301 Masked.push_back('N');
11302 break;
11303 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11304 Masked.push_back('M');
11305 break;
11306 }
11307 for (char Mask : Masked) {
11308 for (const ISADataTy &Data : ISAData) {
11309 SmallString<256> Buffer;
11310 llvm::raw_svector_ostream Out(Buffer);
11311 Out << "_ZGV" << Data.ISA << Mask;
11312 if (!VLENVal) {
11313 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
11314 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11314, __PRETTY_FUNCTION__))
;
11315 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
11316 } else {
11317 Out << VLENVal;
11318 }
11319 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
11320 switch (ParamAttr.Kind){
11321 case LinearWithVarStride:
11322 Out << 's' << ParamAttr.StrideOrArg;
11323 break;
11324 case Linear:
11325 Out << 'l';
11326 if (ParamAttr.StrideOrArg != 1)
11327 Out << ParamAttr.StrideOrArg;
11328 break;
11329 case Uniform:
11330 Out << 'u';
11331 break;
11332 case Vector:
11333 Out << 'v';
11334 break;
11335 }
11336 if (!!ParamAttr.Alignment)
11337 Out << 'a' << ParamAttr.Alignment;
11338 }
11339 Out << '_' << Fn->getName();
11340 Fn->addFnAttr(Out.str());
11341 }
11342 }
11343}
11344
11345// This are the Functions that are needed to mangle the name of the
11346// vector functions generated by the compiler, according to the rules
11347// defined in the "Vector Function ABI specifications for AArch64",
11348// available at
11349// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
11350
11351/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
11352///
11353/// TODO: Need to implement the behavior for reference marked with a
11354/// var or no linear modifiers (1.b in the section). For this, we
11355/// need to extend ParamKindTy to support the linear modifiers.
11356static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
11357 QT = QT.getCanonicalType();
11358
11359 if (QT->isVoidType())
11360 return false;
11361
11362 if (Kind == ParamKindTy::Uniform)
11363 return false;
11364
11365 if (Kind == ParamKindTy::Linear)
11366 return false;
11367
11368 // TODO: Handle linear references with modifiers
11369
11370 if (Kind == ParamKindTy::LinearWithVarStride)
11371 return false;
11372
11373 return true;
11374}
11375
11376/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
11377static bool getAArch64PBV(QualType QT, ASTContext &C) {
11378 QT = QT.getCanonicalType();
11379 unsigned Size = C.getTypeSize(QT);
11380
11381 // Only scalars and complex within 16 bytes wide set PVB to true.
11382 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
11383 return false;
11384
11385 if (QT->isFloatingType())
11386 return true;
11387
11388 if (QT->isIntegerType())
11389 return true;
11390
11391 if (QT->isPointerType())
11392 return true;
11393
11394 // TODO: Add support for complex types (section 3.1.2, item 2).
11395
11396 return false;
11397}
11398
11399/// Computes the lane size (LS) of a return type or of an input parameter,
11400/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
11401/// TODO: Add support for references, section 3.2.1, item 1.
11402static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
11403 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
11404 QualType PTy = QT.getCanonicalType()->getPointeeType();
11405 if (getAArch64PBV(PTy, C))
11406 return C.getTypeSize(PTy);
11407 }
11408 if (getAArch64PBV(QT, C))
11409 return C.getTypeSize(QT);
11410
11411 return C.getTypeSize(C.getUIntPtrType());
11412}
11413
11414// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
11415// signature of the scalar function, as defined in 3.2.2 of the
11416// AAVFABI.
11417static std::tuple<unsigned, unsigned, bool>
11418getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
11419 QualType RetType = FD->getReturnType().getCanonicalType();
11420
11421 ASTContext &C = FD->getASTContext();
11422
11423 bool OutputBecomesInput = false;
11424
11425 llvm::SmallVector<unsigned, 8> Sizes;
11426 if (!RetType->isVoidType()) {
11427 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
11428 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
11429 OutputBecomesInput = true;
11430 }
11431 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
11432 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
11433 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
11434 }
11435
11436 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11436, __PRETTY_FUNCTION__))
;
11437 // The LS of a function parameter / return value can only be a power
11438 // of 2, starting from 8 bits, up to 128.
11439 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11444, __PRETTY_FUNCTION__))
11440 [](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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11444, __PRETTY_FUNCTION__))
11441 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11444, __PRETTY_FUNCTION__))
11442 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11444, __PRETTY_FUNCTION__))
11443 }) &&((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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11444, __PRETTY_FUNCTION__))
11444 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11444, __PRETTY_FUNCTION__))
;
11445
11446 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
11447 *std::max_element(std::begin(Sizes), std::end(Sizes)),
11448 OutputBecomesInput);
11449}
11450
11451/// Mangle the parameter part of the vector function name according to
11452/// their OpenMP classification. The mangling function is defined in
11453/// section 3.5 of the AAVFABI.
11454static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
11455 SmallString<256> Buffer;
11456 llvm::raw_svector_ostream Out(Buffer);
11457 for (const auto &ParamAttr : ParamAttrs) {
11458 switch (ParamAttr.Kind) {
11459 case LinearWithVarStride:
11460 Out << "ls" << ParamAttr.StrideOrArg;
11461 break;
11462 case Linear:
11463 Out << 'l';
11464 // Don't print the step value if it is not present or if it is
11465 // equal to 1.
11466 if (ParamAttr.StrideOrArg != 1)
11467 Out << ParamAttr.StrideOrArg;
11468 break;
11469 case Uniform:
11470 Out << 'u';
11471 break;
11472 case Vector:
11473 Out << 'v';
11474 break;
11475 }
11476
11477 if (!!ParamAttr.Alignment)
11478 Out << 'a' << ParamAttr.Alignment;
11479 }
11480
11481 return std::string(Out.str());
11482}
11483
11484// Function used to add the attribute. The parameter `VLEN` is
11485// templated to allow the use of "x" when targeting scalable functions
11486// for SVE.
11487template <typename T>
11488static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
11489 char ISA, StringRef ParSeq,
11490 StringRef MangledName, bool OutputBecomesInput,
11491 llvm::Function *Fn) {
11492 SmallString<256> Buffer;
11493 llvm::raw_svector_ostream Out(Buffer);
11494 Out << Prefix << ISA << LMask << VLEN;
11495 if (OutputBecomesInput)
11496 Out << "v";
11497 Out << ParSeq << "_" << MangledName;
11498 Fn->addFnAttr(Out.str());
11499}
11500
11501// Helper function to generate the Advanced SIMD names depending on
11502// the value of the NDS when simdlen is not present.
11503static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
11504 StringRef Prefix, char ISA,
11505 StringRef ParSeq, StringRef MangledName,
11506 bool OutputBecomesInput,
11507 llvm::Function *Fn) {
11508 switch (NDS) {
11509 case 8:
11510 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
11511 OutputBecomesInput, Fn);
11512 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
11513 OutputBecomesInput, Fn);
11514 break;
11515 case 16:
11516 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
11517 OutputBecomesInput, Fn);
11518 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
11519 OutputBecomesInput, Fn);
11520 break;
11521 case 32:
11522 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
11523 OutputBecomesInput, Fn);
11524 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
11525 OutputBecomesInput, Fn);
11526 break;
11527 case 64:
11528 case 128:
11529 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
11530 OutputBecomesInput, Fn);
11531 break;
11532 default:
11533 llvm_unreachable("Scalar type is too wide.")::llvm::llvm_unreachable_internal("Scalar type is too wide.",
"/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11533)
;
11534 }
11535}
11536
11537/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
11538static void emitAArch64DeclareSimdFunction(
11539 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
11540 ArrayRef<ParamAttrTy> ParamAttrs,
11541 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
11542 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
11543
11544 // Get basic data for building the vector signature.
11545 const auto Data = getNDSWDS(FD, ParamAttrs);
11546 const unsigned NDS = std::get<0>(Data);
11547 const unsigned WDS = std::get<1>(Data);
11548 const bool OutputBecomesInput = std::get<2>(Data);
11549
11550 // Check the values provided via `simdlen` by the user.
11551 // 1. A `simdlen(1)` doesn't produce vector signatures,
11552 if (UserVLEN == 1) {
11553 unsigned DiagID = CGM.getDiags().getCustomDiagID(
11554 DiagnosticsEngine::Warning,
11555 "The clause simdlen(1) has no effect when targeting aarch64.");
11556 CGM.getDiags().Report(SLoc, DiagID);
11557 return;
11558 }
11559
11560 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
11561 // Advanced SIMD output.
11562 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
11563 unsigned DiagID = CGM.getDiags().getCustomDiagID(
11564 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
11565 "power of 2 when targeting Advanced SIMD.");
11566 CGM.getDiags().Report(SLoc, DiagID);
11567 return;
11568 }
11569
11570 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
11571 // limits.
11572 if (ISA == 's' && UserVLEN != 0) {
11573 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
11574 unsigned DiagID = CGM.getDiags().getCustomDiagID(
11575 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
11576 "lanes in the architectural constraints "
11577 "for SVE (min is 128-bit, max is "
11578 "2048-bit, by steps of 128-bit)");
11579 CGM.getDiags().Report(SLoc, DiagID) << WDS;
11580 return;
11581 }
11582 }
11583
11584 // Sort out parameter sequence.
11585 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
11586 StringRef Prefix = "_ZGV";
11587 // Generate simdlen from user input (if any).
11588 if (UserVLEN) {
11589 if (ISA == 's') {
11590 // SVE generates only a masked function.
11591 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
11592 OutputBecomesInput, Fn);
11593 } else {
11594 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11594, __PRETTY_FUNCTION__))
;
11595 // Advanced SIMD generates one or two functions, depending on
11596 // the `[not]inbranch` clause.
11597 switch (State) {
11598 case OMPDeclareSimdDeclAttr::BS_Undefined:
11599 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
11600 OutputBecomesInput, Fn);
11601 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
11602 OutputBecomesInput, Fn);
11603 break;
11604 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11605 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
11606 OutputBecomesInput, Fn);
11607 break;
11608 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11609 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
11610 OutputBecomesInput, Fn);
11611 break;
11612 }
11613 }
11614 } else {
11615 // If no user simdlen is provided, follow the AAVFABI rules for
11616 // generating the vector length.
11617 if (ISA == 's') {
11618 // SVE, section 3.4.1, item 1.
11619 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
11620 OutputBecomesInput, Fn);
11621 } else {
11622 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11622, __PRETTY_FUNCTION__))
;
11623 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
11624 // two vector names depending on the use of the clause
11625 // `[not]inbranch`.
11626 switch (State) {
11627 case OMPDeclareSimdDeclAttr::BS_Undefined:
11628 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
11629 OutputBecomesInput, Fn);
11630 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
11631 OutputBecomesInput, Fn);
11632 break;
11633 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11634 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
11635 OutputBecomesInput, Fn);
11636 break;
11637 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11638 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
11639 OutputBecomesInput, Fn);
11640 break;
11641 }
11642 }
11643 }
11644}
11645
11646void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
11647 llvm::Function *Fn) {
11648 ASTContext &C = CGM.getContext();
11649 FD = FD->getMostRecentDecl();
11650 // Map params to their positions in function decl.
11651 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
11652 if (isa<CXXMethodDecl>(FD))
11653 ParamPositions.try_emplace(FD, 0);
11654 unsigned ParamPos = ParamPositions.size();
11655 for (const ParmVarDecl *P : FD->parameters()) {
11656 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
11657 ++ParamPos;
11658 }
11659 while (FD) {
11660 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
11661 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
11662 // Mark uniform parameters.
11663 for (const Expr *E : Attr->uniforms()) {
11664 E = E->IgnoreParenImpCasts();
11665 unsigned Pos;
11666 if (isa<CXXThisExpr>(E)) {
11667 Pos = ParamPositions[FD];
11668 } else {
11669 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
11670 ->getCanonicalDecl();
11671 Pos = ParamPositions[PVD];
11672 }
11673 ParamAttrs[Pos].Kind = Uniform;
11674 }
11675 // Get alignment info.
11676 auto NI = Attr->alignments_begin();
11677 for (const Expr *E : Attr->aligneds()) {
11678 E = E->IgnoreParenImpCasts();
11679 unsigned Pos;
11680 QualType ParmTy;
11681 if (isa<CXXThisExpr>(E)) {
11682 Pos = ParamPositions[FD];
11683 ParmTy = E->getType();
11684 } else {
11685 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
11686 ->getCanonicalDecl();
11687 Pos = ParamPositions[PVD];
11688 ParmTy = PVD->getType();
11689 }
11690 ParamAttrs[Pos].Alignment =
11691 (*NI)
11692 ? (*NI)->EvaluateKnownConstInt(C)
11693 : llvm::APSInt::getUnsigned(
11694 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
11695 .getQuantity());
11696 ++NI;
11697 }
11698 // Mark linear parameters.
11699 auto SI = Attr->steps_begin();
11700 auto MI = Attr->modifiers_begin();
11701 for (const Expr *E : Attr->linears()) {
11702 E = E->IgnoreParenImpCasts();
11703 unsigned Pos;
11704 // Rescaling factor needed to compute the linear parameter
11705 // value in the mangled name.
11706 unsigned PtrRescalingFactor = 1;
11707 if (isa<CXXThisExpr>(E)) {
11708 Pos = ParamPositions[FD];
11709 } else {
11710 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
11711 ->getCanonicalDecl();
11712 Pos = ParamPositions[PVD];
11713 if (auto *P = dyn_cast<PointerType>(PVD->getType()))
11714 PtrRescalingFactor = CGM.getContext()
11715 .getTypeSizeInChars(P->getPointeeType())
11716 .getQuantity();
11717 }
11718 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
11719 ParamAttr.Kind = Linear;
11720 // Assuming a stride of 1, for `linear` without modifiers.
11721 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
11722 if (*SI) {
11723 Expr::EvalResult Result;
11724 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
11725 if (const auto *DRE =
11726 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
11727 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
11728 ParamAttr.Kind = LinearWithVarStride;
11729 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
11730 ParamPositions[StridePVD->getCanonicalDecl()]);
11731 }
11732 }
11733 } else {
11734 ParamAttr.StrideOrArg = Result.Val.getInt();
11735 }
11736 }
11737 // If we are using a linear clause on a pointer, we need to
11738 // rescale the value of linear_step with the byte size of the
11739 // pointee type.
11740 if (Linear == ParamAttr.Kind)
11741 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
11742 ++SI;
11743 ++MI;
11744 }
11745 llvm::APSInt VLENVal;
11746 SourceLocation ExprLoc;
11747 const Expr *VLENExpr = Attr->getSimdlen();
11748 if (VLENExpr) {
11749 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
11750 ExprLoc = VLENExpr->getExprLoc();
11751 }
11752 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
11753 if (CGM.getTriple().isX86()) {
11754 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
11755 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
11756 unsigned VLEN = VLENVal.getExtValue();
11757 StringRef MangledName = Fn->getName();
11758 if (CGM.getTarget().hasFeature("sve"))
11759 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
11760 MangledName, 's', 128, Fn, ExprLoc);
11761 if (CGM.getTarget().hasFeature("neon"))
11762 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
11763 MangledName, 'n', 128, Fn, ExprLoc);
11764 }
11765 }
11766 FD = FD->getPreviousDecl();
11767 }
11768}
11769
11770namespace {
11771/// Cleanup action for doacross support.
11772class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
11773public:
11774 static const int DoacrossFinArgs = 2;
11775
11776private:
11777 llvm::FunctionCallee RTLFn;
11778 llvm::Value *Args[DoacrossFinArgs];
11779
11780public:
11781 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
11782 ArrayRef<llvm::Value *> CallArgs)
11783 : RTLFn(RTLFn) {
11784 assert(CallArgs.size() == DoacrossFinArgs)((CallArgs.size() == DoacrossFinArgs) ? static_cast<void>
(0) : __assert_fail ("CallArgs.size() == DoacrossFinArgs", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11784, __PRETTY_FUNCTION__))
;
11785 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11786 }
11787 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
11788 if (!CGF.HaveInsertPoint())
11789 return;
11790 CGF.EmitRuntimeCall(RTLFn, Args);
11791 }
11792};
11793} // namespace
11794
11795void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
11796 const OMPLoopDirective &D,
11797 ArrayRef<Expr *> NumIterations) {
11798 if (!CGF.HaveInsertPoint())
11799 return;
11800
11801 ASTContext &C = CGM.getContext();
11802 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
11803 RecordDecl *RD;
11804 if (KmpDimTy.isNull()) {
11805 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
11806 // kmp_int64 lo; // lower
11807 // kmp_int64 up; // upper
11808 // kmp_int64 st; // stride
11809 // };
11810 RD = C.buildImplicitRecord("kmp_dim");
11811 RD->startDefinition();
11812 addFieldToRecordDecl(C, RD, Int64Ty);
11813 addFieldToRecordDecl(C, RD, Int64Ty);
11814 addFieldToRecordDecl(C, RD, Int64Ty);
11815 RD->completeDefinition();
11816 KmpDimTy = C.getRecordType(RD);
11817 } else {
11818 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
11819 }
11820 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
11821 QualType ArrayTy =
11822 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
11823
11824 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
11825 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
11826 enum { LowerFD = 0, UpperFD, StrideFD };
11827 // Fill dims with data.
11828 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
11829 LValue DimsLVal = CGF.MakeAddrLValue(
11830 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
11831 // dims.upper = num_iterations;
11832 LValue UpperLVal = CGF.EmitLValueForField(
11833 DimsLVal, *std::next(RD->field_begin(), UpperFD));
11834 llvm::Value *NumIterVal = CGF.EmitScalarConversion(
11835 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
11836 Int64Ty, NumIterations[I]->getExprLoc());
11837 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
11838 // dims.stride = 1;
11839 LValue StrideLVal = CGF.EmitLValueForField(
11840 DimsLVal, *std::next(RD->field_begin(), StrideFD));
11841 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
11842 StrideLVal);
11843 }
11844
11845 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
11846 // kmp_int32 num_dims, struct kmp_dim * dims);
11847 llvm::Value *Args[] = {
11848 emitUpdateLocation(CGF, D.getBeginLoc()),
11849 getThreadID(CGF, D.getBeginLoc()),
11850 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
11851 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11852 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
11853 CGM.VoidPtrTy)};
11854
11855 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction(
11856 CGM.getModule(), OMPRTL___kmpc_doacross_init);
11857 CGF.EmitRuntimeCall(RTLFn, Args);
11858 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
11859 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
11860 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction(
11861 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
11862 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11863 llvm::makeArrayRef(FiniArgs));
11864}
11865
11866void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11867 const OMPDependClause *C) {
11868 QualType Int64Ty =
11869 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
11870 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
11871 QualType ArrayTy = CGM.getContext().getConstantArrayType(
11872 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
11873 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
11874 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
11875 const Expr *CounterVal = C->getLoopData(I);
11876 assert(CounterVal)((CounterVal) ? static_cast<void> (0) : __assert_fail (
"CounterVal", "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11876, __PRETTY_FUNCTION__))
;
11877 llvm::Value *CntVal = CGF.EmitScalarConversion(
11878 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
11879 CounterVal->getExprLoc());
11880 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
11881 /*Volatile=*/false, Int64Ty);
11882 }
11883 llvm::Value *Args[] = {
11884 emitUpdateLocation(CGF, C->getBeginLoc()),
11885 getThreadID(CGF, C->getBeginLoc()),
11886 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
11887 llvm::FunctionCallee RTLFn;
11888 if (C->getDependencyKind() == OMPC_DEPEND_source) {
11889 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
11890 OMPRTL___kmpc_doacross_post);
11891 } else {
11892 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11892, __PRETTY_FUNCTION__))
;
11893 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
11894 OMPRTL___kmpc_doacross_wait);
11895 }
11896 CGF.EmitRuntimeCall(RTLFn, Args);
11897}
11898
11899void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
11900 llvm::FunctionCallee Callee,
11901 ArrayRef<llvm::Value *> Args) const {
11902 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11902, __PRETTY_FUNCTION__))
;
11903 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
11904
11905 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
11906 if (Fn->doesNotThrow()) {
11907 CGF.EmitNounwindRuntimeCall(Fn, Args);
11908 return;
11909 }
11910 }
11911 CGF.EmitRuntimeCall(Callee, Args);
11912}
11913
11914void CGOpenMPRuntime::emitOutlinedFunctionCall(
11915 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
11916 ArrayRef<llvm::Value *> Args) const {
11917 emitCall(CGF, Loc, OutlinedFn, Args);
11918}
11919
11920void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
11921 if (const auto *FD = dyn_cast<FunctionDecl>(D))
11922 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
11923 HasEmittedDeclareTargetRegion = true;
11924}
11925
11926Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
11927 const VarDecl *NativeParam,
11928 const VarDecl *TargetParam) const {
11929 return CGF.GetAddrOfLocalVar(NativeParam);
11930}
11931
11932Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
11933 const VarDecl *VD) {
11934 if (!VD)
11935 return Address::invalid();
11936 Address UntiedAddr = Address::invalid();
11937 Address UntiedRealAddr = Address::invalid();
11938 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn);
11939 if (It != FunctionToUntiedTaskStackMap.end()) {
11940 const UntiedLocalVarsAddressesMap &UntiedData =
11941 UntiedLocalVarsStack[It->second];
11942 auto I = UntiedData.find(VD);
11943 if (I != UntiedData.end()) {
11944 UntiedAddr = I->second.first;
11945 UntiedRealAddr = I->second.second;
11946 }
11947 }
11948 const VarDecl *CVD = VD->getCanonicalDecl();
11949 if (CVD->hasAttr<OMPAllocateDeclAttr>()) {
11950 // Use the default allocation.
11951 if (!isAllocatableDecl(VD))
11952 return UntiedAddr;
11953 llvm::Value *Size;
11954 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
11955 if (CVD->getType()->isVariablyModifiedType()) {
11956 Size = CGF.getTypeSize(CVD->getType());
11957 // Align the size: ((size + align - 1) / align) * align
11958 Size = CGF.Builder.CreateNUWAdd(
11959 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
11960 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
11961 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
11962 } else {
11963 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
11964 Size = CGM.getSize(Sz.alignTo(Align));
11965 }
11966 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11967 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
11968 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11969, __PRETTY_FUNCTION__))
11969 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 11969, __PRETTY_FUNCTION__))
;
11970 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
11971 // According to the standard, the original allocator type is a enum
11972 // (integer). Convert to pointer type, if required.
11973 Allocator = CGF.EmitScalarConversion(
11974 Allocator, AA->getAllocator()->getType(), CGF.getContext().VoidPtrTy,
11975 AA->getAllocator()->getExprLoc());
11976 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11977
11978 llvm::Value *Addr =
11979 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
11980 CGM.getModule(), OMPRTL___kmpc_alloc),
11981 Args, getName({CVD->getName(), ".void.addr"}));
11982 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction(
11983 CGM.getModule(), OMPRTL___kmpc_free);
11984 QualType Ty = CGM.getContext().getPointerType(CVD->getType());
11985 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11986 Addr, CGF.ConvertTypeForMem(Ty), getName({CVD->getName(), ".addr"}));
11987 if (UntiedAddr.isValid())
11988 CGF.EmitStoreOfScalar(Addr, UntiedAddr, /*Volatile=*/false, Ty);
11989
11990 // Cleanup action for allocate support.
11991 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
11992 llvm::FunctionCallee RTLFn;
11993 unsigned LocEncoding;
11994 Address Addr;
11995 const Expr *Allocator;
11996
11997 public:
11998 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, unsigned LocEncoding,
11999 Address Addr, const Expr *Allocator)
12000 : RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr),
12001 Allocator(Allocator) {}
12002 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
12003 if (!CGF.HaveInsertPoint())
12004 return;
12005 llvm::Value *Args[3];
12006 Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID(
12007 CGF, SourceLocation::getFromRawEncoding(LocEncoding));
12008 Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
12009 Addr.getPointer(), CGF.VoidPtrTy);
12010 llvm::Value *AllocVal = CGF.EmitScalarExpr(Allocator);
12011 // According to the standard, the original allocator type is a enum
12012 // (integer). Convert to pointer type, if required.
12013 AllocVal = CGF.EmitScalarConversion(AllocVal, Allocator->getType(),
12014 CGF.getContext().VoidPtrTy,
12015 Allocator->getExprLoc());
12016 Args[2] = AllocVal;
12017
12018 CGF.EmitRuntimeCall(RTLFn, Args);
12019 }
12020 };
12021 Address VDAddr =
12022 UntiedRealAddr.isValid() ? UntiedRealAddr : Address(Addr, Align);
12023 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(
12024 NormalAndEHCleanup, FiniRTLFn, CVD->getLocation().getRawEncoding(),
12025 VDAddr, AA->getAllocator());
12026 if (UntiedRealAddr.isValid())
12027 if (auto *Region =
12028 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
12029 Region->emitUntiedSwitch(CGF);
12030 return VDAddr;
12031 }
12032 return UntiedAddr;
12033}
12034
12035bool CGOpenMPRuntime::isLocalVarInUntiedTask(CodeGenFunction &CGF,
12036 const VarDecl *VD) const {
12037 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn);
12038 if (It == FunctionToUntiedTaskStackMap.end())
12039 return false;
12040 return UntiedLocalVarsStack[It->second].count(VD) > 0;
12041}
12042
12043CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII(
12044 CodeGenModule &CGM, const OMPLoopDirective &S)
12045 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) {
12046 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12046, __PRETTY_FUNCTION__))
;
12047 if (!NeedToPush)
12048 return;
12049 NontemporalDeclsSet &DS =
12050 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12051 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) {
12052 for (const Stmt *Ref : C->private_refs()) {
12053 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts();
12054 const ValueDecl *VD;
12055 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12056 VD = DRE->getDecl();
12057 } else {
12058 const auto *ME = cast<MemberExpr>(SimpleRefExpr);
12059 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12061, __PRETTY_FUNCTION__))
12060 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12061, __PRETTY_FUNCTION__))
12061 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12061, __PRETTY_FUNCTION__))
;
12062 VD = ME->getMemberDecl();
12063 }
12064 DS.insert(VD);
12065 }
12066 }
12067}
12068
12069CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() {
12070 if (!NeedToPush)
12071 return;
12072 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12073}
12074
12075CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII(
12076 CodeGenFunction &CGF,
12077 const llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
12078 std::pair<Address, Address>> &LocalVars)
12079 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12080 if (!NeedToPush)
12081 return;
12082 CGM.getOpenMPRuntime().FunctionToUntiedTaskStackMap.try_emplace(
12083 CGF.CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12084 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12085}
12086
12087CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::~UntiedTaskLocalDeclsRAII() {
12088 if (!NeedToPush)
12089 return;
12090 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12091}
12092
12093bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const {
12094 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12094, __PRETTY_FUNCTION__))
;
12095
12096 return llvm::any_of(
12097 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12098 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; });
12099}
12100
12101void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12102 const OMPExecutableDirective &S,
12103 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled)
12104 const {
12105 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12106 // Vars in target/task regions must be excluded completely.
12107 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) ||
12108 isOpenMPTaskingDirective(S.getDirectiveKind())) {
12109 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
12110 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind());
12111 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12112 for (const CapturedStmt::Capture &Cap : CS->captures()) {
12113 if (Cap.capturesVariable() || Cap.capturesVariableByCopy())
12114 NeedToCheckForLPCs.insert(Cap.getCapturedVar());
12115 }
12116 }
12117 // Exclude vars in private clauses.
12118 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
12119 for (const Expr *Ref : C->varlists()) {
12120 if (!Ref->getType()->isScalarType())
12121 continue;
12122 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12123 if (!DRE)
12124 continue;
12125 NeedToCheckForLPCs.insert(DRE->getDecl());
12126 }
12127 }
12128 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12129 for (const Expr *Ref : C->varlists()) {
12130 if (!Ref->getType()->isScalarType())
12131 continue;
12132 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12133 if (!DRE)
12134 continue;
12135 NeedToCheckForLPCs.insert(DRE->getDecl());
12136 }
12137 }
12138 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
12139 for (const Expr *Ref : C->varlists()) {
12140 if (!Ref->getType()->isScalarType())
12141 continue;
12142 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12143 if (!DRE)
12144 continue;
12145 NeedToCheckForLPCs.insert(DRE->getDecl());
12146 }
12147 }
12148 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
12149 for (const Expr *Ref : C->varlists()) {
12150 if (!Ref->getType()->isScalarType())
12151 continue;
12152 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12153 if (!DRE)
12154 continue;
12155 NeedToCheckForLPCs.insert(DRE->getDecl());
12156 }
12157 }
12158 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
12159 for (const Expr *Ref : C->varlists()) {
12160 if (!Ref->getType()->isScalarType())
12161 continue;
12162 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12163 if (!DRE)
12164 continue;
12165 NeedToCheckForLPCs.insert(DRE->getDecl());
12166 }
12167 }
12168 for (const Decl *VD : NeedToCheckForLPCs) {
12169 for (const LastprivateConditionalData &Data :
12170 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12171 if (Data.DeclToUniqueName.count(VD) > 0) {
12172 if (!Data.Disabled)
12173 NeedToAddForLPCsAsDisabled.insert(VD);
12174 break;
12175 }
12176 }
12177 }
12178}
12179
12180CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12181 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal)
12182 : CGM(CGF.CGM),
12183 Action((CGM.getLangOpts().OpenMP >= 50 &&
12184 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
12185 [](const OMPLastprivateClause *C) {
12186 return C->getKind() ==
12187 OMPC_LASTPRIVATE_conditional;
12188 }))
12189 ? ActionToDo::PushAsLastprivateConditional
12190 : ActionToDo::DoNotPush) {
12191 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12191, __PRETTY_FUNCTION__))
;
12192 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12193 return;
12194 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12195, __PRETTY_FUNCTION__))
12195 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12195, __PRETTY_FUNCTION__))
;
12196 LastprivateConditionalData &Data =
12197 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12198 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
12199 if (C->getKind() != OMPC_LASTPRIVATE_conditional)
12200 continue;
12201
12202 for (const Expr *Ref : C->varlists()) {
12203 Data.DeclToUniqueName.insert(std::make_pair(
12204 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(),
12205 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref))));
12206 }
12207 }
12208 Data.IVLVal = IVLVal;
12209 Data.Fn = CGF.CurFn;
12210}
12211
12212CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12213 CodeGenFunction &CGF, const OMPExecutableDirective &S)
12214 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) {
12215 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12215, __PRETTY_FUNCTION__))
;
12216 if (CGM.getLangOpts().OpenMP < 50)
12217 return;
12218 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12219 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12220 if (!NeedToAddForLPCsAsDisabled.empty()) {
12221 Action = ActionToDo::DisableLastprivateConditional;
12222 LastprivateConditionalData &Data =
12223 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12224 for (const Decl *VD : NeedToAddForLPCsAsDisabled)
12225 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>()));
12226 Data.Fn = CGF.CurFn;
12227 Data.Disabled = true;
12228 }
12229}
12230
12231CGOpenMPRuntime::LastprivateConditionalRAII
12232CGOpenMPRuntime::LastprivateConditionalRAII::disable(
12233 CodeGenFunction &CGF, const OMPExecutableDirective &S) {
12234 return LastprivateConditionalRAII(CGF, S);
12235}
12236
12237CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() {
12238 if (CGM.getLangOpts().OpenMP < 50)
12239 return;
12240 if (Action == ActionToDo::DisableLastprivateConditional) {
12241 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12242, __PRETTY_FUNCTION__))
12242 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12242, __PRETTY_FUNCTION__))
;
12243 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12244 }
12245 if (Action == ActionToDo::PushAsLastprivateConditional) {
12246 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12248, __PRETTY_FUNCTION__))
12247 !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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12248, __PRETTY_FUNCTION__))
12248 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12248, __PRETTY_FUNCTION__))
;
12249 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12250 }
12251}
12252
12253Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF,
12254 const VarDecl *VD) {
12255 ASTContext &C = CGM.getContext();
12256 auto I = LastprivateConditionalToTypes.find(CGF.CurFn);
12257 if (I == LastprivateConditionalToTypes.end())
12258 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first;
12259 QualType NewType;
12260 const FieldDecl *VDField;
12261 const FieldDecl *FiredField;
12262 LValue BaseLVal;
12263 auto VI = I->getSecond().find(VD);
12264 if (VI == I->getSecond().end()) {
12265 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional");
12266 RD->startDefinition();
12267 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType());
12268 FiredField = addFieldToRecordDecl(C, RD, C.CharTy);
12269 RD->completeDefinition();
12270 NewType = C.getRecordType(RD);
12271 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName());
12272 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl);
12273 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12274 } else {
12275 NewType = std::get<0>(VI->getSecond());
12276 VDField = std::get<1>(VI->getSecond());
12277 FiredField = std::get<2>(VI->getSecond());
12278 BaseLVal = std::get<3>(VI->getSecond());
12279 }
12280 LValue FiredLVal =
12281 CGF.EmitLValueForField(BaseLVal, FiredField);
12282 CGF.EmitStoreOfScalar(
12283 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)),
12284 FiredLVal);
12285 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF);
12286}
12287
12288namespace {
12289/// Checks if the lastprivate conditional variable is referenced in LHS.
12290class LastprivateConditionalRefChecker final
12291 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> {
12292 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM;
12293 const Expr *FoundE = nullptr;
12294 const Decl *FoundD = nullptr;
12295 StringRef UniqueDeclName;
12296 LValue IVLVal;
12297 llvm::Function *FoundFn = nullptr;
12298 SourceLocation Loc;
12299
12300public:
12301 bool VisitDeclRefExpr(const DeclRefExpr *E) {
12302 for (const CGOpenMPRuntime::LastprivateConditionalData &D :
12303 llvm::reverse(LPM)) {
12304 auto It = D.DeclToUniqueName.find(E->getDecl());
12305 if (It == D.DeclToUniqueName.end())
12306 continue;
12307 if (D.Disabled)
12308 return false;
12309 FoundE = E;
12310 FoundD = E->getDecl()->getCanonicalDecl();
12311 UniqueDeclName = It->second;
12312 IVLVal = D.IVLVal;
12313 FoundFn = D.Fn;
12314 break;
12315 }
12316 return FoundE == E;
12317 }
12318 bool VisitMemberExpr(const MemberExpr *E) {
12319 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase()))
12320 return false;
12321 for (const CGOpenMPRuntime::LastprivateConditionalData &D :
12322 llvm::reverse(LPM)) {
12323 auto It = D.DeclToUniqueName.find(E->getMemberDecl());
12324 if (It == D.DeclToUniqueName.end())
12325 continue;
12326 if (D.Disabled)
12327 return false;
12328 FoundE = E;
12329 FoundD = E->getMemberDecl()->getCanonicalDecl();
12330 UniqueDeclName = It->second;
12331 IVLVal = D.IVLVal;
12332 FoundFn = D.Fn;
12333 break;
12334 }
12335 return FoundE == E;
12336 }
12337 bool VisitStmt(const Stmt *S) {
12338 for (const Stmt *Child : S->children()) {
12339 if (!Child)
12340 continue;
12341 if (const auto *E = dyn_cast<Expr>(Child))
12342 if (!E->isGLValue())
12343 continue;
12344 if (Visit(Child))
12345 return true;
12346 }
12347 return false;
12348 }
12349 explicit LastprivateConditionalRefChecker(
12350 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12351 : LPM(LPM) {}
12352 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12353 getFoundData() const {
12354 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12355 }
12356};
12357} // namespace
12358
12359void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF,
12360 LValue IVLVal,
12361 StringRef UniqueDeclName,
12362 LValue LVal,
12363 SourceLocation Loc) {
12364 // Last updated loop counter for the lastprivate conditional var.
12365 // int<xx> last_iv = 0;
12366 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType());
12367 llvm::Constant *LastIV =
12368 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"}));
12369 cast<llvm::GlobalVariable>(LastIV)->setAlignment(
12370 IVLVal.getAlignment().getAsAlign());
12371 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType());
12372
12373 // Last value of the lastprivate conditional.
12374 // decltype(priv_a) last_a;
12375 llvm::Constant *Last = getOrCreateInternalVariable(
12376 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName);
12377 cast<llvm::GlobalVariable>(Last)->setAlignment(
12378 LVal.getAlignment().getAsAlign());
12379 LValue LastLVal =
12380 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment());
12381
12382 // Global loop counter. Required to handle inner parallel-for regions.
12383 // iv
12384 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc);
12385
12386 // #pragma omp critical(a)
12387 // if (last_iv <= iv) {
12388 // last_iv = iv;
12389 // last_a = priv_a;
12390 // }
12391 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
12392 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
12393 Action.Enter(CGF);
12394 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc);
12395 // (last_iv <= iv) ? Check if the variable is updated and store new
12396 // value in global var.
12397 llvm::Value *CmpRes;
12398 if (IVLVal.getType()->isSignedIntegerType()) {
12399 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal);
12400 } else {
12401 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12402, __PRETTY_FUNCTION__))
12402 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12402, __PRETTY_FUNCTION__))
;
12403 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal);
12404 }
12405 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then");
12406 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit");
12407 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
12408 // {
12409 CGF.EmitBlock(ThenBB);
12410
12411 // last_iv = iv;
12412 CGF.EmitStoreOfScalar(IVVal, LastIVLVal);
12413
12414 // last_a = priv_a;
12415 switch (CGF.getEvaluationKind(LVal.getType())) {
12416 case TEK_Scalar: {
12417 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc);
12418 CGF.EmitStoreOfScalar(PrivVal, LastLVal);
12419 break;
12420 }
12421 case TEK_Complex: {
12422 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc);
12423 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false);
12424 break;
12425 }
12426 case TEK_Aggregate:
12427 llvm_unreachable(::llvm::llvm_unreachable_internal("Aggregates are not supported in lastprivate conditional."
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12428)
12428 "Aggregates are not supported in lastprivate conditional.")::llvm::llvm_unreachable_internal("Aggregates are not supported in lastprivate conditional."
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12428)
;
12429 }
12430 // }
12431 CGF.EmitBranch(ExitBB);
12432 // There is no need to emit line number for unconditional branch.
12433 (void)ApplyDebugLocation::CreateEmpty(CGF);
12434 CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
12435 };
12436
12437 if (CGM.getLangOpts().OpenMPSimd) {
12438 // Do not emit as a critical region as no parallel region could be emitted.
12439 RegionCodeGenTy ThenRCG(CodeGen);
12440 ThenRCG(CGF);
12441 } else {
12442 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc);
12443 }
12444}
12445
12446void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF,
12447 const Expr *LHS) {
12448 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
12449 return;
12450 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack);
12451 if (!Checker.Visit(LHS))
12452 return;
12453 const Expr *FoundE;
12454 const Decl *FoundD;
12455 StringRef UniqueDeclName;
12456 LValue IVLVal;
12457 llvm::Function *FoundFn;
12458 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
12459 Checker.getFoundData();
12460 if (FoundFn != CGF.CurFn) {
12461 // Special codegen for inner parallel regions.
12462 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1;
12463 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD);
12464 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12465, __PRETTY_FUNCTION__))
12465 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12465, __PRETTY_FUNCTION__))
;
12466 QualType StructTy = std::get<0>(It->getSecond());
12467 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
12468 LValue PrivLVal = CGF.EmitLValue(FoundE);
12469 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
12470 PrivLVal.getAddress(CGF),
12471 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy)));
12472 LValue BaseLVal =
12473 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl);
12474 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl);
12475 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get(
12476 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)),
12477 FiredLVal, llvm::AtomicOrdering::Unordered,
12478 /*IsVolatile=*/true, /*isInit=*/false);
12479 return;
12480 }
12481
12482 // Private address of the lastprivate conditional in the current context.
12483 // priv_a
12484 LValue LVal = CGF.EmitLValue(FoundE);
12485 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal,
12486 FoundE->getExprLoc());
12487}
12488
12489void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional(
12490 CodeGenFunction &CGF, const OMPExecutableDirective &D,
12491 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) {
12492 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
12493 return;
12494 auto Range = llvm::reverse(LastprivateConditionalStack);
12495 auto It = llvm::find_if(
12496 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; });
12497 if (It == Range.end() || It->Fn != CGF.CurFn)
12498 return;
12499 auto LPCI = LastprivateConditionalToTypes.find(It->Fn);
12500 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12501, __PRETTY_FUNCTION__))
12501 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12501, __PRETTY_FUNCTION__))
;
12502 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
12503 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind());
12504 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
12505 for (const auto &Pair : It->DeclToUniqueName) {
12506 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl());
12507 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0)
12508 continue;
12509 auto I = LPCI->getSecond().find(Pair.first);
12510 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12511, __PRETTY_FUNCTION__))
12511 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12511, __PRETTY_FUNCTION__))
;
12512 // bool Cmp = priv_a.Fired != 0;
12513 LValue BaseLVal = std::get<3>(I->getSecond());
12514 LValue FiredLVal =
12515 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond()));
12516 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc());
12517 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res);
12518 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then");
12519 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done");
12520 // if (Cmp) {
12521 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
12522 CGF.EmitBlock(ThenBB);
12523 Address Addr = CGF.GetAddrOfLocalVar(VD);
12524 LValue LVal;
12525 if (VD->getType()->isReferenceType())
12526 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
12527 AlignmentSource::Decl);
12528 else
12529 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(),
12530 AlignmentSource::Decl);
12531 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal,
12532 D.getBeginLoc());
12533 auto AL = ApplyDebugLocation::CreateArtificial(CGF);
12534 CGF.EmitBlock(DoneBB, /*IsFinal=*/true);
12535 // }
12536 }
12537}
12538
12539void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate(
12540 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD,
12541 SourceLocation Loc) {
12542 if (CGF.getLangOpts().OpenMP < 50)
12543 return;
12544 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD);
12545 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12546, __PRETTY_FUNCTION__))
12546 "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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12546, __PRETTY_FUNCTION__))
;
12547 StringRef UniqueName = It->second;
12548 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName);
12549 // The variable was not updated in the region - exit.
12550 if (!GV)
12551 return;
12552 LValue LPLVal = CGF.MakeAddrLValue(
12553 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment());
12554 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc);
12555 CGF.EmitStoreOfScalar(Res, PrivLVal);
12556}
12557
12558llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
12559 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
12560 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
12561 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12561)
;
12562}
12563
12564llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
12565 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
12566 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
12567 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12567)
;
12568}
12569
12570llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
12571 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
12572 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
12573 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
12574 bool Tied, unsigned &NumberOfParts) {
12575 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12575)
;
12576}
12577
12578void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
12579 SourceLocation Loc,
12580 llvm::Function *OutlinedFn,
12581 ArrayRef<llvm::Value *> CapturedVars,
12582 const Expr *IfCond) {
12583 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12583)
;
12584}
12585
12586void CGOpenMPSIMDRuntime::emitCriticalRegion(
12587 CodeGenFunction &CGF, StringRef CriticalName,
12588 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
12589 const Expr *Hint) {
12590 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12590)
;
12591}
12592
12593void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
12594 const RegionCodeGenTy &MasterOpGen,
12595 SourceLocation Loc) {
12596 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12596)
;
12597}
12598
12599void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
12600 SourceLocation Loc) {
12601 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12601)
;
12602}
12603
12604void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
12605 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
12606 SourceLocation Loc) {
12607 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12607)
;
12608}
12609
12610void CGOpenMPSIMDRuntime::emitSingleRegion(
12611 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
12612 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
12613 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
12614 ArrayRef<const Expr *> AssignmentOps) {
12615 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12615)
;
12616}
12617
12618void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
12619 const RegionCodeGenTy &OrderedOpGen,
12620 SourceLocation Loc,
12621 bool IsThreads) {
12622 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12622)
;
12623}
12624
12625void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
12626 SourceLocation Loc,
12627 OpenMPDirectiveKind Kind,
12628 bool EmitChecks,
12629 bool ForceSimpleCall) {
12630 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12630)
;
12631}
12632
12633void CGOpenMPSIMDRuntime::emitForDispatchInit(
12634 CodeGenFunction &CGF, SourceLocation Loc,
12635 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
12636 bool Ordered, const DispatchRTInput &DispatchValues) {
12637 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12637)
;
12638}
12639
12640void CGOpenMPSIMDRuntime::emitForStaticInit(
12641 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
12642 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
12643 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12643)
;
12644}
12645
12646void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
12647 CodeGenFunction &CGF, SourceLocation Loc,
12648 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
12649 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12649)
;
12650}
12651
12652void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
12653 SourceLocation Loc,
12654 unsigned IVSize,
12655 bool IVSigned) {
12656 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12656)
;
12657}
12658
12659void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
12660 SourceLocation Loc,
12661 OpenMPDirectiveKind DKind) {
12662 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12662)
;
12663}
12664
12665llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
12666 SourceLocation Loc,
12667 unsigned IVSize, bool IVSigned,
12668 Address IL, Address LB,
12669 Address UB, Address ST) {
12670 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12670)
;
12671}
12672
12673void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
12674 llvm::Value *NumThreads,
12675 SourceLocation Loc) {
12676 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12676)
;
12677}
12678
12679void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
12680 ProcBindKind ProcBind,
12681 SourceLocation Loc) {
12682 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12682)
;
12683}
12684
12685Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
12686 const VarDecl *VD,
12687 Address VDAddr,
12688 SourceLocation Loc) {
12689 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12689)
;
12690}
12691
12692llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
12693 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
12694 CodeGenFunction *CGF) {
12695 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12695)
;
12696}
12697
12698Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
12699 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
12700 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12700)
;
12701}
12702
12703void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
12704 ArrayRef<const Expr *> Vars,
12705 SourceLocation Loc,
12706 llvm::AtomicOrdering AO) {
12707 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12707)
;
12708}
12709
12710void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
12711 const OMPExecutableDirective &D,
12712 llvm::Function *TaskFunction,
12713 QualType SharedsTy, Address Shareds,
12714 const Expr *IfCond,
12715 const OMPTaskDataTy &Data) {
12716 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12716)
;
12717}
12718
12719void CGOpenMPSIMDRuntime::emitTaskLoopCall(
12720 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
12721 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
12722 const Expr *IfCond, const OMPTaskDataTy &Data) {
12723 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12723)
;
12724}
12725
12726void CGOpenMPSIMDRuntime::emitReduction(
12727 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
12728 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
12729 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
12730 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-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12730, __PRETTY_FUNCTION__))
;
12731 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
12732 ReductionOps, Options);
12733}
12734
12735llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
12736 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
12737 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
12738 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12738)
;
12739}
12740
12741void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF,
12742 SourceLocation Loc,
12743 bool IsWorksharingReduction) {
12744 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12744)
;
12745}
12746
12747void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
12748 SourceLocation Loc,
12749 ReductionCodeGen &RCG,
12750 unsigned N) {
12751 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12751)
;
12752}
12753
12754Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
12755 SourceLocation Loc,
12756 llvm::Value *ReductionsPtr,
12757 LValue SharedLVal) {
12758 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12758)
;
12759}
12760
12761void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
12762 SourceLocation Loc) {
12763 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12763)
;
12764}
12765
12766void CGOpenMPSIMDRuntime::emitCancellationPointCall(
12767 CodeGenFunction &CGF, SourceLocation Loc,
12768 OpenMPDirectiveKind CancelRegion) {
12769 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12769)
;
12770}
12771
12772void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
12773 SourceLocation Loc, const Expr *IfCond,
12774 OpenMPDirectiveKind CancelRegion) {
12775 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12775)
;
12776}
12777
12778void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
12779 const OMPExecutableDirective &D, StringRef ParentName,
12780 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
12781 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
12782 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12782)
;
12783}
12784
12785void CGOpenMPSIMDRuntime::emitTargetCall(
12786 CodeGenFunction &CGF, const OMPExecutableDirective &D,
12787 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
12788 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device,
12789 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
12790 const OMPLoopDirective &D)>
12791 SizeEmitter) {
12792 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12792)
;
12793}
12794
12795bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
12796 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12796)
;
12797}
12798
12799bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
12800 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12800)
;
12801}
12802
12803bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
12804 return false;
12805}
12806
12807void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
12808 const OMPExecutableDirective &D,
12809 SourceLocation Loc,
12810 llvm::Function *OutlinedFn,
12811 ArrayRef<llvm::Value *> CapturedVars) {
12812 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12812)
;
12813}
12814
12815void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
12816 const Expr *NumTeams,
12817 const Expr *ThreadLimit,
12818 SourceLocation Loc) {
12819 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12819)
;
12820}
12821
12822void CGOpenMPSIMDRuntime::emitTargetDataCalls(
12823 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
12824 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
12825 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12825)
;
12826}
12827
12828void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
12829 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
12830 const Expr *Device) {
12831 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12831)
;
12832}
12833
12834void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
12835 const OMPLoopDirective &D,
12836 ArrayRef<Expr *> NumIterations) {
12837 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12837)
;
12838}
12839
12840void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
12841 const OMPDependClause *C) {
12842 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12842)
;
12843}
12844
12845const VarDecl *
12846CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
12847 const VarDecl *NativeParam) const {
12848 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12848)
;
12849}
12850
12851Address
12852CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
12853 const VarDecl *NativeParam,
12854 const VarDecl *TargetParam) const {
12855 llvm_unreachable("Not supported in SIMD-only mode")::llvm::llvm_unreachable_internal("Not supported in SIMD-only mode"
, "/build/llvm-toolchain-snapshot-13~++20210413100635+64c24f493e5f/clang/lib/CodeGen/CGOpenMPRuntime.cpp"
, 12855)
;
12856}

/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_iterator.h

1// Iterators -*- C++ -*-
2
3// Copyright (C) 2001-2016 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/*
26 *
27 * Copyright (c) 1994
28 * Hewlett-Packard Company
29 *
30 * Permission to use, copy, modify, distribute and sell this software
31 * and its documentation for any purpose is hereby granted without fee,
32 * provided that the above copyright notice appear in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation. Hewlett-Packard Company makes no
35 * representations about the suitability of this software for any
36 * purpose. It is provided "as is" without express or implied warranty.
37 *
38 *
39 * Copyright (c) 1996-1998
40 * Silicon Graphics Computer Systems, Inc.
41 *
42 * Permission to use, copy, modify, distribute and sell this software
43 * and its documentation for any purpose is hereby granted without fee,
44 * provided that the above copyright notice appear in all copies and
45 * that both that copyright notice and this permission notice appear
46 * in supporting documentation. Silicon Graphics makes no
47 * representations about the suitability of this software for any
48 * purpose. It is provided "as is" without express or implied warranty.
49 */
50
51/** @file bits/stl_iterator.h
52 * This is an internal header file, included by other library headers.
53 * Do not attempt to use it directly. @headername{iterator}
54 *
55 * This file implements reverse_iterator, back_insert_iterator,
56 * front_insert_iterator, insert_iterator, __normal_iterator, and their
57 * supporting functions and overloaded operators.
58 */
59
60#ifndef _STL_ITERATOR_H1
61#define _STL_ITERATOR_H1 1
62
63#include <bits/cpp_type_traits.h>
64#include <ext/type_traits.h>
65#include <bits/move.h>
66#include <bits/ptr_traits.h>
67
68namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
69{
70_GLIBCXX_BEGIN_NAMESPACE_VERSION
71
72 /**
73 * @addtogroup iterators
74 * @{
75 */
76
77 // 24.4.1 Reverse iterators
78 /**
79 * Bidirectional and random access iterators have corresponding reverse
80 * %iterator adaptors that iterate through the data structure in the
81 * opposite direction. They have the same signatures as the corresponding
82 * iterators. The fundamental relation between a reverse %iterator and its
83 * corresponding %iterator @c i is established by the identity:
84 * @code
85 * &*(reverse_iterator(i)) == &*(i - 1)
86 * @endcode
87 *
88 * <em>This mapping is dictated by the fact that while there is always a
89 * pointer past the end of an array, there might not be a valid pointer
90 * before the beginning of an array.</em> [24.4.1]/1,2
91 *
92 * Reverse iterators can be tricky and surprising at first. Their
93 * semantics make sense, however, and the trickiness is a side effect of
94 * the requirement that the iterators must be safe.
95 */
96 template<typename _Iterator>
97 class reverse_iterator
98 : public iterator<typename iterator_traits<_Iterator>::iterator_category,
99 typename iterator_traits<_Iterator>::value_type,
100 typename iterator_traits<_Iterator>::difference_type,
101 typename iterator_traits<_Iterator>::pointer,
102 typename iterator_traits<_Iterator>::reference>
103 {
104 protected:
105 _Iterator current;
106
107 typedef iterator_traits<_Iterator> __traits_type;
108
109 public:
110 typedef _Iterator iterator_type;
111 typedef typename __traits_type::difference_type difference_type;
112 typedef typename __traits_type::pointer pointer;
113 typedef typename __traits_type::reference reference;
114
115 /**
116 * The default constructor value-initializes member @p current.
117 * If it is a pointer, that means it is zero-initialized.
118 */
119 // _GLIBCXX_RESOLVE_LIB_DEFECTS
120 // 235 No specification of default ctor for reverse_iterator
121 reverse_iterator() : current() { }
122
123 /**
124 * This %iterator will move in the opposite direction that @p x does.
125 */
126 explicit
127 reverse_iterator(iterator_type __x) : current(__x) { }
128
129 /**
130 * The copy constructor is normal.
131 */
132 reverse_iterator(const reverse_iterator& __x)
133 : current(__x.current) { }
134
135 /**
136 * A %reverse_iterator across other types can be copied if the
137 * underlying %iterator can be converted to the type of @c current.
138 */
139 template<typename _Iter>
140 reverse_iterator(const reverse_iterator<_Iter>& __x)
141 : current(__x.base()) { }
142
143 /**
144 * @return @c current, the %iterator used for underlying work.
145 */
146 iterator_type
147 base() const
148 { return current; }
149
150 /**
151 * @return A reference to the value at @c --current
152 *
153 * This requires that @c --current is dereferenceable.
154 *
155 * @warning This implementation requires that for an iterator of the
156 * underlying iterator type, @c x, a reference obtained by
157 * @c *x remains valid after @c x has been modified or
158 * destroyed. This is a bug: http://gcc.gnu.org/PR51823
159 */
160 reference
161 operator*() const
162 {
163 _Iterator __tmp = current;
164 return *--__tmp;
165 }
166
167 /**
168 * @return A pointer to the value at @c --current
169 *
170 * This requires that @c --current is dereferenceable.
171 */
172 pointer
173 operator->() const
174 { return &(operator*()); }
175
176 /**
177 * @return @c *this
178 *
179 * Decrements the underlying iterator.
180 */
181 reverse_iterator&
182 operator++()
183 {
184 --current;
185 return *this;
186 }
187
188 /**
189 * @return The original value of @c *this
190 *
191 * Decrements the underlying iterator.
192 */
193 reverse_iterator
194 operator++(int)
195 {
196 reverse_iterator __tmp = *this;
197 --current;
198 return __tmp;
199 }
200
201 /**
202 * @return @c *this
203 *
204 * Increments the underlying iterator.
205 */
206 reverse_iterator&
207 operator--()
208 {
209 ++current;
210 return *this;
211 }
212
213 /**
214 * @return A reverse_iterator with the previous value of @c *this
215 *
216 * Increments the underlying iterator.
217 */
218 reverse_iterator
219 operator--(int)
220 {
221 reverse_iterator __tmp = *this;
222 ++current;
223 return __tmp;
224 }
225
226 /**
227 * @return A reverse_iterator that refers to @c current - @a __n
228 *
229 * The underlying iterator must be a Random Access Iterator.
230 */
231 reverse_iterator
232 operator+(difference_type __n) const
233 { return reverse_iterator(current - __n); }
234
235 /**
236 * @return *this
237 *
238 * Moves the underlying iterator backwards @a __n steps.
239 * The underlying iterator must be a Random Access Iterator.
240 */
241 reverse_iterator&
242 operator+=(difference_type __n)
243 {
244 current -= __n;
245 return *this;
246 }
247
248 /**
249 * @return A reverse_iterator that refers to @c current - @a __n
250 *
251 * The underlying iterator must be a Random Access Iterator.
252 */
253 reverse_iterator
254 operator-(difference_type __n) const
255 { return reverse_iterator(current + __n); }
256
257 /**
258 * @return *this
259 *
260 * Moves the underlying iterator forwards @a __n steps.
261 * The underlying iterator must be a Random Access Iterator.
262 */
263 reverse_iterator&
264 operator-=(difference_type __n)
265 {
266 current += __n;
267 return *this;
268 }
269
270 /**
271 * @return The value at @c current - @a __n - 1
272 *
273 * The underlying iterator must be a Random Access Iterator.
274 */
275 reference
276 operator[](difference_type __n) const
277 { return *(*this + __n); }
278 };
279
280 //@{
281 /**
282 * @param __x A %reverse_iterator.
283 * @param __y A %reverse_iterator.
284 * @return A simple bool.
285 *
286 * Reverse iterators forward many operations to their underlying base()
287 * iterators. Others are implemented in terms of one another.
288 *
289 */
290 template<typename _Iterator>
291 inline bool
292 operator==(const reverse_iterator<_Iterator>& __x,
293 const reverse_iterator<_Iterator>& __y)
294 { return __x.base() == __y.base(); }
8
Assuming the condition is true
9
Returning the value 1, which participates in a condition later
295
296 template<typename _Iterator>
297 inline bool
298 operator<(const reverse_iterator<_Iterator>& __x,
299 const reverse_iterator<_Iterator>& __y)
300 { return __y.base() < __x.base(); }
301
302 template<typename _Iterator>
303 inline bool
304 operator!=(const reverse_iterator<_Iterator>& __x,
305 const reverse_iterator<_Iterator>& __y)
306 { return !(__x == __y); }
7
Calling 'operator==<const clang::OMPClauseMappableExprCommon::MappableComponent *>'
10
Returning from 'operator==<const clang::OMPClauseMappableExprCommon::MappableComponent *>'
11
Returning zero, which participates in a condition later
307
308 template<typename _Iterator>
309 inline bool
310 operator>(const reverse_iterator<_Iterator>& __x,
311 const reverse_iterator<_Iterator>& __y)
312 { return __y < __x; }
313
314 template<typename _Iterator>
315 inline bool
316 operator<=(const reverse_iterator<_Iterator>& __x,
317 const reverse_iterator<_Iterator>& __y)
318 { return !(__y < __x); }
319
320 template<typename _Iterator>
321 inline bool
322 operator>=(const reverse_iterator<_Iterator>& __x,
323 const reverse_iterator<_Iterator>& __y)
324 { return !(__x < __y); }
325
326 template<typename _Iterator>
327#if __cplusplus201402L < 201103L
328 inline typename reverse_iterator<_Iterator>::difference_type
329 operator-(const reverse_iterator<_Iterator>& __x,
330 const reverse_iterator<_Iterator>& __y)
331#else
332 inline auto
333 operator-(const reverse_iterator<_Iterator>& __x,
334 const reverse_iterator<_Iterator>& __y)
335 -> decltype(__x.base() - __y.base())
336#endif
337 { return __y.base() - __x.base(); }
338
339 template<typename _Iterator>
340 inline reverse_iterator<_Iterator>
341 operator+(typename reverse_iterator<_Iterator>::difference_type __n,
342 const reverse_iterator<_Iterator>& __x)
343 { return reverse_iterator<_Iterator>(__x.base() - __n); }
344
345 // _GLIBCXX_RESOLVE_LIB_DEFECTS
346 // DR 280. Comparison of reverse_iterator to const reverse_iterator.
347 template<typename _IteratorL, typename _IteratorR>
348 inline bool
349 operator==(const reverse_iterator<_IteratorL>& __x,
350 const reverse_iterator<_IteratorR>& __y)
351 { return __x.base() == __y.base(); }
352
353 template<typename _IteratorL, typename _IteratorR>
354 inline bool
355 operator<(const reverse_iterator<_IteratorL>& __x,
356 const reverse_iterator<_IteratorR>& __y)
357 { return __y.base() < __x.base(); }
358
359 template<typename _IteratorL, typename _IteratorR>
360 inline bool
361 operator!=(const reverse_iterator<_IteratorL>& __x,
362 const reverse_iterator<_IteratorR>& __y)
363 { return !(__x == __y); }
364
365 template<typename _IteratorL, typename _IteratorR>
366 inline bool
367 operator>(const reverse_iterator<_IteratorL>& __x,
368 const reverse_iterator<_IteratorR>& __y)
369 { return __y < __x; }
370
371 template<typename _IteratorL, typename _IteratorR>
372 inline bool
373 operator<=(const reverse_iterator<_IteratorL>& __x,
374 const reverse_iterator<_IteratorR>& __y)
375 { return !(__y < __x); }
376
377 template<typename _IteratorL, typename _IteratorR>
378 inline bool
379 operator>=(const reverse_iterator<_IteratorL>& __x,
380 const reverse_iterator<_IteratorR>& __y)
381 { return !(__x < __y); }
382
383 template<typename _IteratorL, typename _IteratorR>
384#if __cplusplus201402L >= 201103L
385 // DR 685.
386 inline auto
387 operator-(const reverse_iterator<_IteratorL>& __x,
388 const reverse_iterator<_IteratorR>& __y)
389 -> decltype(__y.base() - __x.base())
390#else
391 inline typename reverse_iterator<_IteratorL>::difference_type
392 operator-(const reverse_iterator<_IteratorL>& __x,
393 const reverse_iterator<_IteratorR>& __y)
394#endif
395 { return __y.base() - __x.base(); }
396 //@}
397
398#if __cplusplus201402L >= 201103L
399 // Same as C++14 make_reverse_iterator but used in C++03 mode too.
400 template<typename _Iterator>
401 inline reverse_iterator<_Iterator>
402 __make_reverse_iterator(_Iterator __i)
403 { return reverse_iterator<_Iterator>(__i); }
404
405# if __cplusplus201402L > 201103L
406# define __cpp_lib_make_reverse_iterator201402 201402
407
408 // _GLIBCXX_RESOLVE_LIB_DEFECTS
409 // DR 2285. make_reverse_iterator
410 /// Generator function for reverse_iterator.
411 template<typename _Iterator>
412 inline reverse_iterator<_Iterator>
413 make_reverse_iterator(_Iterator __i)
414 { return reverse_iterator<_Iterator>(__i); }
415# endif
416#endif
417
418#if __cplusplus201402L >= 201103L
419 template<typename _Iterator>
420 auto
421 __niter_base(reverse_iterator<_Iterator> __it)
422 -> decltype(__make_reverse_iterator(__niter_base(__it.base())))
423 { return __make_reverse_iterator(__niter_base(__it.base())); }
424
425 template<typename _Iterator>
426 struct __is_move_iterator<reverse_iterator<_Iterator> >
427 : __is_move_iterator<_Iterator>
428 { };
429
430 template<typename _Iterator>
431 auto
432 __miter_base(reverse_iterator<_Iterator> __it)
433 -> decltype(__make_reverse_iterator(__miter_base(__it.base())))
434 { return __make_reverse_iterator(__miter_base(__it.base())); }
435#endif
436
437 // 24.4.2.2.1 back_insert_iterator
438 /**
439 * @brief Turns assignment into insertion.
440 *
441 * These are output iterators, constructed from a container-of-T.
442 * Assigning a T to the iterator appends it to the container using
443 * push_back.
444 *
445 * Tip: Using the back_inserter function to create these iterators can
446 * save typing.
447 */
448 template<typename _Container>
449 class back_insert_iterator
450 : public iterator<output_iterator_tag, void, void, void, void>
451 {
452 protected:
453 _Container* container;
454
455 public:
456 /// A nested typedef for the type of whatever container you used.
457 typedef _Container container_type;
458
459 /// The only way to create this %iterator is with a container.
460 explicit
461 back_insert_iterator(_Container& __x)
462 : container(std::__addressof(__x)) { }
463
464 /**
465 * @param __value An instance of whatever type
466 * container_type::const_reference is; presumably a
467 * reference-to-const T for container<T>.
468 * @return This %iterator, for chained operations.
469 *
470 * This kind of %iterator doesn't really have a @a position in the
471 * container (you can think of the position as being permanently at
472 * the end, if you like). Assigning a value to the %iterator will
473 * always append the value to the end of the container.
474 */
475#if __cplusplus201402L < 201103L
476 back_insert_iterator&
477 operator=(typename _Container::const_reference __value)
478 {
479 container->push_back(__value);
480 return *this;
481 }
482#else
483 back_insert_iterator&
484 operator=(const typename _Container::value_type& __value)
485 {
486 container->push_back(__value);
487 return *this;
488 }
489
490 back_insert_iterator&
491 operator=(typename _Container::value_type&& __value)
492 {
493 container->push_back(std::move(__value));
494 return *this;
495 }
496#endif
497
498 /// Simply returns *this.
499 back_insert_iterator&
500 operator*()
501 { return *this; }
502
503 /// Simply returns *this. (This %iterator does not @a move.)
504 back_insert_iterator&
505 operator++()
506 { return *this; }
507
508 /// Simply returns *this. (This %iterator does not @a move.)
509 back_insert_iterator
510 operator++(int)
511 { return *this; }
512 };
513
514 /**
515 * @param __x A container of arbitrary type.
516 * @return An instance of back_insert_iterator working on @p __x.
517 *
518 * This wrapper function helps in creating back_insert_iterator instances.
519 * Typing the name of the %iterator requires knowing the precise full
520 * type of the container, which can be tedious and impedes generic
521 * programming. Using this function lets you take advantage of automatic
522 * template parameter deduction, making the compiler match the correct
523 * types for you.
524 */
525 template<typename _Container>
526 inline back_insert_iterator<_Container>
527 back_inserter(_Container& __x)
528 { return back_insert_iterator<_Container>(__x); }
529
530 /**
531 * @brief Turns assignment into insertion.
532 *
533 * These are output iterators, constructed from a container-of-T.
534 * Assigning a T to the iterator prepends it to the container using
535 * push_front.
536 *
537 * Tip: Using the front_inserter function to create these iterators can
538 * save typing.
539 */
540 template<typename _Container>
541 class front_insert_iterator
542 : public iterator<output_iterator_tag, void, void, void, void>
543 {
544 protected:
545 _Container* container;
546
547 public:
548 /// A nested typedef for the type of whatever container you used.
549 typedef _Container container_type;
550
551 /// The only way to create this %iterator is with a container.
552 explicit front_insert_iterator(_Container& __x)
553 : container(std::__addressof(__x)) { }
554
555 /**
556 * @param __value An instance of whatever type
557 * container_type::const_reference is; presumably a
558 * reference-to-const T for container<T>.
559 * @return This %iterator, for chained operations.
560 *
561 * This kind of %iterator doesn't really have a @a position in the
562 * container (you can think of the position as being permanently at
563 * the front, if you like). Assigning a value to the %iterator will
564 * always prepend the value to the front of the container.
565 */
566#if __cplusplus201402L < 201103L
567 front_insert_iterator&
568 operator=(typename _Container::const_reference __value)
569 {
570 container->push_front(__value);
571 return *this;
572 }
573#else
574 front_insert_iterator&
575 operator=(const typename _Container::value_type& __value)
576 {
577 container->push_front(__value);
578 return *this;
579 }
580
581 front_insert_iterator&
582 operator=(typename _Container::value_type&& __value)
583 {
584 container->push_front(std::move(__value));
585 return *this;
586 }
587#endif
588
589 /// Simply returns *this.
590 front_insert_iterator&
591 operator*()
592 { return *this; }
593
594 /// Simply returns *this. (This %iterator does not @a move.)
595 front_insert_iterator&
596 operator++()
597 { return *this; }
598
599 /// Simply returns *this. (This %iterator does not @a move.)
600 front_insert_iterator
601 operator++(int)
602 { return *this; }
603 };
604
605 /**
606 * @param __x A container of arbitrary type.
607 * @return An instance of front_insert_iterator working on @p x.
608 *
609 * This wrapper function helps in creating front_insert_iterator instances.
610 * Typing the name of the %iterator requires knowing the precise full
611 * type of the container, which can be tedious and impedes generic
612 * programming. Using this function lets you take advantage of automatic
613 * template parameter deduction, making the compiler match the correct
614 * types for you.
615 */
616 template<typename _Container>
617 inline front_insert_iterator<_Container>
618 front_inserter(_Container& __x)
619 { return front_insert_iterator<_Container>(__x); }
620
621 /**
622 * @brief Turns assignment into insertion.
623 *
624 * These are output iterators, constructed from a container-of-T.
625 * Assigning a T to the iterator inserts it in the container at the
626 * %iterator's position, rather than overwriting the value at that
627 * position.
628 *
629 * (Sequences will actually insert a @e copy of the value before the
630 * %iterator's position.)
631 *
632 * Tip: Using the inserter function to create these iterators can
633 * save typing.
634 */
635 template<typename _Container>
636 class insert_iterator
637 : public iterator<output_iterator_tag, void, void, void, void>
638 {
639 protected:
640 _Container* container;
641 typename _Container::iterator iter;
642
643 public:
644 /// A nested typedef for the type of whatever container you used.
645 typedef _Container container_type;
646
647 /**
648 * The only way to create this %iterator is with a container and an
649 * initial position (a normal %iterator into the container).
650 */
651 insert_iterator(_Container& __x, typename _Container::iterator __i)
652 : container(std::__addressof(__x)), iter(__i) {}
653
654 /**
655 * @param __value An instance of whatever type
656 * container_type::const_reference is; presumably a
657 * reference-to-const T for container<T>.
658 * @return This %iterator, for chained operations.
659 *
660 * This kind of %iterator maintains its own position in the
661 * container. Assigning a value to the %iterator will insert the
662 * value into the container at the place before the %iterator.
663 *
664 * The position is maintained such that subsequent assignments will
665 * insert values immediately after one another. For example,
666 * @code
667 * // vector v contains A and Z
668 *
669 * insert_iterator i (v, ++v.begin());
670 * i = 1;
671 * i = 2;
672 * i = 3;
673 *
674 * // vector v contains A, 1, 2, 3, and Z
675 * @endcode
676 */
677#if __cplusplus201402L < 201103L
678 insert_iterator&
679 operator=(typename _Container::const_reference __value)
680 {
681 iter = container->insert(iter, __value);
682 ++iter;
683 return *this;
684 }
685#else
686 insert_iterator&
687 operator=(const typename _Container::value_type& __value)
688 {
689 iter = container->insert(iter, __value);
690 ++iter;
691 return *this;
692 }
693
694 insert_iterator&
695 operator=(typename _Container::value_type&& __value)
696 {
697 iter = container->insert(iter, std::move(__value));
698 ++iter;
699 return *this;
700 }
701#endif
702
703 /// Simply returns *this.
704 insert_iterator&
705 operator*()
706 { return *this; }
707
708 /// Simply returns *this. (This %iterator does not @a move.)
709 insert_iterator&
710 operator++()
711 { return *this; }
712
713 /// Simply returns *this. (This %iterator does not @a move.)
714 insert_iterator&
715 operator++(int)
716 { return *this; }
717 };
718
719 /**
720 * @param __x A container of arbitrary type.
721 * @return An instance of insert_iterator working on @p __x.
722 *
723 * This wrapper function helps in creating insert_iterator instances.
724 * Typing the name of the %iterator requires knowing the precise full
725 * type of the container, which can be tedious and impedes generic
726 * programming. Using this function lets you take advantage of automatic
727 * template parameter deduction, making the compiler match the correct
728 * types for you.
729 */
730 template<typename _Container, typename _Iterator>
731 inline insert_iterator<_Container>
732 inserter(_Container& __x, _Iterator __i)
733 {
734 return insert_iterator<_Container>(__x,
735 typename _Container::iterator(__i));
736 }
737
738 // @} group iterators
739
740_GLIBCXX_END_NAMESPACE_VERSION
741} // namespace
742
743namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
744{
745_GLIBCXX_BEGIN_NAMESPACE_VERSION
746
747 // This iterator adapter is @a normal in the sense that it does not
748 // change the semantics of any of the operators of its iterator
749 // parameter. Its primary purpose is to convert an iterator that is
750 // not a class, e.g. a pointer, into an iterator that is a class.
751 // The _Container parameter exists solely so that different containers
752 // using this template can instantiate different types, even if the
753 // _Iterator parameter is the same.
754 using std::iterator_traits;
755 using std::iterator;
756 template<typename _Iterator, typename _Container>
757 class __normal_iterator
758 {
759 protected:
760 _Iterator _M_current;
761
762 typedef iterator_traits<_Iterator> __traits_type;
763
764 public:
765 typedef _Iterator iterator_type;
766 typedef typename __traits_type::iterator_category iterator_category;
767 typedef typename __traits_type::value_type value_type;
768 typedef typename __traits_type::difference_type difference_type;
769 typedef typename __traits_type::reference reference;
770 typedef typename __traits_type::pointer pointer;
771
772 _GLIBCXX_CONSTEXPRconstexpr __normal_iterator() _GLIBCXX_NOEXCEPTnoexcept
773 : _M_current(_Iterator()) { }
774
775 explicit
776 __normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPTnoexcept
777 : _M_current(__i) { }
778
779 // Allow iterator to const_iterator conversion
780 template<typename _Iter>
781 __normal_iterator(const __normal_iterator<_Iter,
782 typename __enable_if<
783 (std::__are_same<_Iter, typename _Container::pointer>::__value),
784 _Container>::__type>& __i) _GLIBCXX_NOEXCEPTnoexcept
785 : _M_current(__i.base()) { }
786
787 // Forward iterator requirements
788 reference
789 operator*() const _GLIBCXX_NOEXCEPTnoexcept
790 { return *_M_current; }
791
792 pointer
793 operator->() const _GLIBCXX_NOEXCEPTnoexcept
794 { return _M_current; }
795
796 __normal_iterator&
797 operator++() _GLIBCXX_NOEXCEPTnoexcept
798 {
799 ++_M_current;
800 return *this;
801 }
802
803 __normal_iterator
804 operator++(int) _GLIBCXX_NOEXCEPTnoexcept
805 { return __normal_iterator(_M_current++); }
806
807 // Bidirectional iterator requirements
808 __normal_iterator&
809 operator--() _GLIBCXX_NOEXCEPTnoexcept
810 {
811 --_M_current;
812 return *this;
813 }
814
815 __normal_iterator
816 operator--(int) _GLIBCXX_NOEXCEPTnoexcept
817 { return __normal_iterator(_M_current--); }
818
819 // Random access iterator requirements
820 reference
821 operator[](difference_type __n) const _GLIBCXX_NOEXCEPTnoexcept
822 { return _M_current[__n]; }
823
824 __normal_iterator&
825 operator+=(difference_type __n) _GLIBCXX_NOEXCEPTnoexcept
826 { _M_current += __n; return *this; }
827
828 __normal_iterator
829 operator+(difference_type __n) const _GLIBCXX_NOEXCEPTnoexcept
830 { return __normal_iterator(_M_current + __n); }
831
832 __normal_iterator&
833 operator-=(difference_type __n) _GLIBCXX_NOEXCEPTnoexcept
834 { _M_current -= __n; return *this; }
835
836 __normal_iterator
837 operator-(difference_type __n) const _GLIBCXX_NOEXCEPTnoexcept
838 { return __normal_iterator(_M_current - __n); }
839
840 const _Iterator&
841 base() const _GLIBCXX_NOEXCEPTnoexcept
842 { return _M_current; }
843 };
844
845 // Note: In what follows, the left- and right-hand-side iterators are
846 // allowed to vary in types (conceptually in cv-qualification) so that
847 // comparison between cv-qualified and non-cv-qualified iterators be
848 // valid. However, the greedy and unfriendly operators in std::rel_ops
849 // will make overload resolution ambiguous (when in scope) if we don't
850 // provide overloads whose operands are of the same type. Can someone
851 // remind me what generic programming is about? -- Gaby
852
853 // Forward iterator requirements
854 template<typename _IteratorL, typename _IteratorR, typename _Container>
855 inline bool
856 operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
857 const __normal_iterator<_IteratorR, _Container>& __rhs)
858 _GLIBCXX_NOEXCEPTnoexcept
859 { return __lhs.base() == __rhs.base(); }
860
861 template<typename _Iterator, typename _Container>
862 inline bool
863 operator==(const __normal_iterator<_Iterator, _Container>& __lhs,
864 const __normal_iterator<_Iterator, _Container>& __rhs)
865 _GLIBCXX_NOEXCEPTnoexcept
866 { return __lhs.base() == __rhs.base(); }
867
868 template<typename _IteratorL, typename _IteratorR, typename _Container>
869 inline bool
870 operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs,
871 const __normal_iterator<_IteratorR, _Container>& __rhs)
872 _GLIBCXX_NOEXCEPTnoexcept
873 { return __lhs.base() != __rhs.base(); }
874
875 template<typename _Iterator, typename _Container>
876 inline bool
877 operator!=(const __normal_iterator<_Iterator, _Container>& __lhs,
878 const __normal_iterator<_Iterator, _Container>& __rhs)
879 _GLIBCXX_NOEXCEPTnoexcept
880 { return __lhs.base() != __rhs.base(); }
881
882 // Random access iterator requirements
883 template<typename _IteratorL, typename _IteratorR, typename _Container>
884 inline bool
885 operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
886 const __normal_iterator<_IteratorR, _Container>& __rhs)
887 _GLIBCXX_NOEXCEPTnoexcept
888 { return __lhs.base() < __rhs.base(); }
889
890 template<typename _Iterator, typename _Container>
891 inline bool
892 operator<(const __normal_iterator<_Iterator, _Container>& __lhs,
893 const __normal_iterator<_Iterator, _Container>& __rhs)
894 _GLIBCXX_NOEXCEPTnoexcept
895 { return __lhs.base() < __rhs.base(); }
896
897 template<typename _IteratorL, typename _IteratorR, typename _Container>
898 inline bool
899 operator>(const __normal_iterator<_IteratorL, _Container>& __lhs,
900 const __normal_iterator<_IteratorR, _Container>& __rhs)
901 _GLIBCXX_NOEXCEPTnoexcept
902 { return __lhs.base() > __rhs.base(); }
903
904 template<typename _Iterator, typename _Container>
905 inline bool
906 operator>(const __normal_iterator<_Iterator, _Container>& __lhs,
907 const __normal_iterator<_Iterator, _Container>& __rhs)
908 _GLIBCXX_NOEXCEPTnoexcept
909 { return __lhs.base() > __rhs.base(); }
910
911 template<typename _IteratorL, typename _IteratorR, typename _Container>
912 inline bool
913 operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs,
914 const __normal_iterator<_IteratorR, _Container>& __rhs)
915 _GLIBCXX_NOEXCEPTnoexcept
916 { return __lhs.base() <= __rhs.base(); }
917
918 template<typename _Iterator, typename _Container>
919 inline bool
920 operator<=(const __normal_iterator<_Iterator, _Container>& __lhs,
921 const __normal_iterator<_Iterator, _Container>& __rhs)
922 _GLIBCXX_NOEXCEPTnoexcept
923 { return __lhs.base() <= __rhs.base(); }
924
925 template<typename _IteratorL, typename _IteratorR, typename _Container>
926 inline bool
927 operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs,
928 const __normal_iterator<_IteratorR, _Container>& __rhs)
929 _GLIBCXX_NOEXCEPTnoexcept
930 { return __lhs.base() >= __rhs.base(); }
931
932 template<typename _Iterator, typename _Container>
933 inline bool
934 operator>=(const __normal_iterator<_Iterator, _Container>& __lhs,
935 const __normal_iterator<_Iterator, _Container>& __rhs)
936 _GLIBCXX_NOEXCEPTnoexcept
937 { return __lhs.base() >= __rhs.base(); }
938
939 // _GLIBCXX_RESOLVE_LIB_DEFECTS
940 // According to the resolution of DR179 not only the various comparison
941 // operators but also operator- must accept mixed iterator/const_iterator
942 // parameters.
943 template<typename _IteratorL, typename _IteratorR, typename _Container>
944#if __cplusplus201402L >= 201103L
945 // DR 685.
946 inline auto
947 operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
948 const __normal_iterator<_IteratorR, _Container>& __rhs) noexcept
949 -> decltype(__lhs.base() - __rhs.base())
950#else
951 inline typename __normal_iterator<_IteratorL, _Container>::difference_type
952 operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
953 const __normal_iterator<_IteratorR, _Container>& __rhs)
954#endif
955 { return __lhs.base() - __rhs.base(); }
956
957 template<typename _Iterator, typename _Container>
958 inline typename __normal_iterator<_Iterator, _Container>::difference_type
959 operator-(const __normal_iterator<_Iterator, _Container>& __lhs,
960 const __normal_iterator<_Iterator, _Container>& __rhs)
961 _GLIBCXX_NOEXCEPTnoexcept
962 { return __lhs.base() - __rhs.base(); }
963
964 template<typename _Iterator, typename _Container>
965 inline __normal_iterator<_Iterator, _Container>
966 operator+(typename __normal_iterator<_Iterator, _Container>::difference_type
967 __n, const __normal_iterator<_Iterator, _Container>& __i)
968 _GLIBCXX_NOEXCEPTnoexcept
969 { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); }
970
971_GLIBCXX_END_NAMESPACE_VERSION
972} // namespace
973
974namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
975{
976_GLIBCXX_BEGIN_NAMESPACE_VERSION
977
978 template<typename _Iterator, typename _Container>
979 _Iterator
980 __niter_base(__gnu_cxx::__normal_iterator<_Iterator, _Container> __it)
981 { return __it.base(); }
982
983_GLIBCXX_END_NAMESPACE_VERSION
984} // namespace
985
986#if __cplusplus201402L >= 201103L
987
988namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
989{
990_GLIBCXX_BEGIN_NAMESPACE_VERSION
991
992 /**
993 * @addtogroup iterators
994 * @{
995 */
996
997 // 24.4.3 Move iterators
998 /**
999 * Class template move_iterator is an iterator adapter with the same
1000 * behavior as the underlying iterator except that its dereference
1001 * operator implicitly converts the value returned by the underlying
1002 * iterator's dereference operator to an rvalue reference. Some
1003 * generic algorithms can be called with move iterators to replace
1004 * copying with moving.
1005 */
1006 template<typename _Iterator>
1007 class move_iterator
1008 {
1009 protected:
1010 _Iterator _M_current;
1011
1012 typedef iterator_traits<_Iterator> __traits_type;
1013 typedef typename __traits_type::reference __base_ref;
1014
1015 public:
1016 typedef _Iterator iterator_type;
1017 typedef typename __traits_type::iterator_category iterator_category;
1018 typedef typename __traits_type::value_type value_type;
1019 typedef typename __traits_type::difference_type difference_type;
1020 // NB: DR 680.
1021 typedef _Iterator pointer;
1022 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1023 // 2106. move_iterator wrapping iterators returning prvalues
1024 typedef typename conditional<is_reference<__base_ref>::value,
1025 typename remove_reference<__base_ref>::type&&,
1026 __base_ref>::type reference;
1027
1028 move_iterator()
1029 : _M_current() { }
1030
1031 explicit
1032 move_iterator(iterator_type __i)
1033 : _M_current(__i) { }
1034
1035 template<typename _Iter>
1036 move_iterator(const move_iterator<_Iter>& __i)
1037 : _M_current(__i.base()) { }
1038
1039 iterator_type
1040 base() const
1041 { return _M_current; }
1042
1043 reference
1044 operator*() const
1045 { return static_cast<reference>(*_M_current); }
1046
1047 pointer
1048 operator->() const
1049 { return _M_current; }
1050
1051 move_iterator&
1052 operator++()
1053 {
1054 ++_M_current;
1055 return *this;
1056 }
1057
1058 move_iterator
1059 operator++(int)
1060 {
1061 move_iterator __tmp = *this;
1062 ++_M_current;
1063 return __tmp;
1064 }
1065
1066 move_iterator&
1067 operator--()
1068 {
1069 --_M_current;
1070 return *this;
1071 }
1072
1073 move_iterator
1074 operator--(int)
1075 {
1076 move_iterator __tmp = *this;
1077 --_M_current;
1078 return __tmp;
1079 }
1080
1081 move_iterator
1082 operator+(difference_type __n) const
1083 { return move_iterator(_M_current + __n); }
1084
1085 move_iterator&
1086 operator+=(difference_type __n)
1087 {
1088 _M_current += __n;
1089 return *this;
1090 }
1091
1092 move_iterator
1093 operator-(difference_type __n) const
1094 { return move_iterator(_M_current - __n); }
1095
1096 move_iterator&
1097 operator-=(difference_type __n)
1098 {
1099 _M_current -= __n;
1100 return *this;
1101 }
1102
1103 reference
1104 operator[](difference_type __n) const
1105 { return std::move(_M_current[__n]); }
1106 };
1107
1108 // Note: See __normal_iterator operators note from Gaby to understand
1109 // why there are always 2 versions for most of the move_iterator
1110 // operators.
1111 template<typename _IteratorL, typename _IteratorR>
1112 inline bool
1113 operator==(const move_iterator<_IteratorL>& __x,
1114 const move_iterator<_IteratorR>& __y)
1115 { return __x.base() == __y.base(); }
1116
1117 template<typename _Iterator>
1118 inline bool
1119 operator==(const move_iterator<_Iterator>& __x,
1120 const move_iterator<_Iterator>& __y)
1121 { return __x.base() == __y.base(); }
1122
1123 template<typename _IteratorL, typename _IteratorR>
1124 inline bool
1125 operator!=(const move_iterator<_IteratorL>& __x,
1126 const move_iterator<_IteratorR>& __y)
1127 { return !(__x == __y); }
1128
1129 template<typename _Iterator>
1130 inline bool
1131 operator!=(const move_iterator<_Iterator>& __x,
1132 const move_iterator<_Iterator>& __y)
1133 { return !(__x == __y); }
1134
1135 template<typename _IteratorL, typename _IteratorR>
1136 inline bool
1137 operator<(const move_iterator<_IteratorL>& __x,
1138 const move_iterator<_IteratorR>& __y)
1139 { return __x.base() < __y.base(); }
1140
1141 template<typename _Iterator>
1142 inline bool
1143 operator<(const move_iterator<_Iterator>& __x,
1144 const move_iterator<_Iterator>& __y)
1145 { return __x.base() < __y.base(); }
1146
1147 template<typename _IteratorL, typename _IteratorR>
1148 inline bool
1149 operator<=(const move_iterator<_IteratorL>& __x,
1150 const move_iterator<_IteratorR>& __y)
1151 { return !(__y < __x); }
1152
1153 template<typename _Iterator>
1154 inline bool
1155 operator<=(const move_iterator<_Iterator>& __x,
1156 const move_iterator<_Iterator>& __y)
1157 { return !(__y < __x); }
1158
1159 template<typename _IteratorL, typename _IteratorR>
1160 inline bool
1161 operator>(const move_iterator<_IteratorL>& __x,
1162 const move_iterator<_IteratorR>& __y)
1163 { return __y < __x; }
1164
1165 template<typename _Iterator>
1166 inline bool
1167 operator>(const move_iterator<_Iterator>& __x,
1168 const move_iterator<_Iterator>& __y)
1169 { return __y < __x; }
1170
1171 template<typename _IteratorL, typename _IteratorR>
1172 inline bool
1173 operator>=(const move_iterator<_IteratorL>& __x,
1174 const move_iterator<_IteratorR>& __y)
1175 { return !(__x < __y); }
1176
1177 template<typename _Iterator>
1178 inline bool
1179 operator>=(const move_iterator<_Iterator>& __x,
1180 const move_iterator<_Iterator>& __y)
1181 { return !(__x < __y); }
1182
1183 // DR 685.
1184 template<typename _IteratorL, typename _IteratorR>
1185 inline auto
1186 operator-(const move_iterator<_IteratorL>& __x,
1187 const move_iterator<_IteratorR>& __y)
1188 -> decltype(__x.base() - __y.base())
1189 { return __x.base() - __y.base(); }
1190
1191 template<typename _Iterator>
1192 inline auto
1193 operator-(const move_iterator<_Iterator>& __x,
1194 const move_iterator<_Iterator>& __y)
1195 -> decltype(__x.base() - __y.base())
1196 { return __x.base() - __y.base(); }
1197
1198 template<typename _Iterator>
1199 inline move_iterator<_Iterator>
1200 operator+(typename move_iterator<_Iterator>::difference_type __n,
1201 const move_iterator<_Iterator>& __x)
1202 { return __x + __n; }
1203
1204 template<typename _Iterator>
1205 inline move_iterator<_Iterator>
1206 make_move_iterator(_Iterator __i)
1207 { return move_iterator<_Iterator>(__i); }
1208
1209 template<typename _Iterator, typename _ReturnType
1210 = typename conditional<__move_if_noexcept_cond
1211 <typename iterator_traits<_Iterator>::value_type>::value,
1212 _Iterator, move_iterator<_Iterator>>::type>
1213 inline _ReturnType
1214 __make_move_if_noexcept_iterator(_Iterator __i)
1215 { return _ReturnType(__i); }
1216
1217 // Overload for pointers that matches std::move_if_noexcept more closely,
1218 // returning a constant iterator when we don't want to move.
1219 template<typename _Tp, typename _ReturnType
1220 = typename conditional<__move_if_noexcept_cond<_Tp>::value,
1221 const _Tp*, move_iterator<_Tp*>>::type>
1222 inline _ReturnType
1223 __make_move_if_noexcept_iterator(_Tp* __i)
1224 { return _ReturnType(__i); }
1225
1226 // @} group iterators
1227
1228 template<typename _Iterator>
1229 auto
1230 __niter_base(move_iterator<_Iterator> __it)
1231 -> decltype(make_move_iterator(__niter_base(__it.base())))
1232 { return make_move_iterator(__niter_base(__it.base())); }
1233
1234 template<typename _Iterator>
1235 struct __is_move_iterator<move_iterator<_Iterator> >
1236 {
1237 enum { __value = 1 };
1238 typedef __true_type __type;
1239 };
1240
1241 template<typename _Iterator>
1242 auto
1243 __miter_base(move_iterator<_Iterator> __it)
1244 -> decltype(__miter_base(__it.base()))
1245 { return __miter_base(__it.base()); }
1246
1247_GLIBCXX_END_NAMESPACE_VERSION
1248} // namespace
1249
1250#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter)std::make_move_iterator(_Iter) std::make_move_iterator(_Iter)
1251#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter)std::__make_move_if_noexcept_iterator(_Iter) \
1252 std::__make_move_if_noexcept_iterator(_Iter)
1253#else
1254#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter)std::make_move_iterator(_Iter) (_Iter)
1255#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter)std::__make_move_if_noexcept_iterator(_Iter) (_Iter)
1256#endif // C++11
1257
1258#ifdef _GLIBCXX_DEBUG
1259# include <debug/stl_iterator.h>
1260#endif
1261
1262#endif