blob: 75103db2667ac90c582f05de6ce72f0ad3cb8081 [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides a class for OpenMP runtime code generation.
11//
12//===----------------------------------------------------------------------===//
13
Samuel Antaoee8fb302016-01-06 13:42:12 +000014#include "CGCXXABI.h"
15#include "CGCleanup.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000016#include "CGOpenMPRuntime.h"
17#include "CodeGenFunction.h"
18#include "clang/AST/Decl.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000019#include "clang/AST/StmtOpenMP.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000020#include "llvm/ADT/ArrayRef.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000021#include "llvm/Bitcode/ReaderWriter.h"
Alexey Bataevd74d0602014-10-13 06:02:40 +000022#include "llvm/IR/CallSite.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000023#include "llvm/IR/DerivedTypes.h"
24#include "llvm/IR/GlobalValue.h"
25#include "llvm/IR/Value.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000026#include "llvm/Support/Format.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000027#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000028#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000029
30using namespace clang;
31using namespace CodeGen;
32
Benjamin Kramerc52193f2014-10-10 13:57:57 +000033namespace {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000034/// \brief Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000035class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
36public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000037 /// \brief Kinds of OpenMP regions used in codegen.
38 enum CGOpenMPRegionKind {
39 /// \brief Region with outlined function for standalone 'parallel'
40 /// directive.
41 ParallelOutlinedRegion,
42 /// \brief Region with outlined function for standalone 'task' directive.
43 TaskOutlinedRegion,
44 /// \brief Region for constructs that do not require function outlining,
45 /// like 'for', 'sections', 'atomic' etc. directives.
46 InlinedRegion,
Samuel Antaobed3c462015-10-02 16:14:20 +000047 /// \brief Region with outlined function for standalone 'target' directive.
48 TargetRegion,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000049 };
Alexey Bataev18095712014-10-10 12:19:54 +000050
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000051 CGOpenMPRegionInfo(const CapturedStmt &CS,
52 const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000053 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
54 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000055 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000056 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000057
58 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000059 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
60 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000061 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000062 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000063
64 /// \brief Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000065 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000066 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000067
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000068 /// \brief Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000069 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000070
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000071 /// \brief Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000072 /// \return LValue for thread id variable. This LValue always has type int32*.
73 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000074
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000075 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000076
Alexey Bataev81c7ea02015-07-03 09:56:58 +000077 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
78
Alexey Bataev25e5b442015-09-15 12:52:43 +000079 bool hasCancel() const { return HasCancel; }
80
Alexey Bataev18095712014-10-10 12:19:54 +000081 static bool classof(const CGCapturedStmtInfo *Info) {
82 return Info->getKind() == CR_OpenMP;
83 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000084
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000085protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000086 CGOpenMPRegionKind RegionKind;
Hans Wennborg45c74392016-01-12 20:54:36 +000087 RegionCodeGenTy CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000088 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +000089 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000090};
Alexey Bataev18095712014-10-10 12:19:54 +000091
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000092/// \brief API for captured statement code generation in OpenMP constructs.
93class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
94public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000095 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +000096 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +000097 OpenMPDirectiveKind Kind, bool HasCancel)
98 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
99 HasCancel),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000100 ThreadIDVar(ThreadIDVar) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000101 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
102 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000103
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000104 /// \brief Get a variable or parameter for storing global thread id
105 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000106 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000107
Alexey Bataev18095712014-10-10 12:19:54 +0000108 /// \brief Get the name of the capture helper.
Benjamin Kramerc52193f2014-10-10 13:57:57 +0000109 StringRef getHelperName() const override { return ".omp_outlined."; }
Alexey Bataev18095712014-10-10 12:19:54 +0000110
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000111 static bool classof(const CGCapturedStmtInfo *Info) {
112 return CGOpenMPRegionInfo::classof(Info) &&
113 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
114 ParallelOutlinedRegion;
115 }
116
Alexey Bataev18095712014-10-10 12:19:54 +0000117private:
118 /// \brief A variable or parameter storing global thread id for OpenMP
119 /// constructs.
120 const VarDecl *ThreadIDVar;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000121};
122
Alexey Bataev62b63b12015-03-10 07:28:44 +0000123/// \brief API for captured statement code generation in OpenMP constructs.
124class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo {
125public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000126 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000127 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000128 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000129 OpenMPDirectiveKind Kind, bool HasCancel)
130 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000131 ThreadIDVar(ThreadIDVar) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000132 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
133 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000134
Alexey Bataev62b63b12015-03-10 07:28:44 +0000135 /// \brief Get a variable or parameter for storing global thread id
136 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000137 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000138
139 /// \brief Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000140 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000141
Alexey Bataev62b63b12015-03-10 07:28:44 +0000142 /// \brief Get the name of the capture helper.
143 StringRef getHelperName() const override { return ".omp_outlined."; }
144
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000145 static bool classof(const CGCapturedStmtInfo *Info) {
146 return CGOpenMPRegionInfo::classof(Info) &&
147 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
148 TaskOutlinedRegion;
149 }
150
Alexey Bataev62b63b12015-03-10 07:28:44 +0000151private:
152 /// \brief A variable or parameter storing global thread id for OpenMP
153 /// constructs.
154 const VarDecl *ThreadIDVar;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000155};
156
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000157/// \brief API for inlined captured statement code generation in OpenMP
158/// constructs.
159class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
160public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000161 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000162 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000163 OpenMPDirectiveKind Kind, bool HasCancel)
164 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
165 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000166 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000167
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000168 // \brief Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000169 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000170 if (OuterRegionInfo)
171 return OuterRegionInfo->getContextValue();
172 llvm_unreachable("No context value for inlined OpenMP region");
173 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000174
Hans Wennborg7eb54642015-09-10 17:07:54 +0000175 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000176 if (OuterRegionInfo) {
177 OuterRegionInfo->setContextValue(V);
178 return;
179 }
180 llvm_unreachable("No context value for inlined OpenMP region");
181 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000182
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000183 /// \brief Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000184 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000185 if (OuterRegionInfo)
186 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000187 // If there is no outer outlined region,no need to lookup in a list of
188 // captured variables, we can use the original one.
189 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000190 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000191
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000192 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000193 if (OuterRegionInfo)
194 return OuterRegionInfo->getThisFieldDecl();
195 return nullptr;
196 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000197
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000198 /// \brief Get a variable or parameter for storing global thread id
199 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000200 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000201 if (OuterRegionInfo)
202 return OuterRegionInfo->getThreadIDVariable();
203 return nullptr;
204 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000205
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000206 /// \brief Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000207 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000208 if (auto *OuterRegionInfo = getOldCSI())
209 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000210 llvm_unreachable("No helper name for inlined OpenMP construct");
211 }
212
213 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
214
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000215 static bool classof(const CGCapturedStmtInfo *Info) {
216 return CGOpenMPRegionInfo::classof(Info) &&
217 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
218 }
219
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000220private:
221 /// \brief CodeGen info about outer OpenMP region.
222 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
223 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000224};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000225
Samuel Antaobed3c462015-10-02 16:14:20 +0000226/// \brief API for captured statement code generation in OpenMP target
227/// constructs. For this captures, implicit parameters are used instead of the
Samuel Antaoee8fb302016-01-06 13:42:12 +0000228/// captured fields. The name of the target region has to be unique in a given
229/// application so it is provided by the client, because only the client has
230/// the information to generate that.
Samuel Antaobed3c462015-10-02 16:14:20 +0000231class CGOpenMPTargetRegionInfo : public CGOpenMPRegionInfo {
232public:
233 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000234 const RegionCodeGenTy &CodeGen, StringRef HelperName)
Samuel Antaobed3c462015-10-02 16:14:20 +0000235 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000236 /*HasCancel=*/false),
237 HelperName(HelperName) {}
Samuel Antaobed3c462015-10-02 16:14:20 +0000238
239 /// \brief This is unused for target regions because each starts executing
240 /// with a single thread.
241 const VarDecl *getThreadIDVariable() const override { return nullptr; }
242
243 /// \brief Get the name of the capture helper.
Samuel Antaoee8fb302016-01-06 13:42:12 +0000244 StringRef getHelperName() const override { return HelperName; }
Samuel Antaobed3c462015-10-02 16:14:20 +0000245
246 static bool classof(const CGCapturedStmtInfo *Info) {
247 return CGOpenMPRegionInfo::classof(Info) &&
248 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
249 }
Samuel Antaoee8fb302016-01-06 13:42:12 +0000250
251private:
252 StringRef HelperName;
Samuel Antaobed3c462015-10-02 16:14:20 +0000253};
254
Alexey Bataevb8c425c2016-03-28 09:53:43 +0000255static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000256 llvm_unreachable("No codegen for expressions");
257}
258/// \brief API for generation of expressions captured in a innermost OpenMP
259/// region.
260class CGOpenMPInnerExprInfo : public CGOpenMPInlinedRegionInfo {
261public:
262 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
263 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
264 OMPD_unknown,
265 /*HasCancel=*/false),
266 PrivScope(CGF) {
267 // Make sure the globals captured in the provided statement are local by
268 // using the privatization logic. We assume the same variable is not
269 // captured more than once.
270 for (auto &C : CS.captures()) {
271 if (!C.capturesVariable() && !C.capturesVariableByCopy())
272 continue;
273
274 const VarDecl *VD = C.getCapturedVar();
275 if (VD->isLocalVarDeclOrParm())
276 continue;
277
278 DeclRefExpr DRE(const_cast<VarDecl *>(VD),
279 /*RefersToEnclosingVariableOrCapture=*/false,
280 VD->getType().getNonReferenceType(), VK_LValue,
281 SourceLocation());
282 PrivScope.addPrivate(VD, [&CGF, &DRE]() -> Address {
283 return CGF.EmitLValue(&DRE).getAddress();
284 });
285 }
286 (void)PrivScope.Privatize();
287 }
288
289 /// \brief Lookup the captured field decl for a variable.
290 const FieldDecl *lookup(const VarDecl *VD) const override {
291 if (auto *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
292 return FD;
293 return nullptr;
294 }
295
296 /// \brief Emit the captured statement body.
297 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
298 llvm_unreachable("No body for expressions");
299 }
300
301 /// \brief Get a variable or parameter for storing global thread id
302 /// inside OpenMP construct.
303 const VarDecl *getThreadIDVariable() const override {
304 llvm_unreachable("No thread id for expressions");
305 }
306
307 /// \brief Get the name of the capture helper.
308 StringRef getHelperName() const override {
309 llvm_unreachable("No helper name for expressions");
310 }
311
312 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
313
314private:
315 /// Private scope to capture global variables.
316 CodeGenFunction::OMPPrivateScope PrivScope;
317};
318
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000319/// \brief RAII for emitting code of OpenMP constructs.
320class InlinedOpenMPRegionRAII {
321 CodeGenFunction &CGF;
322
323public:
324 /// \brief Constructs region for combined constructs.
325 /// \param CodeGen Code generation sequence for combined directives. Includes
326 /// a list of functions used for code generation of implicitly inlined
327 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000328 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000329 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000330 : CGF(CGF) {
331 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000332 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
333 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000334 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000335
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000336 ~InlinedOpenMPRegionRAII() {
337 // Restore original CapturedStmtInfo only if we're done with code emission.
338 auto *OldCSI =
339 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
340 delete CGF.CapturedStmtInfo;
341 CGF.CapturedStmtInfo = OldCSI;
342 }
343};
344
Alexey Bataev50b3c952016-02-19 10:38:26 +0000345/// \brief Values for bit flags used in the ident_t to describe the fields.
346/// All enumeric elements are named and described in accordance with the code
347/// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
348enum OpenMPLocationFlags {
349 /// \brief Use trampoline for internal microtask.
350 OMP_IDENT_IMD = 0x01,
351 /// \brief Use c-style ident structure.
352 OMP_IDENT_KMPC = 0x02,
353 /// \brief Atomic reduction option for kmpc_reduce.
354 OMP_ATOMIC_REDUCE = 0x10,
355 /// \brief Explicit 'barrier' directive.
356 OMP_IDENT_BARRIER_EXPL = 0x20,
357 /// \brief Implicit barrier in code.
358 OMP_IDENT_BARRIER_IMPL = 0x40,
359 /// \brief Implicit barrier in 'for' directive.
360 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
361 /// \brief Implicit barrier in 'sections' directive.
362 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
363 /// \brief Implicit barrier in 'single' directive.
364 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140
365};
366
367/// \brief Describes ident structure that describes a source location.
368/// All descriptions are taken from
369/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
370/// Original structure:
371/// typedef struct ident {
372/// kmp_int32 reserved_1; /**< might be used in Fortran;
373/// see above */
374/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
375/// KMP_IDENT_KMPC identifies this union
376/// member */
377/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
378/// see above */
379///#if USE_ITT_BUILD
380/// /* but currently used for storing
381/// region-specific ITT */
382/// /* contextual information. */
383///#endif /* USE_ITT_BUILD */
384/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
385/// C++ */
386/// char const *psource; /**< String describing the source location.
387/// The string is composed of semi-colon separated
388// fields which describe the source file,
389/// the function and a pair of line numbers that
390/// delimit the construct.
391/// */
392/// } ident_t;
393enum IdentFieldIndex {
394 /// \brief might be used in Fortran
395 IdentField_Reserved_1,
396 /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
397 IdentField_Flags,
398 /// \brief Not really used in Fortran any more
399 IdentField_Reserved_2,
400 /// \brief Source[4] in Fortran, do not use for C++
401 IdentField_Reserved_3,
402 /// \brief String describing the source location. The string is composed of
403 /// semi-colon separated fields which describe the source file, the function
404 /// and a pair of line numbers that delimit the construct.
405 IdentField_PSource
406};
407
408/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
409/// the enum sched_type in kmp.h).
410enum OpenMPSchedType {
411 /// \brief Lower bound for default (unordered) versions.
412 OMP_sch_lower = 32,
413 OMP_sch_static_chunked = 33,
414 OMP_sch_static = 34,
415 OMP_sch_dynamic_chunked = 35,
416 OMP_sch_guided_chunked = 36,
417 OMP_sch_runtime = 37,
418 OMP_sch_auto = 38,
419 /// \brief Lower bound for 'ordered' versions.
420 OMP_ord_lower = 64,
421 OMP_ord_static_chunked = 65,
422 OMP_ord_static = 66,
423 OMP_ord_dynamic_chunked = 67,
424 OMP_ord_guided_chunked = 68,
425 OMP_ord_runtime = 69,
426 OMP_ord_auto = 70,
427 OMP_sch_default = OMP_sch_static,
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000428 /// \brief dist_schedule types
429 OMP_dist_sch_static_chunked = 91,
430 OMP_dist_sch_static = 92,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000431};
432
433enum OpenMPRTLFunction {
434 /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
435 /// kmpc_micro microtask, ...);
436 OMPRTL__kmpc_fork_call,
437 /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc,
438 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
439 OMPRTL__kmpc_threadprivate_cached,
440 /// \brief Call to void __kmpc_threadprivate_register( ident_t *,
441 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
442 OMPRTL__kmpc_threadprivate_register,
443 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
444 OMPRTL__kmpc_global_thread_num,
445 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
446 // kmp_critical_name *crit);
447 OMPRTL__kmpc_critical,
448 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
449 // global_tid, kmp_critical_name *crit, uintptr_t hint);
450 OMPRTL__kmpc_critical_with_hint,
451 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
452 // kmp_critical_name *crit);
453 OMPRTL__kmpc_end_critical,
454 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
455 // global_tid);
456 OMPRTL__kmpc_cancel_barrier,
457 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
458 OMPRTL__kmpc_barrier,
459 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
460 OMPRTL__kmpc_for_static_fini,
461 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
462 // global_tid);
463 OMPRTL__kmpc_serialized_parallel,
464 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
465 // global_tid);
466 OMPRTL__kmpc_end_serialized_parallel,
467 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
468 // kmp_int32 num_threads);
469 OMPRTL__kmpc_push_num_threads,
470 // Call to void __kmpc_flush(ident_t *loc);
471 OMPRTL__kmpc_flush,
472 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
473 OMPRTL__kmpc_master,
474 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
475 OMPRTL__kmpc_end_master,
476 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
477 // int end_part);
478 OMPRTL__kmpc_omp_taskyield,
479 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
480 OMPRTL__kmpc_single,
481 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
482 OMPRTL__kmpc_end_single,
483 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
484 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
485 // kmp_routine_entry_t *task_entry);
486 OMPRTL__kmpc_omp_task_alloc,
487 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
488 // new_task);
489 OMPRTL__kmpc_omp_task,
490 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
491 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
492 // kmp_int32 didit);
493 OMPRTL__kmpc_copyprivate,
494 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
495 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
496 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
497 OMPRTL__kmpc_reduce,
498 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
499 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
500 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
501 // *lck);
502 OMPRTL__kmpc_reduce_nowait,
503 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
504 // kmp_critical_name *lck);
505 OMPRTL__kmpc_end_reduce,
506 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
507 // kmp_critical_name *lck);
508 OMPRTL__kmpc_end_reduce_nowait,
509 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
510 // kmp_task_t * new_task);
511 OMPRTL__kmpc_omp_task_begin_if0,
512 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
513 // kmp_task_t * new_task);
514 OMPRTL__kmpc_omp_task_complete_if0,
515 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
516 OMPRTL__kmpc_ordered,
517 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
518 OMPRTL__kmpc_end_ordered,
519 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
520 // global_tid);
521 OMPRTL__kmpc_omp_taskwait,
522 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
523 OMPRTL__kmpc_taskgroup,
524 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
525 OMPRTL__kmpc_end_taskgroup,
526 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
527 // int proc_bind);
528 OMPRTL__kmpc_push_proc_bind,
529 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
530 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
531 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
532 OMPRTL__kmpc_omp_task_with_deps,
533 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
534 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
535 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
536 OMPRTL__kmpc_omp_wait_deps,
537 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
538 // global_tid, kmp_int32 cncl_kind);
539 OMPRTL__kmpc_cancellationpoint,
540 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
541 // kmp_int32 cncl_kind);
542 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000543 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
544 // kmp_int32 num_teams, kmp_int32 thread_limit);
545 OMPRTL__kmpc_push_num_teams,
546 /// \brief Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc,
547 /// kmpc_micro microtask, ...);
548 OMPRTL__kmpc_fork_teams,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000549
550 //
551 // Offloading related calls
552 //
553 // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
554 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
555 // *arg_types);
556 OMPRTL__tgt_target,
Samuel Antaob68e2db2016-03-03 16:20:23 +0000557 // Call to int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
558 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
559 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
560 OMPRTL__tgt_target_teams,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000561 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
562 OMPRTL__tgt_register_lib,
563 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
564 OMPRTL__tgt_unregister_lib,
565};
566
Alexey Bataevb8c425c2016-03-28 09:53:43 +0000567/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
568/// region.
569class CleanupTy final : public EHScopeStack::Cleanup {
570 PrePostActionTy *Action;
571
572public:
573 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
574 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
575 if (!CGF.HaveInsertPoint())
576 return;
577 Action->Exit(CGF);
578 }
579};
580
Hans Wennborg7eb54642015-09-10 17:07:54 +0000581} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000582
Alexey Bataevb8c425c2016-03-28 09:53:43 +0000583void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
584 CodeGenFunction::RunCleanupsScope Scope(CGF);
585 if (PrePostAction) {
586 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
587 Callback(CodeGen, CGF, *PrePostAction);
588 } else {
589 PrePostActionTy Action;
590 Callback(CodeGen, CGF, Action);
591 }
592}
593
Alexey Bataev18095712014-10-10 12:19:54 +0000594LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +0000595 return CGF.EmitLoadOfPointerLValue(
596 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
597 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +0000598}
599
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000600void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000601 if (!CGF.HaveInsertPoint())
602 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000603 // 1.2.2 OpenMP Language Terminology
604 // Structured block - An executable statement with a single entry at the
605 // top and a single exit at the bottom.
606 // The point of exit cannot be a branch out of the structured block.
607 // longjmp() and throw() must not violate the entry/exit criteria.
608 CGF.EHStack.pushTerminate();
Alexey Bataevb8c425c2016-03-28 09:53:43 +0000609 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000610 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000611}
612
Alexey Bataev62b63b12015-03-10 07:28:44 +0000613LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
614 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000615 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
616 getThreadIDVariable()->getType(),
617 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000618}
619
Alexey Bataev9959db52014-05-06 10:08:46 +0000620CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000621 : CGM(CGM), OffloadEntriesInfoManager(CGM) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000622 IdentTy = llvm::StructType::create(
623 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
624 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000625 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000626 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
Alexey Bataev23b69422014-06-18 07:08:49 +0000627 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
628 llvm::PointerType::getUnqual(CGM.Int32Ty)};
Alexey Bataev9959db52014-05-06 10:08:46 +0000629 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000630 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +0000631
632 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +0000633}
634
Alexey Bataev91797552015-03-18 04:13:55 +0000635void CGOpenMPRuntime::clear() {
636 InternalVars.clear();
637}
638
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000639static llvm::Function *
640emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
641 const Expr *CombinerInitializer, const VarDecl *In,
642 const VarDecl *Out, bool IsCombiner) {
643 // void .omp_combiner.(Ty *in, Ty *out);
644 auto &C = CGM.getContext();
645 QualType PtrTy = C.getPointerType(Ty).withRestrict();
646 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000647 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
648 /*Id=*/nullptr, PtrTy);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000649 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
650 /*Id=*/nullptr, PtrTy);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000651 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000652 Args.push_back(&OmpInParm);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000653 auto &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +0000654 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000655 auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
656 auto *Fn = llvm::Function::Create(
657 FnTy, llvm::GlobalValue::InternalLinkage,
658 IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
659 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000660 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000661 CodeGenFunction CGF(CGM);
662 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
663 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
664 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args);
665 CodeGenFunction::OMPPrivateScope Scope(CGF);
666 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
667 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() -> Address {
668 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
669 .getAddress();
670 });
671 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
672 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() -> Address {
673 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
674 .getAddress();
675 });
676 (void)Scope.Privatize();
677 CGF.EmitIgnoredExpr(CombinerInitializer);
678 Scope.ForceCleanup();
679 CGF.FinishFunction();
680 return Fn;
681}
682
683void CGOpenMPRuntime::emitUserDefinedReduction(
684 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
685 if (UDRMap.count(D) > 0)
686 return;
687 auto &C = CGM.getContext();
688 if (!In || !Out) {
689 In = &C.Idents.get("omp_in");
690 Out = &C.Idents.get("omp_out");
691 }
692 llvm::Function *Combiner = emitCombinerOrInitializer(
693 CGM, D->getType(), D->getCombiner(), cast<VarDecl>(D->lookup(In).front()),
694 cast<VarDecl>(D->lookup(Out).front()),
695 /*IsCombiner=*/true);
696 llvm::Function *Initializer = nullptr;
697 if (auto *Init = D->getInitializer()) {
698 if (!Priv || !Orig) {
699 Priv = &C.Idents.get("omp_priv");
700 Orig = &C.Idents.get("omp_orig");
701 }
702 Initializer = emitCombinerOrInitializer(
703 CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()),
704 cast<VarDecl>(D->lookup(Priv).front()),
705 /*IsCombiner=*/false);
706 }
707 UDRMap.insert(std::make_pair(D, std::make_pair(Combiner, Initializer)));
708 if (CGF) {
709 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
710 Decls.second.push_back(D);
711 }
712}
713
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000714std::pair<llvm::Function *, llvm::Function *>
715CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
716 auto I = UDRMap.find(D);
717 if (I != UDRMap.end())
718 return I->second;
719 emitUserDefinedReduction(/*CGF=*/nullptr, D);
720 return UDRMap.lookup(D);
721}
722
John McCall7f416cc2015-09-08 08:05:57 +0000723// Layout information for ident_t.
724static CharUnits getIdentAlign(CodeGenModule &CGM) {
725 return CGM.getPointerAlign();
726}
727static CharUnits getIdentSize(CodeGenModule &CGM) {
728 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign()));
729 return CharUnits::fromQuantity(16) + CGM.getPointerSize();
730}
Alexey Bataev50b3c952016-02-19 10:38:26 +0000731static CharUnits getOffsetOfIdentField(IdentFieldIndex Field) {
John McCall7f416cc2015-09-08 08:05:57 +0000732 // All the fields except the last are i32, so this works beautifully.
733 return unsigned(Field) * CharUnits::fromQuantity(4);
734}
735static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000736 IdentFieldIndex Field,
John McCall7f416cc2015-09-08 08:05:57 +0000737 const llvm::Twine &Name = "") {
738 auto Offset = getOffsetOfIdentField(Field);
739 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
740}
741
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000742llvm::Value *CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000743 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
744 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000745 assert(ThreadIDVar->getType()->isPointerType() &&
746 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +0000747 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
748 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +0000749 bool HasCancel = false;
750 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
751 HasCancel = OPD->hasCancel();
752 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
753 HasCancel = OPSD->hasCancel();
754 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
755 HasCancel = OPFD->hasCancel();
756 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
757 HasCancel);
Alexey Bataevd157d472015-06-24 03:35:38 +0000758 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000759 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +0000760}
761
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000762llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
763 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
764 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000765 assert(!ThreadIDVar->getType()->isPointerType() &&
766 "thread id variable must be of type kmp_int32 for tasks");
767 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
768 CodeGenFunction CGF(CGM, true);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000769 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000770 InnermostKind,
771 cast<OMPTaskDirective>(D).hasCancel());
Alexey Bataevd157d472015-06-24 03:35:38 +0000772 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000773 return CGF.GenerateCapturedStmtFunction(*CS);
774}
775
Alexey Bataev50b3c952016-02-19 10:38:26 +0000776Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
John McCall7f416cc2015-09-08 08:05:57 +0000777 CharUnits Align = getIdentAlign(CGM);
Alexey Bataev15007ba2014-05-07 06:18:01 +0000778 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000779 if (!Entry) {
780 if (!DefaultOpenMPPSource) {
781 // Initialize default location for psource field of ident_t structure of
782 // all ident_t objects. Format is ";file;function;line;column;;".
783 // Taken from
784 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
785 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +0000786 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000787 DefaultOpenMPPSource =
788 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
789 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000790 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
791 CGM.getModule(), IdentTy, /*isConstant*/ true,
792 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000793 DefaultOpenMPLocation->setUnnamedAddr(true);
John McCall7f416cc2015-09-08 08:05:57 +0000794 DefaultOpenMPLocation->setAlignment(Align.getQuantity());
Alexey Bataev9959db52014-05-06 10:08:46 +0000795
796 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000797 llvm::Constant *Values[] = {Zero,
798 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
799 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000800 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
801 DefaultOpenMPLocation->setInitializer(Init);
John McCall7f416cc2015-09-08 08:05:57 +0000802 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000803 }
John McCall7f416cc2015-09-08 08:05:57 +0000804 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +0000805}
806
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000807llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
808 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000809 unsigned Flags) {
810 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +0000811 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +0000812 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +0000813 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +0000814 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000815
816 assert(CGF.CurFn && "No function in current CodeGenFunction.");
817
John McCall7f416cc2015-09-08 08:05:57 +0000818 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000819 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
820 if (I != OpenMPLocThreadIDMap.end())
John McCall7f416cc2015-09-08 08:05:57 +0000821 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
822
Alexander Musmanc6388682014-12-15 07:07:06 +0000823 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
824 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +0000825 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000826 // Generate "ident_t .kmpc_loc.addr;"
John McCall7f416cc2015-09-08 08:05:57 +0000827 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
828 ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +0000829 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +0000830 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000831 LocValue = AI;
832
833 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
834 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000835 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
John McCall7f416cc2015-09-08 08:05:57 +0000836 CGM.getSize(getIdentSize(CGF.CGM)));
Alexey Bataev9959db52014-05-06 10:08:46 +0000837 }
838
839 // char **psource = &.kmpc_loc_<flags>.addr.psource;
John McCall7f416cc2015-09-08 08:05:57 +0000840 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000841
Alexey Bataevf002aca2014-05-30 05:48:40 +0000842 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
843 if (OMPDebugLoc == nullptr) {
844 SmallString<128> Buffer2;
845 llvm::raw_svector_ostream OS2(Buffer2);
846 // Build debug location
847 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
848 OS2 << ";" << PLoc.getFilename() << ";";
849 if (const FunctionDecl *FD =
850 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
851 OS2 << FD->getQualifiedNameAsString();
852 }
853 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
854 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
855 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000856 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000857 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000858 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
859
John McCall7f416cc2015-09-08 08:05:57 +0000860 // Our callers always pass this to a runtime function, so for
861 // convenience, go ahead and return a naked pointer.
862 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000863}
864
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000865llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
866 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000867 assert(CGF.CurFn && "No function in current CodeGenFunction.");
868
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000869 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000870 // Check whether we've already cached a load of the thread id in this
871 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000872 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000873 if (I != OpenMPLocThreadIDMap.end()) {
874 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000875 if (ThreadID != nullptr)
876 return ThreadID;
877 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +0000878 if (auto *OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000879 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000880 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000881 // Check if this an outlined function with thread id passed as argument.
882 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000883 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
884 // If value loaded in entry block, cache it and use it everywhere in
885 // function.
886 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
887 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
888 Elem.second.ThreadID = ThreadID;
889 }
890 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000891 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000892 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000893
894 // This is not an outlined function region - need to call __kmpc_int32
895 // kmpc_global_thread_num(ident_t *loc).
896 // Generate thread id value and cache this value for use across the
897 // function.
898 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
899 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
900 ThreadID =
901 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
902 emitUpdateLocation(CGF, Loc));
903 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
904 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000905 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000906}
907
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000908void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000909 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000910 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
911 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000912 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
913 for(auto *D : FunctionUDRMap[CGF.CurFn]) {
914 UDRMap.erase(D);
915 }
916 FunctionUDRMap.erase(CGF.CurFn);
917 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000918}
919
920llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
921 return llvm::PointerType::getUnqual(IdentTy);
922}
923
924llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
925 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
926}
927
928llvm::Constant *
Alexey Bataev50b3c952016-02-19 10:38:26 +0000929CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000930 llvm::Constant *RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +0000931 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000932 case OMPRTL__kmpc_fork_call: {
933 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
934 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +0000935 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
936 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000937 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000938 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +0000939 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
940 break;
941 }
942 case OMPRTL__kmpc_global_thread_num: {
943 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +0000944 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000945 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000946 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +0000947 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
948 break;
949 }
Alexey Bataev97720002014-11-11 04:05:39 +0000950 case OMPRTL__kmpc_threadprivate_cached: {
951 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
952 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
953 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
954 CGM.VoidPtrTy, CGM.SizeTy,
955 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
956 llvm::FunctionType *FnTy =
957 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
958 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
959 break;
960 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000961 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000962 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
963 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000964 llvm::Type *TypeParams[] = {
965 getIdentTyPointerTy(), CGM.Int32Ty,
966 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
967 llvm::FunctionType *FnTy =
968 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
969 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
970 break;
971 }
Alexey Bataevfc57d162015-12-15 10:55:09 +0000972 case OMPRTL__kmpc_critical_with_hint: {
973 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
974 // kmp_critical_name *crit, uintptr_t hint);
975 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
976 llvm::PointerType::getUnqual(KmpCriticalNameTy),
977 CGM.IntPtrTy};
978 llvm::FunctionType *FnTy =
979 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
980 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
981 break;
982 }
Alexey Bataev97720002014-11-11 04:05:39 +0000983 case OMPRTL__kmpc_threadprivate_register: {
984 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
985 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
986 // typedef void *(*kmpc_ctor)(void *);
987 auto KmpcCtorTy =
988 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
989 /*isVarArg*/ false)->getPointerTo();
990 // typedef void *(*kmpc_cctor)(void *, void *);
991 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
992 auto KmpcCopyCtorTy =
993 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
994 /*isVarArg*/ false)->getPointerTo();
995 // typedef void (*kmpc_dtor)(void *);
996 auto KmpcDtorTy =
997 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
998 ->getPointerTo();
999 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1000 KmpcCopyCtorTy, KmpcDtorTy};
1001 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
1002 /*isVarArg*/ false);
1003 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1004 break;
1005 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001006 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001007 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1008 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001009 llvm::Type *TypeParams[] = {
1010 getIdentTyPointerTy(), CGM.Int32Ty,
1011 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1012 llvm::FunctionType *FnTy =
1013 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1014 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1015 break;
1016 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001017 case OMPRTL__kmpc_cancel_barrier: {
1018 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1019 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001020 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1021 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001022 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1023 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001024 break;
1025 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001026 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001027 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001028 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1029 llvm::FunctionType *FnTy =
1030 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1031 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1032 break;
1033 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001034 case OMPRTL__kmpc_for_static_fini: {
1035 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1036 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1037 llvm::FunctionType *FnTy =
1038 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1039 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1040 break;
1041 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001042 case OMPRTL__kmpc_push_num_threads: {
1043 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1044 // kmp_int32 num_threads)
1045 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1046 CGM.Int32Ty};
1047 llvm::FunctionType *FnTy =
1048 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1049 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1050 break;
1051 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001052 case OMPRTL__kmpc_serialized_parallel: {
1053 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1054 // global_tid);
1055 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1056 llvm::FunctionType *FnTy =
1057 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1058 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1059 break;
1060 }
1061 case OMPRTL__kmpc_end_serialized_parallel: {
1062 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1063 // global_tid);
1064 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1065 llvm::FunctionType *FnTy =
1066 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1067 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1068 break;
1069 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001070 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001071 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001072 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
1073 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001074 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001075 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1076 break;
1077 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001078 case OMPRTL__kmpc_master: {
1079 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1080 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1081 llvm::FunctionType *FnTy =
1082 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1083 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1084 break;
1085 }
1086 case OMPRTL__kmpc_end_master: {
1087 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1088 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1089 llvm::FunctionType *FnTy =
1090 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1091 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1092 break;
1093 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001094 case OMPRTL__kmpc_omp_taskyield: {
1095 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1096 // int end_part);
1097 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1098 llvm::FunctionType *FnTy =
1099 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1100 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1101 break;
1102 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001103 case OMPRTL__kmpc_single: {
1104 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1105 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1106 llvm::FunctionType *FnTy =
1107 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1108 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1109 break;
1110 }
1111 case OMPRTL__kmpc_end_single: {
1112 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1113 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1114 llvm::FunctionType *FnTy =
1115 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1116 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1117 break;
1118 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001119 case OMPRTL__kmpc_omp_task_alloc: {
1120 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1121 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1122 // kmp_routine_entry_t *task_entry);
1123 assert(KmpRoutineEntryPtrTy != nullptr &&
1124 "Type kmp_routine_entry_t must be created.");
1125 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1126 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1127 // Return void * and then cast to particular kmp_task_t type.
1128 llvm::FunctionType *FnTy =
1129 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1130 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1131 break;
1132 }
1133 case OMPRTL__kmpc_omp_task: {
1134 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1135 // *new_task);
1136 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1137 CGM.VoidPtrTy};
1138 llvm::FunctionType *FnTy =
1139 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1140 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
1141 break;
1142 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001143 case OMPRTL__kmpc_copyprivate: {
1144 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00001145 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001146 // kmp_int32 didit);
1147 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1148 auto *CpyFnTy =
1149 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001150 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001151 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
1152 CGM.Int32Ty};
1153 llvm::FunctionType *FnTy =
1154 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1155 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
1156 break;
1157 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001158 case OMPRTL__kmpc_reduce: {
1159 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
1160 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
1161 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
1162 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1163 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1164 /*isVarArg=*/false);
1165 llvm::Type *TypeParams[] = {
1166 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1167 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1168 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1169 llvm::FunctionType *FnTy =
1170 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1171 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
1172 break;
1173 }
1174 case OMPRTL__kmpc_reduce_nowait: {
1175 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
1176 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
1177 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
1178 // *lck);
1179 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1180 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1181 /*isVarArg=*/false);
1182 llvm::Type *TypeParams[] = {
1183 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1184 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1185 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1186 llvm::FunctionType *FnTy =
1187 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1188 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
1189 break;
1190 }
1191 case OMPRTL__kmpc_end_reduce: {
1192 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
1193 // kmp_critical_name *lck);
1194 llvm::Type *TypeParams[] = {
1195 getIdentTyPointerTy(), CGM.Int32Ty,
1196 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1197 llvm::FunctionType *FnTy =
1198 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1199 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
1200 break;
1201 }
1202 case OMPRTL__kmpc_end_reduce_nowait: {
1203 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
1204 // kmp_critical_name *lck);
1205 llvm::Type *TypeParams[] = {
1206 getIdentTyPointerTy(), CGM.Int32Ty,
1207 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1208 llvm::FunctionType *FnTy =
1209 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1210 RTLFn =
1211 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
1212 break;
1213 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001214 case OMPRTL__kmpc_omp_task_begin_if0: {
1215 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1216 // *new_task);
1217 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1218 CGM.VoidPtrTy};
1219 llvm::FunctionType *FnTy =
1220 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1221 RTLFn =
1222 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
1223 break;
1224 }
1225 case OMPRTL__kmpc_omp_task_complete_if0: {
1226 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1227 // *new_task);
1228 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1229 CGM.VoidPtrTy};
1230 llvm::FunctionType *FnTy =
1231 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1232 RTLFn = CGM.CreateRuntimeFunction(FnTy,
1233 /*Name=*/"__kmpc_omp_task_complete_if0");
1234 break;
1235 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001236 case OMPRTL__kmpc_ordered: {
1237 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
1238 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1239 llvm::FunctionType *FnTy =
1240 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1241 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
1242 break;
1243 }
1244 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001245 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001246 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1247 llvm::FunctionType *FnTy =
1248 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1249 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
1250 break;
1251 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00001252 case OMPRTL__kmpc_omp_taskwait: {
1253 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
1254 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1255 llvm::FunctionType *FnTy =
1256 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1257 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
1258 break;
1259 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001260 case OMPRTL__kmpc_taskgroup: {
1261 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
1262 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1263 llvm::FunctionType *FnTy =
1264 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1265 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
1266 break;
1267 }
1268 case OMPRTL__kmpc_end_taskgroup: {
1269 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
1270 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1271 llvm::FunctionType *FnTy =
1272 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1273 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
1274 break;
1275 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00001276 case OMPRTL__kmpc_push_proc_bind: {
1277 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
1278 // int proc_bind)
1279 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1280 llvm::FunctionType *FnTy =
1281 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1282 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
1283 break;
1284 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00001285 case OMPRTL__kmpc_omp_task_with_deps: {
1286 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
1287 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
1288 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
1289 llvm::Type *TypeParams[] = {
1290 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
1291 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
1292 llvm::FunctionType *FnTy =
1293 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1294 RTLFn =
1295 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
1296 break;
1297 }
1298 case OMPRTL__kmpc_omp_wait_deps: {
1299 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
1300 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
1301 // kmp_depend_info_t *noalias_dep_list);
1302 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1303 CGM.Int32Ty, CGM.VoidPtrTy,
1304 CGM.Int32Ty, CGM.VoidPtrTy};
1305 llvm::FunctionType *FnTy =
1306 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1307 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
1308 break;
1309 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00001310 case OMPRTL__kmpc_cancellationpoint: {
1311 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
1312 // global_tid, kmp_int32 cncl_kind)
1313 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1314 llvm::FunctionType *FnTy =
1315 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1316 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
1317 break;
1318 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001319 case OMPRTL__kmpc_cancel: {
1320 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
1321 // kmp_int32 cncl_kind)
1322 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1323 llvm::FunctionType *FnTy =
1324 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1325 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
1326 break;
1327 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00001328 case OMPRTL__kmpc_push_num_teams: {
1329 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
1330 // kmp_int32 num_teams, kmp_int32 num_threads)
1331 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1332 CGM.Int32Ty};
1333 llvm::FunctionType *FnTy =
1334 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1335 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
1336 break;
1337 }
1338 case OMPRTL__kmpc_fork_teams: {
1339 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
1340 // microtask, ...);
1341 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1342 getKmpc_MicroPointerTy()};
1343 llvm::FunctionType *FnTy =
1344 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
1345 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
1346 break;
1347 }
Samuel Antaobed3c462015-10-02 16:14:20 +00001348 case OMPRTL__tgt_target: {
1349 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
1350 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
1351 // *arg_types);
1352 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1353 CGM.VoidPtrTy,
1354 CGM.Int32Ty,
1355 CGM.VoidPtrPtrTy,
1356 CGM.VoidPtrPtrTy,
1357 CGM.SizeTy->getPointerTo(),
1358 CGM.Int32Ty->getPointerTo()};
1359 llvm::FunctionType *FnTy =
1360 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1361 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
1362 break;
1363 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00001364 case OMPRTL__tgt_target_teams: {
1365 // Build int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
1366 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
1367 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
1368 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1369 CGM.VoidPtrTy,
1370 CGM.Int32Ty,
1371 CGM.VoidPtrPtrTy,
1372 CGM.VoidPtrPtrTy,
1373 CGM.SizeTy->getPointerTo(),
1374 CGM.Int32Ty->getPointerTo(),
1375 CGM.Int32Ty,
1376 CGM.Int32Ty};
1377 llvm::FunctionType *FnTy =
1378 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1379 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
1380 break;
1381 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00001382 case OMPRTL__tgt_register_lib: {
1383 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
1384 QualType ParamTy =
1385 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1386 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1387 llvm::FunctionType *FnTy =
1388 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1389 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
1390 break;
1391 }
1392 case OMPRTL__tgt_unregister_lib: {
1393 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
1394 QualType ParamTy =
1395 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1396 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1397 llvm::FunctionType *FnTy =
1398 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1399 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
1400 break;
1401 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001402 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00001403 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00001404 return RTLFn;
1405}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001406
Alexander Musman21212e42015-03-13 10:38:23 +00001407llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
1408 bool IVSigned) {
1409 assert((IVSize == 32 || IVSize == 64) &&
1410 "IV size is not compatible with the omp runtime");
1411 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
1412 : "__kmpc_for_static_init_4u")
1413 : (IVSigned ? "__kmpc_for_static_init_8"
1414 : "__kmpc_for_static_init_8u");
1415 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1416 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1417 llvm::Type *TypeParams[] = {
1418 getIdentTyPointerTy(), // loc
1419 CGM.Int32Ty, // tid
1420 CGM.Int32Ty, // schedtype
1421 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1422 PtrTy, // p_lower
1423 PtrTy, // p_upper
1424 PtrTy, // p_stride
1425 ITy, // incr
1426 ITy // chunk
1427 };
1428 llvm::FunctionType *FnTy =
1429 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1430 return CGM.CreateRuntimeFunction(FnTy, Name);
1431}
1432
Alexander Musman92bdaab2015-03-12 13:37:50 +00001433llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
1434 bool IVSigned) {
1435 assert((IVSize == 32 || IVSize == 64) &&
1436 "IV size is not compatible with the omp runtime");
1437 auto Name =
1438 IVSize == 32
1439 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
1440 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
1441 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1442 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
1443 CGM.Int32Ty, // tid
1444 CGM.Int32Ty, // schedtype
1445 ITy, // lower
1446 ITy, // upper
1447 ITy, // stride
1448 ITy // chunk
1449 };
1450 llvm::FunctionType *FnTy =
1451 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1452 return CGM.CreateRuntimeFunction(FnTy, Name);
1453}
1454
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001455llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
1456 bool IVSigned) {
1457 assert((IVSize == 32 || IVSize == 64) &&
1458 "IV size is not compatible with the omp runtime");
1459 auto Name =
1460 IVSize == 32
1461 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1462 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1463 llvm::Type *TypeParams[] = {
1464 getIdentTyPointerTy(), // loc
1465 CGM.Int32Ty, // tid
1466 };
1467 llvm::FunctionType *FnTy =
1468 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1469 return CGM.CreateRuntimeFunction(FnTy, Name);
1470}
1471
Alexander Musman92bdaab2015-03-12 13:37:50 +00001472llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
1473 bool IVSigned) {
1474 assert((IVSize == 32 || IVSize == 64) &&
1475 "IV size is not compatible with the omp runtime");
1476 auto Name =
1477 IVSize == 32
1478 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1479 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1480 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1481 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1482 llvm::Type *TypeParams[] = {
1483 getIdentTyPointerTy(), // loc
1484 CGM.Int32Ty, // tid
1485 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1486 PtrTy, // p_lower
1487 PtrTy, // p_upper
1488 PtrTy // p_stride
1489 };
1490 llvm::FunctionType *FnTy =
1491 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1492 return CGM.CreateRuntimeFunction(FnTy, Name);
1493}
1494
Alexey Bataev97720002014-11-11 04:05:39 +00001495llvm::Constant *
1496CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001497 assert(!CGM.getLangOpts().OpenMPUseTLS ||
1498 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00001499 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001500 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001501 Twine(CGM.getMangledName(VD)) + ".cache.");
1502}
1503
John McCall7f416cc2015-09-08 08:05:57 +00001504Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1505 const VarDecl *VD,
1506 Address VDAddr,
1507 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001508 if (CGM.getLangOpts().OpenMPUseTLS &&
1509 CGM.getContext().getTargetInfo().isTLSSupported())
1510 return VDAddr;
1511
John McCall7f416cc2015-09-08 08:05:57 +00001512 auto VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001513 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001514 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1515 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001516 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1517 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00001518 return Address(CGF.EmitRuntimeCall(
1519 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
1520 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00001521}
1522
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001523void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00001524 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00001525 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1526 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1527 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001528 auto OMPLoc = emitUpdateLocation(CGF, Loc);
1529 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00001530 OMPLoc);
1531 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1532 // to register constructor/destructor for variable.
1533 llvm::Value *Args[] = {OMPLoc,
John McCall7f416cc2015-09-08 08:05:57 +00001534 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1535 CGM.VoidPtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001536 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001537 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001538 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001539}
1540
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001541llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00001542 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00001543 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001544 if (CGM.getLangOpts().OpenMPUseTLS &&
1545 CGM.getContext().getTargetInfo().isTLSSupported())
1546 return nullptr;
1547
Alexey Bataev97720002014-11-11 04:05:39 +00001548 VD = VD->getDefinition(CGM.getContext());
1549 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
1550 ThreadPrivateWithDefinition.insert(VD);
1551 QualType ASTTy = VD->getType();
1552
1553 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1554 auto Init = VD->getAnyInitializer();
1555 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1556 // Generate function that re-emits the declaration's initializer into the
1557 // threadprivate copy of the variable VD
1558 CodeGenFunction CtorCGF(CGM);
1559 FunctionArgList Args;
1560 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1561 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1562 Args.push_back(&Dst);
1563
John McCallc56a8b32016-03-11 04:30:31 +00001564 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1565 CGM.getContext().VoidPtrTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001566 auto FTy = CGM.getTypes().GetFunctionType(FI);
1567 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001568 FTy, ".__kmpc_global_ctor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001569 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1570 Args, SourceLocation());
1571 auto ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001572 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001573 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00001574 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1575 Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
1576 CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00001577 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1578 /*IsInitializer=*/true);
1579 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001580 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001581 CGM.getContext().VoidPtrTy, Dst.getLocation());
1582 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1583 CtorCGF.FinishFunction();
1584 Ctor = Fn;
1585 }
1586 if (VD->getType().isDestructedType() != QualType::DK_none) {
1587 // Generate function that emits destructor call for the threadprivate copy
1588 // of the variable VD
1589 CodeGenFunction DtorCGF(CGM);
1590 FunctionArgList Args;
1591 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1592 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1593 Args.push_back(&Dst);
1594
John McCallc56a8b32016-03-11 04:30:31 +00001595 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1596 CGM.getContext().VoidTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001597 auto FTy = CGM.getTypes().GetFunctionType(FI);
1598 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001599 FTy, ".__kmpc_global_dtor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001600 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1601 SourceLocation());
1602 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1603 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00001604 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1605 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001606 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1607 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1608 DtorCGF.FinishFunction();
1609 Dtor = Fn;
1610 }
1611 // Do not emit init function if it is not required.
1612 if (!Ctor && !Dtor)
1613 return nullptr;
1614
1615 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1616 auto CopyCtorTy =
1617 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1618 /*isVarArg=*/false)->getPointerTo();
1619 // Copying constructor for the threadprivate variable.
1620 // Must be NULL - reserved by runtime, but currently it requires that this
1621 // parameter is always NULL. Otherwise it fires assertion.
1622 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1623 if (Ctor == nullptr) {
1624 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1625 /*isVarArg=*/false)->getPointerTo();
1626 Ctor = llvm::Constant::getNullValue(CtorTy);
1627 }
1628 if (Dtor == nullptr) {
1629 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1630 /*isVarArg=*/false)->getPointerTo();
1631 Dtor = llvm::Constant::getNullValue(DtorTy);
1632 }
1633 if (!CGF) {
1634 auto InitFunctionTy =
1635 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1636 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001637 InitFunctionTy, ".__omp_threadprivate_init_.",
1638 CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00001639 CodeGenFunction InitCGF(CGM);
1640 FunctionArgList ArgList;
1641 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1642 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1643 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001644 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001645 InitCGF.FinishFunction();
1646 return InitFunction;
1647 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001648 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001649 }
1650 return nullptr;
1651}
1652
Alexey Bataev1d677132015-04-22 13:57:31 +00001653/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1654/// function. Here is the logic:
1655/// if (Cond) {
1656/// ThenGen();
1657/// } else {
1658/// ElseGen();
1659/// }
1660static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1661 const RegionCodeGenTy &ThenGen,
1662 const RegionCodeGenTy &ElseGen) {
1663 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1664
1665 // If the condition constant folds and can be elided, try to avoid emitting
1666 // the condition and the dead arm of the if/else.
1667 bool CondConstant;
1668 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001669 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00001670 ThenGen(CGF);
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001671 else
Alexey Bataev1d677132015-04-22 13:57:31 +00001672 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001673 return;
1674 }
1675
1676 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1677 // emit the conditional branch.
1678 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1679 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1680 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1681 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1682
1683 // Emit the 'then' code.
1684 CGF.EmitBlock(ThenBlock);
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001685 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001686 CGF.EmitBranch(ContBlock);
1687 // Emit the 'else' code if present.
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001688 // There is no need to emit line number for unconditional branch.
1689 (void)ApplyDebugLocation::CreateEmpty(CGF);
1690 CGF.EmitBlock(ElseBlock);
1691 ElseGen(CGF);
1692 // There is no need to emit line number for unconditional branch.
1693 (void)ApplyDebugLocation::CreateEmpty(CGF);
1694 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00001695 // Emit the continuation block for code after the if.
1696 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001697}
1698
Alexey Bataev1d677132015-04-22 13:57:31 +00001699void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1700 llvm::Value *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001701 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00001702 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001703 if (!CGF.HaveInsertPoint())
1704 return;
Alexey Bataev1d677132015-04-22 13:57:31 +00001705 auto *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001706 RegionCodeGenTy ThenGen = [this, OutlinedFn, CapturedVars,
1707 RTLoc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001708 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
1709 llvm::Value *Args[] = {
1710 RTLoc,
1711 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
1712 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
1713 llvm::SmallVector<llvm::Value *, 16> RealArgs;
1714 RealArgs.append(std::begin(Args), std::end(Args));
1715 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1716
1717 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
1718 CGF.EmitRuntimeCall(RTLFn, RealArgs);
1719 };
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001720 RegionCodeGenTy ElseGen = [this, OutlinedFn, CapturedVars, RTLoc,
1721 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev1d677132015-04-22 13:57:31 +00001722 auto ThreadID = getThreadID(CGF, Loc);
1723 // Build calls:
1724 // __kmpc_serialized_parallel(&Loc, GTid);
1725 llvm::Value *Args[] = {RTLoc, ThreadID};
1726 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel),
1727 Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001728
Alexey Bataev1d677132015-04-22 13:57:31 +00001729 // OutlinedFn(&GTid, &zero, CapturedStruct);
1730 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00001731 Address ZeroAddr =
1732 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
1733 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00001734 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00001735 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
1736 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
1737 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1738 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev1d677132015-04-22 13:57:31 +00001739 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001740
Alexey Bataev1d677132015-04-22 13:57:31 +00001741 // __kmpc_end_serialized_parallel(&Loc, GTid);
1742 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID};
1743 CGF.EmitRuntimeCall(
1744 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs);
1745 };
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001746 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00001747 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001748 else
Alexey Bataev1d677132015-04-22 13:57:31 +00001749 ThenGen(CGF);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001750}
1751
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001752// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001753// thread-ID variable (it is passed in a first argument of the outlined function
1754// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1755// regular serial code region, get thread ID by calling kmp_int32
1756// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1757// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00001758Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
1759 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00001760 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001761 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001762 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001763 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001764
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001765 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001766 auto Int32Ty =
1767 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1768 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1769 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00001770 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00001771
1772 return ThreadIDTemp;
1773}
1774
Alexey Bataev97720002014-11-11 04:05:39 +00001775llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001776CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001777 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001778 SmallString<256> Buffer;
1779 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001780 Out << Name;
1781 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001782 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1783 if (Elem.second) {
1784 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001785 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001786 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001787 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001788
David Blaikie13156b62014-11-19 03:06:06 +00001789 return Elem.second = new llvm::GlobalVariable(
1790 CGM.getModule(), Ty, /*IsConstant*/ false,
1791 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1792 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001793}
1794
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001795llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001796 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001797 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001798}
1799
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001800namespace {
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001801/// Common pre(post)-action for different OpenMP constructs.
1802class CommonActionTy final : public PrePostActionTy {
1803 llvm::Value *EnterCallee;
1804 ArrayRef<llvm::Value *> EnterArgs;
1805 llvm::Value *ExitCallee;
1806 ArrayRef<llvm::Value *> ExitArgs;
1807 bool Conditional;
1808 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001809
1810public:
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001811 CommonActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs,
1812 llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs,
1813 bool Conditional = false)
1814 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1815 ExitArgs(ExitArgs), Conditional(Conditional) {}
1816 void Enter(CodeGenFunction &CGF) override {
1817 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
1818 if (Conditional) {
1819 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
1820 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1821 ContBlock = CGF.createBasicBlock("omp_if.end");
1822 // Generate the branch (If-stmt)
1823 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1824 CGF.EmitBlock(ThenBlock);
1825 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00001826 }
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001827 void Done(CodeGenFunction &CGF) {
1828 // Emit the rest of blocks/branches
1829 CGF.EmitBranch(ContBlock);
1830 CGF.EmitBlock(ContBlock, true);
1831 }
1832 void Exit(CodeGenFunction &CGF) override {
1833 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001834 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001835};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001836} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001837
1838void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1839 StringRef CriticalName,
1840 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00001841 SourceLocation Loc, const Expr *Hint) {
1842 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001843 // CriticalOpGen();
1844 // __kmpc_end_critical(ident_t *, gtid, Lock);
1845 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00001846 if (!CGF.HaveInsertPoint())
1847 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00001848 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1849 getCriticalRegionLock(CriticalName)};
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001850 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
1851 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00001852 if (Hint) {
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001853 EnterArgs.push_back(CGF.Builder.CreateIntCast(
1854 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
1855 }
1856 CommonActionTy Action(
1857 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
1858 : OMPRTL__kmpc_critical),
1859 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
1860 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00001861 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001862}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001863
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001864void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001865 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001866 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001867 if (!CGF.HaveInsertPoint())
1868 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00001869 // if(__kmpc_master(ident_t *, gtid)) {
1870 // MasterOpGen();
1871 // __kmpc_end_master(ident_t *, gtid);
1872 // }
1873 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001874 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001875 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
1876 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
1877 /*Conditional=*/true);
1878 MasterOpGen.setAction(Action);
1879 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
1880 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00001881}
1882
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001883void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
1884 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001885 if (!CGF.HaveInsertPoint())
1886 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00001887 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
1888 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001889 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00001890 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001891 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev9f797f32015-02-05 05:57:51 +00001892}
1893
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001894void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
1895 const RegionCodeGenTy &TaskgroupOpGen,
1896 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001897 if (!CGF.HaveInsertPoint())
1898 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001899 // __kmpc_taskgroup(ident_t *, gtid);
1900 // TaskgroupOpGen();
1901 // __kmpc_end_taskgroup(ident_t *, gtid);
1902 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataevb8c425c2016-03-28 09:53:43 +00001903 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1904 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
1905 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
1906 Args);
1907 TaskgroupOpGen.setAction(Action);
1908 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001909}
1910
John McCall7f416cc2015-09-08 08:05:57 +00001911/// Given an array of pointers to variables, project the address of a
1912/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001913static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
1914 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00001915 // Pull out the pointer to the variable.
1916 Address PtrAddr =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001917 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00001918 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
1919
1920 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001921 Addr = CGF.Builder.CreateElementBitCast(
1922 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00001923 return Addr;
1924}
1925
Alexey Bataeva63048e2015-03-23 06:18:07 +00001926static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00001927 CodeGenModule &CGM, llvm::Type *ArgsType,
1928 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
1929 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00001930 auto &C = CGM.getContext();
1931 // void copy_func(void *LHSArg, void *RHSArg);
1932 FunctionArgList Args;
1933 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1934 C.VoidPtrTy);
1935 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1936 C.VoidPtrTy);
1937 Args.push_back(&LHSArg);
1938 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00001939 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001940 auto *Fn = llvm::Function::Create(
1941 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
1942 ".omp.copyprivate.copy_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00001943 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001944 CodeGenFunction CGF(CGM);
1945 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00001946 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001947 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00001948 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1949 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
1950 ArgsType), CGF.getPointerAlign());
1951 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1952 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
1953 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00001954 // *(Type0*)Dst[0] = *(Type0*)Src[0];
1955 // *(Type1*)Dst[1] = *(Type1*)Src[1];
1956 // ...
1957 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00001958 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00001959 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
1960 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
1961
1962 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
1963 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
1964
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001965 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
1966 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00001967 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001968 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001969 CGF.FinishFunction();
1970 return Fn;
1971}
1972
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001973void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001974 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001975 SourceLocation Loc,
1976 ArrayRef<const Expr *> CopyprivateVars,
1977 ArrayRef<const Expr *> SrcExprs,
1978 ArrayRef<const Expr *> DstExprs,
1979 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001980 if (!CGF.HaveInsertPoint())
1981 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00001982 assert(CopyprivateVars.size() == SrcExprs.size() &&
1983 CopyprivateVars.size() == DstExprs.size() &&
1984 CopyprivateVars.size() == AssignmentOps.size());
1985 auto &C = CGM.getContext();
1986 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001987 // if(__kmpc_single(ident_t *, gtid)) {
1988 // SingleOpGen();
1989 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001990 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001991 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001992 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1993 // <copy_func>, did_it);
1994
John McCall7f416cc2015-09-08 08:05:57 +00001995 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00001996 if (!CopyprivateVars.empty()) {
1997 // int32 did_it = 0;
1998 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1999 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00002000 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002001 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002002 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00002003 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataevb8c425c2016-03-28 09:53:43 +00002004 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
2005 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
2006 /*Conditional=*/true);
2007 SingleOpGen.setAction(Action);
2008 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
2009 if (DidIt.isValid()) {
2010 // did_it = 1;
2011 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
2012 }
2013 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002014 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2015 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00002016 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002017 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
2018 auto CopyprivateArrayTy =
2019 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2020 /*IndexTypeQuals=*/0);
2021 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00002022 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002023 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
2024 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002025 Address Elem = CGF.Builder.CreateConstArrayGEP(
2026 CopyprivateList, I, CGF.getPointerSize());
2027 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00002028 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002029 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
2030 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002031 }
2032 // Build function that copies private values from single region to all other
2033 // threads in the corresponding parallel region.
2034 auto *CpyFn = emitCopyprivateCopyFunction(
2035 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00002036 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataev1189bd02016-01-26 12:20:39 +00002037 auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00002038 Address CL =
2039 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
2040 CGF.VoidPtrTy);
2041 auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002042 llvm::Value *Args[] = {
2043 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
2044 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00002045 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00002046 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00002047 CpyFn, // void (*) (void *, void *) <copy_func>
2048 DidItVal // i32 did_it
2049 };
2050 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
2051 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002052}
2053
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002054void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
2055 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00002056 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002057 if (!CGF.HaveInsertPoint())
2058 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002059 // __kmpc_ordered(ident_t *, gtid);
2060 // OrderedOpGen();
2061 // __kmpc_end_ordered(ident_t *, gtid);
2062 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00002063 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002064 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataevb8c425c2016-03-28 09:53:43 +00002065 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
2066 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
2067 Args);
2068 OrderedOpGen.setAction(Action);
2069 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2070 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002071 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00002072 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002073}
2074
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002075void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev25e5b442015-09-15 12:52:43 +00002076 OpenMPDirectiveKind Kind, bool EmitChecks,
2077 bool ForceSimpleCall) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002078 if (!CGF.HaveInsertPoint())
2079 return;
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00002080 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002081 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002082 unsigned Flags;
2083 if (Kind == OMPD_for)
2084 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2085 else if (Kind == OMPD_sections)
2086 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2087 else if (Kind == OMPD_single)
2088 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2089 else if (Kind == OMPD_barrier)
2090 Flags = OMP_IDENT_BARRIER_EXPL;
2091 else
2092 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002093 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
2094 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002095 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
2096 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002097 if (auto *OMPRegionInfo =
2098 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00002099 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002100 auto *Result = CGF.EmitRuntimeCall(
2101 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00002102 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002103 // if (__kmpc_cancel_barrier()) {
2104 // exit from construct;
2105 // }
2106 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
2107 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
2108 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
2109 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2110 CGF.EmitBlock(ExitBB);
2111 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00002112 auto CancelDestination =
2113 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002114 CGF.EmitBranchThroughCleanup(CancelDestination);
2115 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2116 }
2117 return;
2118 }
2119 }
2120 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002121}
2122
Alexander Musmanc6388682014-12-15 07:07:06 +00002123/// \brief Map the OpenMP loop schedule to the runtime enumeration.
2124static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002125 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002126 switch (ScheduleKind) {
2127 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002128 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2129 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00002130 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002131 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002132 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002133 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002134 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002135 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2136 case OMPC_SCHEDULE_auto:
2137 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00002138 case OMPC_SCHEDULE_unknown:
2139 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002140 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00002141 }
2142 llvm_unreachable("Unexpected runtime schedule");
2143}
2144
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002145/// \brief Map the OpenMP distribute schedule to the runtime enumeration.
2146static OpenMPSchedType
2147getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
2148 // only static is allowed for dist_schedule
2149 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2150}
2151
Alexander Musmanc6388682014-12-15 07:07:06 +00002152bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
2153 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002154 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00002155 return Schedule == OMP_sch_static;
2156}
2157
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002158bool CGOpenMPRuntime::isStaticNonchunked(
2159 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2160 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2161 return Schedule == OMP_dist_sch_static;
2162}
2163
2164
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002165bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002166 auto Schedule =
2167 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002168 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
2169 return Schedule != OMP_sch_static;
2170}
2171
John McCall7f416cc2015-09-08 08:05:57 +00002172void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
2173 SourceLocation Loc,
2174 OpenMPScheduleClauseKind ScheduleKind,
2175 unsigned IVSize, bool IVSigned,
2176 bool Ordered, llvm::Value *UB,
2177 llvm::Value *Chunk) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002178 if (!CGF.HaveInsertPoint())
2179 return;
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002180 OpenMPSchedType Schedule =
2181 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00002182 assert(Ordered ||
2183 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2184 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
2185 // Call __kmpc_dispatch_init(
2186 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
2187 // kmp_int[32|64] lower, kmp_int[32|64] upper,
2188 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002189
John McCall7f416cc2015-09-08 08:05:57 +00002190 // If the Chunk was not specified in the clause - use default value 1.
2191 if (Chunk == nullptr)
2192 Chunk = CGF.Builder.getIntN(IVSize, 1);
2193 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002194 emitUpdateLocation(CGF, Loc),
2195 getThreadID(CGF, Loc),
2196 CGF.Builder.getInt32(Schedule), // Schedule type
2197 CGF.Builder.getIntN(IVSize, 0), // Lower
2198 UB, // Upper
2199 CGF.Builder.getIntN(IVSize, 1), // Stride
2200 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00002201 };
2202 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
2203}
2204
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002205static void emitForStaticInitCall(CodeGenFunction &CGF,
2206 SourceLocation Loc,
2207 llvm::Value * UpdateLocation,
2208 llvm::Value * ThreadId,
2209 llvm::Constant * ForStaticInitFunction,
2210 OpenMPSchedType Schedule,
2211 unsigned IVSize, bool IVSigned, bool Ordered,
2212 Address IL, Address LB, Address UB,
2213 Address ST, llvm::Value *Chunk) {
2214 if (!CGF.HaveInsertPoint())
2215 return;
2216
2217 assert(!Ordered);
2218 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2219 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2220 Schedule == OMP_dist_sch_static ||
2221 Schedule == OMP_dist_sch_static_chunked);
2222
2223 // Call __kmpc_for_static_init(
2224 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
2225 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
2226 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
2227 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
2228 if (Chunk == nullptr) {
2229 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2230 Schedule == OMP_dist_sch_static) &&
2231 "expected static non-chunked schedule");
2232 // If the Chunk was not specified in the clause - use default value 1.
2233 Chunk = CGF.Builder.getIntN(IVSize, 1);
2234 } else {
2235 assert((Schedule == OMP_sch_static_chunked ||
2236 Schedule == OMP_ord_static_chunked ||
2237 Schedule == OMP_dist_sch_static_chunked) &&
2238 "expected static chunked schedule");
2239 }
2240 llvm::Value *Args[] = {
2241 UpdateLocation,
2242 ThreadId,
2243 CGF.Builder.getInt32(Schedule), // Schedule type
2244 IL.getPointer(), // &isLastIter
2245 LB.getPointer(), // &LB
2246 UB.getPointer(), // &UB
2247 ST.getPointer(), // &Stride
2248 CGF.Builder.getIntN(IVSize, 1), // Incr
2249 Chunk // Chunk
2250 };
2251 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
2252}
2253
John McCall7f416cc2015-09-08 08:05:57 +00002254void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
2255 SourceLocation Loc,
2256 OpenMPScheduleClauseKind ScheduleKind,
2257 unsigned IVSize, bool IVSigned,
2258 bool Ordered, Address IL, Address LB,
2259 Address UB, Address ST,
2260 llvm::Value *Chunk) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002261 OpenMPSchedType ScheduleNum = getRuntimeSchedule(ScheduleKind, Chunk != nullptr,
2262 Ordered);
2263 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2264 auto *ThreadId = getThreadID(CGF, Loc);
2265 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
2266 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction,
2267 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
2268}
John McCall7f416cc2015-09-08 08:05:57 +00002269
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002270void CGOpenMPRuntime::emitDistributeStaticInit(CodeGenFunction &CGF,
2271 SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind,
2272 unsigned IVSize, bool IVSigned,
2273 bool Ordered, Address IL, Address LB,
2274 Address UB, Address ST,
2275 llvm::Value *Chunk) {
2276 OpenMPSchedType ScheduleNum = getRuntimeSchedule(SchedKind, Chunk != nullptr);
2277 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2278 auto *ThreadId = getThreadID(CGF, Loc);
2279 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
2280 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction,
2281 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002282}
2283
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002284void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
2285 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002286 if (!CGF.HaveInsertPoint())
2287 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00002288 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002289 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002290 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
2291 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00002292}
2293
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002294void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
2295 SourceLocation Loc,
2296 unsigned IVSize,
2297 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002298 if (!CGF.HaveInsertPoint())
2299 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002300 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002301 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002302 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
2303}
2304
Alexander Musman92bdaab2015-03-12 13:37:50 +00002305llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
2306 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00002307 bool IVSigned, Address IL,
2308 Address LB, Address UB,
2309 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002310 // Call __kmpc_dispatch_next(
2311 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2312 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2313 // kmp_int[32|64] *p_stride);
2314 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002315 emitUpdateLocation(CGF, Loc),
2316 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002317 IL.getPointer(), // &isLastIter
2318 LB.getPointer(), // &Lower
2319 UB.getPointer(), // &Upper
2320 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00002321 };
2322 llvm::Value *Call =
2323 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
2324 return CGF.EmitScalarConversion(
2325 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00002326 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002327}
2328
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002329void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
2330 llvm::Value *NumThreads,
2331 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002332 if (!CGF.HaveInsertPoint())
2333 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00002334 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
2335 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002336 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00002337 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002338 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
2339 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00002340}
2341
Alexey Bataev7f210c62015-06-18 13:40:03 +00002342void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
2343 OpenMPProcBindClauseKind ProcBind,
2344 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002345 if (!CGF.HaveInsertPoint())
2346 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00002347 // Constants for proc bind value accepted by the runtime.
2348 enum ProcBindTy {
2349 ProcBindFalse = 0,
2350 ProcBindTrue,
2351 ProcBindMaster,
2352 ProcBindClose,
2353 ProcBindSpread,
2354 ProcBindIntel,
2355 ProcBindDefault
2356 } RuntimeProcBind;
2357 switch (ProcBind) {
2358 case OMPC_PROC_BIND_master:
2359 RuntimeProcBind = ProcBindMaster;
2360 break;
2361 case OMPC_PROC_BIND_close:
2362 RuntimeProcBind = ProcBindClose;
2363 break;
2364 case OMPC_PROC_BIND_spread:
2365 RuntimeProcBind = ProcBindSpread;
2366 break;
2367 case OMPC_PROC_BIND_unknown:
2368 llvm_unreachable("Unsupported proc_bind value.");
2369 }
2370 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
2371 llvm::Value *Args[] = {
2372 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2373 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
2374 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
2375}
2376
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002377void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
2378 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002379 if (!CGF.HaveInsertPoint())
2380 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00002381 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002382 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
2383 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00002384}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002385
Alexey Bataev62b63b12015-03-10 07:28:44 +00002386namespace {
2387/// \brief Indexes of fields for type kmp_task_t.
2388enum KmpTaskTFields {
2389 /// \brief List of shared variables.
2390 KmpTaskTShareds,
2391 /// \brief Task routine.
2392 KmpTaskTRoutine,
2393 /// \brief Partition id for the untied tasks.
2394 KmpTaskTPartId,
2395 /// \brief Function with call of destructors for private variables.
2396 KmpTaskTDestructors,
2397};
Hans Wennborg7eb54642015-09-10 17:07:54 +00002398} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00002399
Samuel Antaoee8fb302016-01-06 13:42:12 +00002400bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
2401 // FIXME: Add other entries type when they become supported.
2402 return OffloadEntriesTargetRegion.empty();
2403}
2404
2405/// \brief Initialize target region entry.
2406void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2407 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2408 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002409 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002410 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
2411 "only required for the device "
2412 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002413 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002414 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr);
2415 ++OffloadingEntriesNum;
2416}
2417
2418void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2419 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2420 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002421 llvm::Constant *Addr, llvm::Constant *ID) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002422 // If we are emitting code for a target, the entry is already initialized,
2423 // only has to be registered.
2424 if (CGM.getLangOpts().OpenMPIsDevice) {
Samuel Antao2de62b02016-02-13 23:35:10 +00002425 assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) &&
Samuel Antaoee8fb302016-01-06 13:42:12 +00002426 "Entry must exist.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002427 auto &Entry =
2428 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00002429 assert(Entry.isValid() && "Entry not initialized!");
2430 Entry.setAddress(Addr);
2431 Entry.setID(ID);
2432 return;
2433 } else {
2434 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID);
Samuel Antao2de62b02016-02-13 23:35:10 +00002435 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002436 }
2437}
2438
2439bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00002440 unsigned DeviceID, unsigned FileID, StringRef ParentName,
2441 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002442 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
2443 if (PerDevice == OffloadEntriesTargetRegion.end())
2444 return false;
2445 auto PerFile = PerDevice->second.find(FileID);
2446 if (PerFile == PerDevice->second.end())
2447 return false;
2448 auto PerParentName = PerFile->second.find(ParentName);
2449 if (PerParentName == PerFile->second.end())
2450 return false;
2451 auto PerLine = PerParentName->second.find(LineNum);
2452 if (PerLine == PerParentName->second.end())
2453 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002454 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00002455 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00002456 return false;
2457 return true;
2458}
2459
2460void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
2461 const OffloadTargetRegionEntryInfoActTy &Action) {
2462 // Scan all target region entries and perform the provided action.
2463 for (auto &D : OffloadEntriesTargetRegion)
2464 for (auto &F : D.second)
2465 for (auto &P : F.second)
2466 for (auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00002467 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002468}
2469
2470/// \brief Create a Ctor/Dtor-like function whose body is emitted through
2471/// \a Codegen. This is used to emit the two functions that register and
2472/// unregister the descriptor of the current compilation unit.
2473static llvm::Function *
2474createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
2475 const RegionCodeGenTy &Codegen) {
2476 auto &C = CGM.getContext();
2477 FunctionArgList Args;
2478 ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(),
2479 /*Id=*/nullptr, C.VoidPtrTy);
2480 Args.push_back(&DummyPtr);
2481
2482 CodeGenFunction CGF(CGM);
2483 GlobalDecl();
John McCallc56a8b32016-03-11 04:30:31 +00002484 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002485 auto FTy = CGM.getTypes().GetFunctionType(FI);
2486 auto *Fn =
2487 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation());
2488 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation());
2489 Codegen(CGF);
2490 CGF.FinishFunction();
2491 return Fn;
2492}
2493
2494llvm::Function *
2495CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
2496
2497 // If we don't have entries or if we are emitting code for the device, we
2498 // don't need to do anything.
2499 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
2500 return nullptr;
2501
2502 auto &M = CGM.getModule();
2503 auto &C = CGM.getContext();
2504
2505 // Get list of devices we care about
2506 auto &Devices = CGM.getLangOpts().OMPTargetTriples;
2507
2508 // We should be creating an offloading descriptor only if there are devices
2509 // specified.
2510 assert(!Devices.empty() && "No OpenMP offloading devices??");
2511
2512 // Create the external variables that will point to the begin and end of the
2513 // host entries section. These will be defined by the linker.
2514 auto *OffloadEntryTy =
2515 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
2516 llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable(
2517 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002518 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002519 ".omp_offloading.entries_begin");
2520 llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable(
2521 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002522 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002523 ".omp_offloading.entries_end");
2524
2525 // Create all device images
2526 llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires;
2527 auto *DeviceImageTy = cast<llvm::StructType>(
2528 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
2529
2530 for (unsigned i = 0; i < Devices.size(); ++i) {
2531 StringRef T = Devices[i].getTriple();
2532 auto *ImgBegin = new llvm::GlobalVariable(
2533 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002534 /*Initializer=*/nullptr,
2535 Twine(".omp_offloading.img_start.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002536 auto *ImgEnd = new llvm::GlobalVariable(
2537 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002538 /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002539
2540 llvm::Constant *Dev =
2541 llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd,
2542 HostEntriesBegin, HostEntriesEnd, nullptr);
2543 DeviceImagesEntires.push_back(Dev);
2544 }
2545
2546 // Create device images global array.
2547 llvm::ArrayType *DeviceImagesInitTy =
2548 llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size());
2549 llvm::Constant *DeviceImagesInit =
2550 llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires);
2551
2552 llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable(
2553 M, DeviceImagesInitTy, /*isConstant=*/true,
2554 llvm::GlobalValue::InternalLinkage, DeviceImagesInit,
2555 ".omp_offloading.device_images");
2556 DeviceImages->setUnnamedAddr(true);
2557
2558 // This is a Zero array to be used in the creation of the constant expressions
2559 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
2560 llvm::Constant::getNullValue(CGM.Int32Ty)};
2561
2562 // Create the target region descriptor.
2563 auto *BinaryDescriptorTy = cast<llvm::StructType>(
2564 CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
2565 llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get(
2566 BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
2567 llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages,
2568 Index),
2569 HostEntriesBegin, HostEntriesEnd, nullptr);
2570
2571 auto *Desc = new llvm::GlobalVariable(
2572 M, BinaryDescriptorTy, /*isConstant=*/true,
2573 llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit,
2574 ".omp_offloading.descriptor");
2575
2576 // Emit code to register or unregister the descriptor at execution
2577 // startup or closing, respectively.
2578
2579 // Create a variable to drive the registration and unregistration of the
2580 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
2581 auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var");
2582 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(),
2583 IdentInfo, C.CharTy);
2584
2585 auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataevb8c425c2016-03-28 09:53:43 +00002586 CGM, ".omp_offloading.descriptor_unreg",
2587 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002588 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
2589 Desc);
2590 });
2591 auto *RegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataevb8c425c2016-03-28 09:53:43 +00002592 CGM, ".omp_offloading.descriptor_reg",
2593 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002594 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib),
2595 Desc);
2596 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
2597 });
2598 return RegFn;
2599}
2600
Samuel Antao2de62b02016-02-13 23:35:10 +00002601void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID,
2602 llvm::Constant *Addr, uint64_t Size) {
2603 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00002604 auto *TgtOffloadEntryType = cast<llvm::StructType>(
2605 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()));
2606 llvm::LLVMContext &C = CGM.getModule().getContext();
2607 llvm::Module &M = CGM.getModule();
2608
2609 // Make sure the address has the right type.
Samuel Antao2de62b02016-02-13 23:35:10 +00002610 llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002611
2612 // Create constant string with the name.
2613 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
2614
2615 llvm::GlobalVariable *Str =
2616 new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true,
2617 llvm::GlobalValue::InternalLinkage, StrPtrInit,
2618 ".omp_offloading.entry_name");
2619 Str->setUnnamedAddr(true);
2620 llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy);
2621
2622 // Create the entry struct.
2623 llvm::Constant *EntryInit = llvm::ConstantStruct::get(
2624 TgtOffloadEntryType, AddrPtr, StrPtr,
2625 llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr);
2626 llvm::GlobalVariable *Entry = new llvm::GlobalVariable(
2627 M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage,
2628 EntryInit, ".omp_offloading.entry");
2629
2630 // The entry has to be created in the section the linker expects it to be.
2631 Entry->setSection(".omp_offloading.entries");
2632 // We can't have any padding between symbols, so we need to have 1-byte
2633 // alignment.
2634 Entry->setAlignment(1);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002635}
2636
2637void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
2638 // Emit the offloading entries and metadata so that the device codegen side
2639 // can
2640 // easily figure out what to emit. The produced metadata looks like this:
2641 //
2642 // !omp_offload.info = !{!1, ...}
2643 //
2644 // Right now we only generate metadata for function that contain target
2645 // regions.
2646
2647 // If we do not have entries, we dont need to do anything.
2648 if (OffloadEntriesInfoManager.empty())
2649 return;
2650
2651 llvm::Module &M = CGM.getModule();
2652 llvm::LLVMContext &C = M.getContext();
2653 SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
2654 OrderedEntries(OffloadEntriesInfoManager.size());
2655
2656 // Create the offloading info metadata node.
2657 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
2658
2659 // Auxiliar methods to create metadata values and strings.
2660 auto getMDInt = [&](unsigned v) {
2661 return llvm::ConstantAsMetadata::get(
2662 llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v));
2663 };
2664
2665 auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); };
2666
2667 // Create function that emits metadata for each target region entry;
2668 auto &&TargetRegionMetadataEmitter = [&](
2669 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002670 OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
2671 llvm::SmallVector<llvm::Metadata *, 32> Ops;
2672 // Generate metadata for target regions. Each entry of this metadata
2673 // contains:
2674 // - Entry 0 -> Kind of this type of metadata (0).
2675 // - Entry 1 -> Device ID of the file where the entry was identified.
2676 // - Entry 2 -> File ID of the file where the entry was identified.
2677 // - Entry 3 -> Mangled name of the function where the entry was identified.
2678 // - Entry 4 -> Line in the file where the entry was identified.
Samuel Antao2de62b02016-02-13 23:35:10 +00002679 // - Entry 5 -> Order the entry was created.
Samuel Antaoee8fb302016-01-06 13:42:12 +00002680 // The first element of the metadata node is the kind.
2681 Ops.push_back(getMDInt(E.getKind()));
2682 Ops.push_back(getMDInt(DeviceID));
2683 Ops.push_back(getMDInt(FileID));
2684 Ops.push_back(getMDString(ParentName));
2685 Ops.push_back(getMDInt(Line));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002686 Ops.push_back(getMDInt(E.getOrder()));
2687
2688 // Save this entry in the right position of the ordered entries array.
2689 OrderedEntries[E.getOrder()] = &E;
2690
2691 // Add metadata to the named metadata node.
2692 MD->addOperand(llvm::MDNode::get(C, Ops));
2693 };
2694
2695 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
2696 TargetRegionMetadataEmitter);
2697
2698 for (auto *E : OrderedEntries) {
2699 assert(E && "All ordered entries must exist!");
2700 if (auto *CE =
2701 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
2702 E)) {
2703 assert(CE->getID() && CE->getAddress() &&
2704 "Entry ID and Addr are invalid!");
Samuel Antao2de62b02016-02-13 23:35:10 +00002705 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002706 } else
2707 llvm_unreachable("Unsupported entry kind.");
2708 }
2709}
2710
2711/// \brief Loads all the offload entries information from the host IR
2712/// metadata.
2713void CGOpenMPRuntime::loadOffloadInfoMetadata() {
2714 // If we are in target mode, load the metadata from the host IR. This code has
2715 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
2716
2717 if (!CGM.getLangOpts().OpenMPIsDevice)
2718 return;
2719
2720 if (CGM.getLangOpts().OMPHostIRFile.empty())
2721 return;
2722
2723 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
2724 if (Buf.getError())
2725 return;
2726
2727 llvm::LLVMContext C;
2728 auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C);
2729
2730 if (ME.getError())
2731 return;
2732
2733 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
2734 if (!MD)
2735 return;
2736
2737 for (auto I : MD->operands()) {
2738 llvm::MDNode *MN = cast<llvm::MDNode>(I);
2739
2740 auto getMDInt = [&](unsigned Idx) {
2741 llvm::ConstantAsMetadata *V =
2742 cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
2743 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
2744 };
2745
2746 auto getMDString = [&](unsigned Idx) {
2747 llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx));
2748 return V->getString();
2749 };
2750
2751 switch (getMDInt(0)) {
2752 default:
2753 llvm_unreachable("Unexpected metadata!");
2754 break;
2755 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
2756 OFFLOAD_ENTRY_INFO_TARGET_REGION:
2757 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
2758 /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2),
2759 /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4),
Samuel Antao2de62b02016-02-13 23:35:10 +00002760 /*Order=*/getMDInt(5));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002761 break;
2762 }
2763 }
2764}
2765
Alexey Bataev62b63b12015-03-10 07:28:44 +00002766void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
2767 if (!KmpRoutineEntryPtrTy) {
2768 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
2769 auto &C = CGM.getContext();
2770 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
2771 FunctionProtoType::ExtProtoInfo EPI;
2772 KmpRoutineEntryPtrQTy = C.getPointerType(
2773 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2774 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
2775 }
2776}
2777
Alexey Bataevc71a4092015-09-11 10:29:41 +00002778static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
2779 QualType FieldTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002780 auto *Field = FieldDecl::Create(
2781 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
2782 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
2783 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
2784 Field->setAccess(AS_public);
2785 DC->addDecl(Field);
Alexey Bataevc71a4092015-09-11 10:29:41 +00002786 return Field;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002787}
2788
Samuel Antaoee8fb302016-01-06 13:42:12 +00002789QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
2790
2791 // Make sure the type of the entry is already created. This is the type we
2792 // have to create:
2793 // struct __tgt_offload_entry{
2794 // void *addr; // Pointer to the offload entry info.
2795 // // (function or global)
2796 // char *name; // Name of the function or global.
2797 // size_t size; // Size of the entry info (0 if it a function).
2798 // };
2799 if (TgtOffloadEntryQTy.isNull()) {
2800 ASTContext &C = CGM.getContext();
2801 auto *RD = C.buildImplicitRecord("__tgt_offload_entry");
2802 RD->startDefinition();
2803 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2804 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
2805 addFieldToRecordDecl(C, RD, C.getSizeType());
2806 RD->completeDefinition();
2807 TgtOffloadEntryQTy = C.getRecordType(RD);
2808 }
2809 return TgtOffloadEntryQTy;
2810}
2811
2812QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
2813 // These are the types we need to build:
2814 // struct __tgt_device_image{
2815 // void *ImageStart; // Pointer to the target code start.
2816 // void *ImageEnd; // Pointer to the target code end.
2817 // // We also add the host entries to the device image, as it may be useful
2818 // // for the target runtime to have access to that information.
2819 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
2820 // // the entries.
2821 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2822 // // entries (non inclusive).
2823 // };
2824 if (TgtDeviceImageQTy.isNull()) {
2825 ASTContext &C = CGM.getContext();
2826 auto *RD = C.buildImplicitRecord("__tgt_device_image");
2827 RD->startDefinition();
2828 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2829 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2830 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2831 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2832 RD->completeDefinition();
2833 TgtDeviceImageQTy = C.getRecordType(RD);
2834 }
2835 return TgtDeviceImageQTy;
2836}
2837
2838QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
2839 // struct __tgt_bin_desc{
2840 // int32_t NumDevices; // Number of devices supported.
2841 // __tgt_device_image *DeviceImages; // Arrays of device images
2842 // // (one per device).
2843 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
2844 // // entries.
2845 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2846 // // entries (non inclusive).
2847 // };
2848 if (TgtBinaryDescriptorQTy.isNull()) {
2849 ASTContext &C = CGM.getContext();
2850 auto *RD = C.buildImplicitRecord("__tgt_bin_desc");
2851 RD->startDefinition();
2852 addFieldToRecordDecl(
2853 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
2854 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
2855 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2856 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2857 RD->completeDefinition();
2858 TgtBinaryDescriptorQTy = C.getRecordType(RD);
2859 }
2860 return TgtBinaryDescriptorQTy;
2861}
2862
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002863namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00002864struct PrivateHelpersTy {
2865 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
2866 const VarDecl *PrivateElemInit)
2867 : Original(Original), PrivateCopy(PrivateCopy),
2868 PrivateElemInit(PrivateElemInit) {}
2869 const VarDecl *Original;
2870 const VarDecl *PrivateCopy;
2871 const VarDecl *PrivateElemInit;
2872};
2873typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00002874} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002875
Alexey Bataev9e034042015-05-05 04:05:12 +00002876static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00002877createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002878 if (!Privates.empty()) {
2879 auto &C = CGM.getContext();
2880 // Build struct .kmp_privates_t. {
2881 // /* private vars */
2882 // };
2883 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
2884 RD->startDefinition();
2885 for (auto &&Pair : Privates) {
Alexey Bataevc71a4092015-09-11 10:29:41 +00002886 auto *VD = Pair.second.Original;
2887 auto Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002888 Type = Type.getNonReferenceType();
Alexey Bataevc71a4092015-09-11 10:29:41 +00002889 auto *FD = addFieldToRecordDecl(C, RD, Type);
2890 if (VD->hasAttrs()) {
2891 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
2892 E(VD->getAttrs().end());
2893 I != E; ++I)
2894 FD->addAttr(*I);
2895 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002896 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002897 RD->completeDefinition();
2898 return RD;
2899 }
2900 return nullptr;
2901}
2902
Alexey Bataev9e034042015-05-05 04:05:12 +00002903static RecordDecl *
2904createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002905 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002906 auto &C = CGM.getContext();
2907 // Build struct kmp_task_t {
2908 // void * shareds;
2909 // kmp_routine_entry_t routine;
2910 // kmp_int32 part_id;
2911 // kmp_routine_entry_t destructors;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002912 // };
2913 auto *RD = C.buildImplicitRecord("kmp_task_t");
2914 RD->startDefinition();
2915 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2916 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
2917 addFieldToRecordDecl(C, RD, KmpInt32Ty);
2918 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002919 RD->completeDefinition();
2920 return RD;
2921}
2922
2923static RecordDecl *
2924createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00002925 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002926 auto &C = CGM.getContext();
2927 // Build struct kmp_task_t_with_privates {
2928 // kmp_task_t task_data;
2929 // .kmp_privates_t. privates;
2930 // };
2931 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
2932 RD->startDefinition();
2933 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002934 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
2935 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
2936 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002937 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002938 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002939}
2940
2941/// \brief Emit a proxy function which accepts kmp_task_t as the second
2942/// argument.
2943/// \code
2944/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002945/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map,
2946/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002947/// return 0;
2948/// }
2949/// \endcode
2950static llvm::Value *
2951emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002952 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
2953 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002954 QualType SharedsPtrTy, llvm::Value *TaskFunction,
2955 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002956 auto &C = CGM.getContext();
2957 FunctionArgList Args;
2958 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
2959 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002960 /*Id=*/nullptr,
2961 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002962 Args.push_back(&GtidArg);
2963 Args.push_back(&TaskTypeArg);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002964 auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00002965 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002966 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
2967 auto *TaskEntry =
2968 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
2969 ".omp_task_entry.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002970 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002971 CodeGenFunction CGF(CGM);
2972 CGF.disableDebugInfo();
2973 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
2974
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002975 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
2976 // tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002977 auto *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002978 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00002979 LValue TDBase = CGF.EmitLoadOfPointerLValue(
2980 CGF.GetAddrOfLocalVar(&TaskTypeArg),
2981 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002982 auto *KmpTaskTWithPrivatesQTyRD =
2983 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002984 LValue Base =
2985 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002986 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
2987 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
2988 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
2989 auto *PartidParam = CGF.EmitLoadOfLValue(PartIdLVal, Loc).getScalarVal();
2990
2991 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
2992 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002993 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002994 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002995 CGF.ConvertTypeForMem(SharedsPtrTy));
2996
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002997 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
2998 llvm::Value *PrivatesParam;
2999 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3000 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
3001 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003002 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003003 } else {
3004 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3005 }
3006
3007 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam,
3008 TaskPrivatesMap, SharedsParam};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003009 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
3010 CGF.EmitStoreThroughLValue(
3011 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
John McCall7f416cc2015-09-08 08:05:57 +00003012 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00003013 CGF.FinishFunction();
3014 return TaskEntry;
3015}
3016
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003017static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
3018 SourceLocation Loc,
3019 QualType KmpInt32Ty,
3020 QualType KmpTaskTWithPrivatesPtrQTy,
3021 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003022 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003023 FunctionArgList Args;
3024 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3025 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003026 /*Id=*/nullptr,
3027 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003028 Args.push_back(&GtidArg);
3029 Args.push_back(&TaskTypeArg);
3030 FunctionType::ExtInfo Info;
3031 auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003032 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003033 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
3034 auto *DestructorFn =
3035 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3036 ".omp_task_destructor.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003037 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
3038 DestructorFnInfo);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003039 CodeGenFunction CGF(CGM);
3040 CGF.disableDebugInfo();
3041 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
3042 Args);
3043
Alexey Bataev31300ed2016-02-04 11:27:03 +00003044 LValue Base = CGF.EmitLoadOfPointerLValue(
3045 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3046 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003047 auto *KmpTaskTWithPrivatesQTyRD =
3048 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3049 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003050 Base = CGF.EmitLValueForField(Base, *FI);
3051 for (auto *Field :
3052 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3053 if (auto DtorKind = Field->getType().isDestructedType()) {
3054 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
3055 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3056 }
3057 }
3058 CGF.FinishFunction();
3059 return DestructorFn;
3060}
3061
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003062/// \brief Emit a privates mapping function for correct handling of private and
3063/// firstprivate variables.
3064/// \code
3065/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
3066/// **noalias priv1,..., <tyn> **noalias privn) {
3067/// *priv1 = &.privates.priv1;
3068/// ...;
3069/// *privn = &.privates.privn;
3070/// }
3071/// \endcode
3072static llvm::Value *
3073emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00003074 ArrayRef<const Expr *> PrivateVars,
3075 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003076 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003077 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003078 auto &C = CGM.getContext();
3079 FunctionArgList Args;
3080 ImplicitParamDecl TaskPrivatesArg(
3081 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3082 C.getPointerType(PrivatesQTy).withConst().withRestrict());
3083 Args.push_back(&TaskPrivatesArg);
3084 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
3085 unsigned Counter = 1;
3086 for (auto *E: PrivateVars) {
3087 Args.push_back(ImplicitParamDecl::Create(
3088 C, /*DC=*/nullptr, Loc,
3089 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3090 .withConst()
3091 .withRestrict()));
3092 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3093 PrivateVarsPos[VD] = Counter;
3094 ++Counter;
3095 }
3096 for (auto *E : FirstprivateVars) {
3097 Args.push_back(ImplicitParamDecl::Create(
3098 C, /*DC=*/nullptr, Loc,
3099 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3100 .withConst()
3101 .withRestrict()));
3102 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3103 PrivateVarsPos[VD] = Counter;
3104 ++Counter;
3105 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003106 auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003107 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003108 auto *TaskPrivatesMapTy =
3109 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
3110 auto *TaskPrivatesMap = llvm::Function::Create(
3111 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
3112 ".omp_task_privates_map.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003113 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
3114 TaskPrivatesMapFnInfo);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00003115 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003116 CodeGenFunction CGF(CGM);
3117 CGF.disableDebugInfo();
3118 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
3119 TaskPrivatesMapFnInfo, Args);
3120
3121 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00003122 LValue Base = CGF.EmitLoadOfPointerLValue(
3123 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
3124 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003125 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
3126 Counter = 0;
3127 for (auto *Field : PrivatesQTyRD->fields()) {
3128 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
3129 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
John McCall7f416cc2015-09-08 08:05:57 +00003130 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
Alexey Bataev31300ed2016-02-04 11:27:03 +00003131 auto RefLoadLVal = CGF.EmitLoadOfPointerLValue(
3132 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003133 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003134 ++Counter;
3135 }
3136 CGF.FinishFunction();
3137 return TaskPrivatesMap;
3138}
3139
Alexey Bataev9e034042015-05-05 04:05:12 +00003140static int array_pod_sort_comparator(const PrivateDataTy *P1,
3141 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003142 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
3143}
3144
3145void CGOpenMPRuntime::emitTaskCall(
3146 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
3147 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
John McCall7f416cc2015-09-08 08:05:57 +00003148 llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003149 const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
3150 ArrayRef<const Expr *> PrivateCopies,
3151 ArrayRef<const Expr *> FirstprivateVars,
3152 ArrayRef<const Expr *> FirstprivateCopies,
3153 ArrayRef<const Expr *> FirstprivateInits,
3154 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003155 if (!CGF.HaveInsertPoint())
3156 return;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003157 auto &C = CGM.getContext();
Alexey Bataev9e034042015-05-05 04:05:12 +00003158 llvm::SmallVector<PrivateDataTy, 8> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003159 // Aggregate privates and sort them by the alignment.
Alexey Bataev9e034042015-05-05 04:05:12 +00003160 auto I = PrivateCopies.begin();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003161 for (auto *E : PrivateVars) {
3162 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3163 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003164 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003165 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3166 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003167 ++I;
3168 }
Alexey Bataev9e034042015-05-05 04:05:12 +00003169 I = FirstprivateCopies.begin();
3170 auto IElemInitRef = FirstprivateInits.begin();
3171 for (auto *E : FirstprivateVars) {
3172 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3173 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003174 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003175 PrivateHelpersTy(
3176 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3177 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
Richard Trieucc3949d2016-02-18 22:34:54 +00003178 ++I;
3179 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00003180 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003181 llvm::array_pod_sort(Privates.begin(), Privates.end(),
3182 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003183 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
3184 // Build type kmp_routine_entry_t (if not built yet).
3185 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003186 // Build type kmp_task_t (if not built yet).
3187 if (KmpTaskTQTy.isNull()) {
3188 KmpTaskTQTy = C.getRecordType(
3189 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
3190 }
3191 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003192 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003193 auto *KmpTaskTWithPrivatesQTyRD =
3194 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
3195 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
3196 QualType KmpTaskTWithPrivatesPtrQTy =
3197 C.getPointerType(KmpTaskTWithPrivatesQTy);
3198 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
3199 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003200 auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003201 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
3202
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003203 // Emit initial values for private copies (if any).
3204 llvm::Value *TaskPrivatesMap = nullptr;
3205 auto *TaskPrivatesMapTy =
3206 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
3207 3)
3208 ->getType();
3209 if (!Privates.empty()) {
3210 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3211 TaskPrivatesMap = emitTaskPrivateMappingFunction(
3212 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
3213 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3214 TaskPrivatesMap, TaskPrivatesMapTy);
3215 } else {
3216 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3217 cast<llvm::PointerType>(TaskPrivatesMapTy));
3218 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003219 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
3220 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003221 auto *TaskEntry = emitProxyTaskFunction(
3222 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003223 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003224
3225 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
3226 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
3227 // kmp_routine_entry_t *task_entry);
3228 // Task flags. Format is taken from
3229 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
3230 // description of kmp_tasking_flags struct.
3231 const unsigned TiedFlag = 0x1;
3232 const unsigned FinalFlag = 0x2;
3233 unsigned Flags = Tied ? TiedFlag : 0;
3234 auto *TaskFlags =
3235 Final.getPointer()
3236 ? CGF.Builder.CreateSelect(Final.getPointer(),
3237 CGF.Builder.getInt32(FinalFlag),
3238 CGF.Builder.getInt32(/*C=*/0))
3239 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
3240 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataev40e36f12015-11-24 13:01:44 +00003241 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003242 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
3243 getThreadID(CGF, Loc), TaskFlags,
3244 KmpTaskTWithPrivatesTySize, SharedsSize,
3245 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3246 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003247 auto *NewTask = CGF.EmitRuntimeCall(
3248 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003249 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3250 NewTask, KmpTaskTWithPrivatesPtrTy);
3251 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
3252 KmpTaskTWithPrivatesQTy);
3253 LValue TDBase =
3254 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003255 // Fill the data in the resulting kmp_task_t record.
3256 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00003257 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003258 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003259 KmpTaskSharedsPtr =
3260 Address(CGF.EmitLoadOfScalar(
3261 CGF.EmitLValueForField(
3262 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
3263 KmpTaskTShareds)),
3264 Loc),
3265 CGF.getNaturalTypeAlignment(SharedsTy));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003266 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003267 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003268 // Emit initial values for private copies (if any).
3269 bool NeedsCleanup = false;
3270 if (!Privates.empty()) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003271 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3272 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003273 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003274 LValue SharedsBase;
3275 if (!FirstprivateVars.empty()) {
John McCall7f416cc2015-09-08 08:05:57 +00003276 SharedsBase = CGF.MakeAddrLValue(
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003277 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3278 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
3279 SharedsTy);
3280 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003281 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
3282 cast<CapturedStmt>(*D.getAssociatedStmt()));
3283 for (auto &&Pair : Privates) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003284 auto *VD = Pair.second.PrivateCopy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003285 auto *Init = VD->getAnyInitializer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003286 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003287 if (Init) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003288 if (auto *Elem = Pair.second.PrivateElemInit) {
3289 auto *OriginalVD = Pair.second.Original;
3290 auto *SharedField = CapturesInfo.lookup(OriginalVD);
3291 auto SharedRefLValue =
3292 CGF.EmitLValueForField(SharedsBase, SharedField);
Alexey Bataevc71a4092015-09-11 10:29:41 +00003293 SharedRefLValue = CGF.MakeAddrLValue(
3294 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
3295 SharedRefLValue.getType(), AlignmentSource::Decl);
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003296 QualType Type = OriginalVD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003297 if (Type->isArrayType()) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003298 // Initialize firstprivate array.
3299 if (!isa<CXXConstructExpr>(Init) ||
3300 CGF.isTrivialInitializer(Init)) {
3301 // Perform simple memcpy.
3302 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003303 SharedRefLValue.getAddress(), Type);
Alexey Bataev9e034042015-05-05 04:05:12 +00003304 } else {
3305 // Initialize firstprivate array using element-by-element
3306 // intialization.
3307 CGF.EmitOMPAggregateAssign(
3308 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003309 Type, [&CGF, Elem, Init, &CapturesInfo](
John McCall7f416cc2015-09-08 08:05:57 +00003310 Address DestElement, Address SrcElement) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003311 // Clean up any temporaries needed by the initialization.
3312 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003313 InitScope.addPrivate(Elem, [SrcElement]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003314 return SrcElement;
3315 });
3316 (void)InitScope.Privatize();
3317 // Emit initialization for single element.
Alexey Bataevd157d472015-06-24 03:35:38 +00003318 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3319 CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003320 CGF.EmitAnyExprToMem(Init, DestElement,
3321 Init->getType().getQualifiers(),
3322 /*IsInitializer=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003323 });
3324 }
3325 } else {
3326 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003327 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003328 return SharedRefLValue.getAddress();
3329 });
3330 (void)InitScope.Privatize();
Alexey Bataevd157d472015-06-24 03:35:38 +00003331 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003332 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
3333 /*capturedByInit=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003334 }
3335 } else {
3336 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
3337 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003338 }
3339 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003340 ++FI;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003341 }
3342 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003343 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003344 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003345 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
3346 KmpTaskTWithPrivatesPtrQTy,
3347 KmpTaskTWithPrivatesQTy)
3348 : llvm::ConstantPointerNull::get(
3349 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
3350 LValue Destructor = CGF.EmitLValueForField(
3351 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
3352 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3353 DestructorFn, KmpRoutineEntryPtrTy),
3354 Destructor);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003355
3356 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00003357 Address DependenciesArray = Address::invalid();
3358 unsigned NumDependencies = Dependences.size();
3359 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003360 // Dependence kind for RTL.
Alexey Bataev92e82f92015-11-23 13:33:42 +00003361 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003362 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
3363 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003364 QualType FlagsTy =
3365 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003366 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
3367 if (KmpDependInfoTy.isNull()) {
3368 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
3369 KmpDependInfoRD->startDefinition();
3370 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
3371 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
3372 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
3373 KmpDependInfoRD->completeDefinition();
3374 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
3375 } else {
3376 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
3377 }
John McCall7f416cc2015-09-08 08:05:57 +00003378 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003379 // Define type kmp_depend_info[<Dependences.size()>];
3380 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00003381 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003382 ArrayType::Normal, /*IndexTypeQuals=*/0);
3383 // kmp_depend_info[<Dependences.size()>] deps;
John McCall7f416cc2015-09-08 08:05:57 +00003384 DependenciesArray = CGF.CreateMemTemp(KmpDependInfoArrayTy);
3385 for (unsigned i = 0; i < NumDependencies; ++i) {
3386 const Expr *E = Dependences[i].second;
3387 auto Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003388 llvm::Value *Size;
3389 QualType Ty = E->getType();
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003390 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
3391 LValue UpAddrLVal =
3392 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
3393 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00003394 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003395 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00003396 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003397 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
3398 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003399 } else
Alexey Bataev1189bd02016-01-26 12:20:39 +00003400 Size = CGF.getTypeSize(Ty);
John McCall7f416cc2015-09-08 08:05:57 +00003401 auto Base = CGF.MakeAddrLValue(
3402 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003403 KmpDependInfoTy);
3404 // deps[i].base_addr = &<Dependences[i].second>;
3405 auto BaseAddrLVal = CGF.EmitLValueForField(
3406 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00003407 CGF.EmitStoreOfScalar(
3408 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
3409 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003410 // deps[i].len = sizeof(<Dependences[i].second>);
3411 auto LenLVal = CGF.EmitLValueForField(
3412 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
3413 CGF.EmitStoreOfScalar(Size, LenLVal);
3414 // deps[i].flags = <Dependences[i].first>;
3415 RTLDependenceKindTy DepKind;
3416 switch (Dependences[i].first) {
3417 case OMPC_DEPEND_in:
3418 DepKind = DepIn;
3419 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00003420 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003421 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003422 case OMPC_DEPEND_inout:
3423 DepKind = DepInOut;
3424 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00003425 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00003426 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003427 case OMPC_DEPEND_unknown:
3428 llvm_unreachable("Unknown task dependence type");
3429 }
3430 auto FlagsLVal = CGF.EmitLValueForField(
3431 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
3432 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
3433 FlagsLVal);
3434 }
John McCall7f416cc2015-09-08 08:05:57 +00003435 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3436 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003437 CGF.VoidPtrTy);
3438 }
3439
Alexey Bataev62b63b12015-03-10 07:28:44 +00003440 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
3441 // libcall.
3442 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
3443 // *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003444 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
3445 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
3446 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
3447 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00003448 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003449 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00003450 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
3451 llvm::Value *DepTaskArgs[7];
3452 if (NumDependencies) {
3453 DepTaskArgs[0] = UpLoc;
3454 DepTaskArgs[1] = ThreadID;
3455 DepTaskArgs[2] = NewTask;
3456 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
3457 DepTaskArgs[4] = DependenciesArray.getPointer();
3458 DepTaskArgs[5] = CGF.Builder.getInt32(0);
3459 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3460 }
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003461 RegionCodeGenTy ThenCodeGen = [this, NumDependencies, &TaskArgs,
3462 &DepTaskArgs](CodeGenFunction &CGF,
3463 PrePostActionTy &) {
3464 // TODO: add check for untied tasks.
John McCall7f416cc2015-09-08 08:05:57 +00003465 if (NumDependencies) {
3466 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps),
3467 DepTaskArgs);
3468 } else {
3469 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
3470 TaskArgs);
3471 }
Alexey Bataev1d677132015-04-22 13:57:31 +00003472 };
John McCall7f416cc2015-09-08 08:05:57 +00003473
3474 llvm::Value *DepWaitTaskArgs[6];
3475 if (NumDependencies) {
3476 DepWaitTaskArgs[0] = UpLoc;
3477 DepWaitTaskArgs[1] = ThreadID;
3478 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
3479 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
3480 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
3481 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3482 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003483 auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003484 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF,
3485 PrePostActionTy &) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003486 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
3487 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
3488 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
3489 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
3490 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00003491 if (NumDependencies)
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003492 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
3493 DepWaitTaskArgs);
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003494 // Call proxy_task_entry(gtid, new_task);
3495 RegionCodeGenTy CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy](
3496 CodeGenFunction &CGF, PrePostActionTy &Action) {
3497 Action.Enter(CGF);
3498 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
3499 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
3500 };
3501
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003502 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
3503 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003504 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
3505 // kmp_task_t *new_task);
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003506 CommonActionTy Action(
3507 createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
3508 createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
3509 CodeGen.setAction(Action);
3510 CodeGen(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003511 };
John McCall7f416cc2015-09-08 08:05:57 +00003512
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003513 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00003514 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003515 else
Alexey Bataev1d677132015-04-22 13:57:31 +00003516 ThenCodeGen(CGF);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003517}
3518
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003519/// \brief Emit reduction operation for each element of array (required for
3520/// array sections) LHS op = RHS.
3521/// \param Type Type of array.
3522/// \param LHSVar Variable on the left side of the reduction operation
3523/// (references element of array in original variable).
3524/// \param RHSVar Variable on the right side of the reduction operation
3525/// (references element of array in original variable).
3526/// \param RedOpGen Generator of reduction operation with use of LHSVar and
3527/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00003528static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003529 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
3530 const VarDecl *RHSVar,
3531 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
3532 const Expr *, const Expr *)> &RedOpGen,
3533 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
3534 const Expr *UpExpr = nullptr) {
3535 // Perform element-by-element initialization.
3536 QualType ElementTy;
3537 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
3538 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
3539
3540 // Drill down to the base element type on both arrays.
3541 auto ArrayTy = Type->getAsArrayTypeUnsafe();
3542 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
3543
3544 auto RHSBegin = RHSAddr.getPointer();
3545 auto LHSBegin = LHSAddr.getPointer();
3546 // Cast from pointer to array type to pointer to single element.
3547 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
3548 // The basic structure here is a while-do loop.
3549 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
3550 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
3551 auto IsEmpty =
3552 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
3553 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
3554
3555 // Enter the loop body, making that address the current address.
3556 auto EntryBB = CGF.Builder.GetInsertBlock();
3557 CGF.EmitBlock(BodyBB);
3558
3559 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
3560
3561 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
3562 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
3563 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
3564 Address RHSElementCurrent =
3565 Address(RHSElementPHI,
3566 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3567
3568 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
3569 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
3570 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
3571 Address LHSElementCurrent =
3572 Address(LHSElementPHI,
3573 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3574
3575 // Emit copy.
3576 CodeGenFunction::OMPPrivateScope Scope(CGF);
3577 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
3578 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
3579 Scope.Privatize();
3580 RedOpGen(CGF, XExpr, EExpr, UpExpr);
3581 Scope.ForceCleanup();
3582
3583 // Shift the address forward by one element.
3584 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
3585 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
3586 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
3587 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
3588 // Check whether we've reached the end.
3589 auto Done =
3590 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
3591 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
3592 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
3593 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
3594
3595 // Done.
3596 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
3597}
3598
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003599/// Emit reduction combiner. If the combiner is a simple expression emit it as
3600/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
3601/// UDR combiner function.
3602static void emitReductionCombiner(CodeGenFunction &CGF,
3603 const Expr *ReductionOp) {
3604 if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
3605 if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
3606 if (auto *DRE =
3607 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
3608 if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
3609 std::pair<llvm::Function *, llvm::Function *> Reduction =
3610 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
3611 RValue Func = RValue::get(Reduction.first);
3612 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
3613 CGF.EmitIgnoredExpr(ReductionOp);
3614 return;
3615 }
3616 CGF.EmitIgnoredExpr(ReductionOp);
3617}
3618
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003619static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
3620 llvm::Type *ArgsType,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003621 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003622 ArrayRef<const Expr *> LHSExprs,
3623 ArrayRef<const Expr *> RHSExprs,
3624 ArrayRef<const Expr *> ReductionOps) {
3625 auto &C = CGM.getContext();
3626
3627 // void reduction_func(void *LHSArg, void *RHSArg);
3628 FunctionArgList Args;
3629 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3630 C.VoidPtrTy);
3631 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3632 C.VoidPtrTy);
3633 Args.push_back(&LHSArg);
3634 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00003635 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003636 auto *Fn = llvm::Function::Create(
3637 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
3638 ".omp.reduction.reduction_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003639 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003640 CodeGenFunction CGF(CGM);
3641 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
3642
3643 // Dst = (void*[n])(LHSArg);
3644 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003645 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3646 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3647 ArgsType), CGF.getPointerAlign());
3648 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3649 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3650 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003651
3652 // ...
3653 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
3654 // ...
3655 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003656 auto IPriv = Privates.begin();
3657 unsigned Idx = 0;
3658 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003659 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
3660 Scope.addPrivate(RHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003661 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003662 });
3663 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
3664 Scope.addPrivate(LHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003665 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003666 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003667 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003668 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003669 // Get array size and emit VLA type.
3670 ++Idx;
3671 Address Elem =
3672 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
3673 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003674 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy);
3675 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003676 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00003677 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003678 CGF.EmitVariablyModifiedType(PrivTy);
3679 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003680 }
3681 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003682 IPriv = Privates.begin();
3683 auto ILHS = LHSExprs.begin();
3684 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003685 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003686 if ((*IPriv)->getType()->isArrayType()) {
3687 // Emit reduction for array section.
3688 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3689 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003690 EmitOMPAggregateReduction(
3691 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3692 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
3693 emitReductionCombiner(CGF, E);
3694 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003695 } else
3696 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003697 emitReductionCombiner(CGF, E);
Richard Trieucc3949d2016-02-18 22:34:54 +00003698 ++IPriv;
3699 ++ILHS;
3700 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003701 }
3702 Scope.ForceCleanup();
3703 CGF.FinishFunction();
3704 return Fn;
3705}
3706
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003707static void emitSingleReductionCombiner(CodeGenFunction &CGF,
3708 const Expr *ReductionOp,
3709 const Expr *PrivateRef,
3710 const DeclRefExpr *LHS,
3711 const DeclRefExpr *RHS) {
3712 if (PrivateRef->getType()->isArrayType()) {
3713 // Emit reduction for array section.
3714 auto *LHSVar = cast<VarDecl>(LHS->getDecl());
3715 auto *RHSVar = cast<VarDecl>(RHS->getDecl());
3716 EmitOMPAggregateReduction(
3717 CGF, PrivateRef->getType(), LHSVar, RHSVar,
3718 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
3719 emitReductionCombiner(CGF, ReductionOp);
3720 });
3721 } else
3722 // Emit reduction for array subscript or single variable.
3723 emitReductionCombiner(CGF, ReductionOp);
3724}
3725
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003726void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003727 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003728 ArrayRef<const Expr *> LHSExprs,
3729 ArrayRef<const Expr *> RHSExprs,
3730 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003731 bool WithNowait, bool SimpleReduction) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003732 if (!CGF.HaveInsertPoint())
3733 return;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003734 // Next code should be emitted for reduction:
3735 //
3736 // static kmp_critical_name lock = { 0 };
3737 //
3738 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
3739 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
3740 // ...
3741 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
3742 // *(Type<n>-1*)rhs[<n>-1]);
3743 // }
3744 //
3745 // ...
3746 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
3747 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
3748 // RedList, reduce_func, &<lock>)) {
3749 // case 1:
3750 // ...
3751 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3752 // ...
3753 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3754 // break;
3755 // case 2:
3756 // ...
3757 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
3758 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00003759 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003760 // break;
3761 // default:;
3762 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003763 //
3764 // if SimpleReduction is true, only the next code is generated:
3765 // ...
3766 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3767 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003768
3769 auto &C = CGM.getContext();
3770
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003771 if (SimpleReduction) {
3772 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003773 auto IPriv = Privates.begin();
3774 auto ILHS = LHSExprs.begin();
3775 auto IRHS = RHSExprs.begin();
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003776 for (auto *E : ReductionOps) {
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003777 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
3778 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00003779 ++IPriv;
3780 ++ILHS;
3781 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003782 }
3783 return;
3784 }
3785
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003786 // 1. Build a list of reduction variables.
3787 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003788 auto Size = RHSExprs.size();
3789 for (auto *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00003790 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003791 // Reserve place for array size.
3792 ++Size;
3793 }
3794 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003795 QualType ReductionArrayTy =
3796 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
3797 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00003798 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003799 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003800 auto IPriv = Privates.begin();
3801 unsigned Idx = 0;
3802 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003803 Address Elem =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003804 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00003805 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003806 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003807 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
3808 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003809 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003810 // Store array size.
3811 ++Idx;
3812 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
3813 CGF.getPointerSize());
Alexey Bataev1189bd02016-01-26 12:20:39 +00003814 llvm::Value *Size = CGF.Builder.CreateIntCast(
3815 CGF.getVLASize(
3816 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
3817 .first,
3818 CGF.SizeTy, /*isSigned=*/false);
3819 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
3820 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003821 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003822 }
3823
3824 // 2. Emit reduce_func().
3825 auto *ReductionFn = emitReductionFunction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003826 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
3827 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003828
3829 // 3. Create static kmp_critical_name lock = { 0 };
3830 auto *Lock = getCriticalRegionLock(".reduction");
3831
3832 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
3833 // RedList, reduce_func, &<lock>);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003834 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003835 auto *ThreadId = getThreadID(CGF, Loc);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003836 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003837 auto *RL =
3838 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
3839 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003840 llvm::Value *Args[] = {
3841 IdentTLoc, // ident_t *<loc>
3842 ThreadId, // i32 <gtid>
3843 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
3844 ReductionArrayTySize, // size_type sizeof(RedList)
3845 RL, // void *RedList
3846 ReductionFn, // void (*) (void *, void *) <reduce_func>
3847 Lock // kmp_critical_name *&<lock>
3848 };
3849 auto Res = CGF.EmitRuntimeCall(
3850 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
3851 : OMPRTL__kmpc_reduce),
3852 Args);
3853
3854 // 5. Build switch(res)
3855 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
3856 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
3857
3858 // 6. Build case 1:
3859 // ...
3860 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3861 // ...
3862 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3863 // break;
3864 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
3865 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
3866 CGF.EmitBlock(Case1BB);
3867
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003868 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3869 llvm::Value *EndArgs[] = {
3870 IdentTLoc, // ident_t *<loc>
3871 ThreadId, // i32 <gtid>
3872 Lock // kmp_critical_name *&<lock>
3873 };
3874 RegionCodeGenTy CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps](
3875 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003876 auto IPriv = Privates.begin();
3877 auto ILHS = LHSExprs.begin();
3878 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003879 for (auto *E : ReductionOps) {
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003880 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
3881 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00003882 ++IPriv;
3883 ++ILHS;
3884 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003885 }
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003886 };
3887 CommonActionTy Action(
3888 nullptr, llvm::None,
3889 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
3890 : OMPRTL__kmpc_end_reduce),
3891 EndArgs);
3892 CodeGen.setAction(Action);
3893 CodeGen(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003894
3895 CGF.EmitBranch(DefaultBB);
3896
3897 // 7. Build case 2:
3898 // ...
3899 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
3900 // ...
3901 // break;
3902 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
3903 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
3904 CGF.EmitBlock(Case2BB);
3905
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003906 RegionCodeGenTy AtomicCodeGen = [this, Loc, &Privates, &LHSExprs, &RHSExprs,
3907 &ReductionOps](CodeGenFunction &CGF,
3908 PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003909 auto ILHS = LHSExprs.begin();
3910 auto IRHS = RHSExprs.begin();
3911 auto IPriv = Privates.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003912 for (auto *E : ReductionOps) {
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003913 const Expr *XExpr = nullptr;
3914 const Expr *EExpr = nullptr;
3915 const Expr *UpExpr = nullptr;
3916 BinaryOperatorKind BO = BO_Comma;
3917 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
3918 if (BO->getOpcode() == BO_Assign) {
3919 XExpr = BO->getLHS();
3920 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003921 }
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003922 }
3923 // Try to emit update expression as a simple atomic.
3924 auto *RHSExpr = UpExpr;
3925 if (RHSExpr) {
3926 // Analyze RHS part of the whole expression.
3927 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
3928 RHSExpr->IgnoreParenImpCasts())) {
3929 // If this is a conditional operator, analyze its condition for
3930 // min/max reduction operator.
3931 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00003932 }
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003933 if (auto *BORHS =
3934 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
3935 EExpr = BORHS->getRHS();
3936 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003937 }
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003938 }
3939 if (XExpr) {
3940 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3941 auto &&AtomicRedGen = [this, BO, VD, IPriv,
3942 Loc](CodeGenFunction &CGF, const Expr *XExpr,
3943 const Expr *EExpr, const Expr *UpExpr) {
3944 LValue X = CGF.EmitLValue(XExpr);
3945 RValue E;
3946 if (EExpr)
3947 E = CGF.EmitAnyExpr(EExpr);
3948 CGF.EmitOMPAtomicSimpleUpdateExpr(
3949 X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
3950 [&CGF, UpExpr, VD, IPriv, Loc](RValue XRValue) {
3951 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
3952 PrivateScope.addPrivate(
3953 VD, [&CGF, VD, XRValue, Loc]() -> Address {
3954 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
3955 CGF.emitOMPSimpleStore(
3956 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
3957 VD->getType().getNonReferenceType(), Loc);
3958 return LHSTemp;
3959 });
3960 (void)PrivateScope.Privatize();
3961 return CGF.EmitAnyExpr(UpExpr);
3962 });
3963 };
3964 if ((*IPriv)->getType()->isArrayType()) {
3965 // Emit atomic reduction for array section.
3966 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3967 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
3968 AtomicRedGen, XExpr, EExpr, UpExpr);
3969 } else
3970 // Emit atomic reduction for array subscript or single variable.
3971 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
3972 } else {
3973 // Emit as a critical region.
3974 auto &&CritRedGen = [this, E, Loc](CodeGenFunction &CGF, const Expr *,
3975 const Expr *, const Expr *) {
3976 emitCriticalRegion(
3977 CGF, ".atomic_reduction",
3978 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
3979 Action.Enter(CGF);
3980 emitReductionCombiner(CGF, E);
3981 },
3982 Loc);
3983 };
3984 if ((*IPriv)->getType()->isArrayType()) {
3985 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3986 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3987 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3988 CritRedGen);
3989 } else
3990 CritRedGen(CGF, nullptr, nullptr, nullptr);
3991 }
Richard Trieucc3949d2016-02-18 22:34:54 +00003992 ++ILHS;
3993 ++IRHS;
3994 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003995 }
Alexey Bataevb8c425c2016-03-28 09:53:43 +00003996 };
3997 if (!WithNowait) {
3998 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
3999 llvm::Value *EndArgs[] = {
4000 IdentTLoc, // ident_t *<loc>
4001 ThreadId, // i32 <gtid>
4002 Lock // kmp_critical_name *&<lock>
4003 };
4004 CommonActionTy Action(nullptr, llvm::None,
4005 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
4006 EndArgs);
4007 AtomicCodeGen.setAction(Action);
4008 AtomicCodeGen(CGF);
4009 } else
4010 AtomicCodeGen(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004011
4012 CGF.EmitBranch(DefaultBB);
4013 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
4014}
4015
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004016void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
4017 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004018 if (!CGF.HaveInsertPoint())
4019 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004020 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
4021 // global_tid);
4022 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
4023 // Ignore return result until untied tasks are supported.
4024 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
4025}
4026
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004027void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004028 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00004029 const RegionCodeGenTy &CodeGen,
4030 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004031 if (!CGF.HaveInsertPoint())
4032 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004033 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004034 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00004035}
4036
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004037namespace {
4038enum RTCancelKind {
4039 CancelNoreq = 0,
4040 CancelParallel = 1,
4041 CancelLoop = 2,
4042 CancelSections = 3,
4043 CancelTaskgroup = 4
4044};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004045} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004046
4047static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
4048 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00004049 if (CancelRegion == OMPD_parallel)
4050 CancelKind = CancelParallel;
4051 else if (CancelRegion == OMPD_for)
4052 CancelKind = CancelLoop;
4053 else if (CancelRegion == OMPD_sections)
4054 CancelKind = CancelSections;
4055 else {
4056 assert(CancelRegion == OMPD_taskgroup);
4057 CancelKind = CancelTaskgroup;
4058 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004059 return CancelKind;
4060}
4061
4062void CGOpenMPRuntime::emitCancellationPointCall(
4063 CodeGenFunction &CGF, SourceLocation Loc,
4064 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004065 if (!CGF.HaveInsertPoint())
4066 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004067 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
4068 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004069 if (auto *OMPRegionInfo =
4070 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00004071 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004072 llvm::Value *Args[] = {
4073 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
4074 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004075 // Ignore return result until untied tasks are supported.
4076 auto *Result = CGF.EmitRuntimeCall(
4077 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
4078 // if (__kmpc_cancellationpoint()) {
4079 // __kmpc_cancel_barrier();
4080 // exit from construct;
4081 // }
4082 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4083 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4084 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4085 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4086 CGF.EmitBlock(ExitBB);
4087 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00004088 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004089 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004090 auto CancelDest =
4091 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004092 CGF.EmitBranchThroughCleanup(CancelDest);
4093 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4094 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004095 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004096}
4097
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004098void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00004099 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004100 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004101 if (!CGF.HaveInsertPoint())
4102 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004103 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
4104 // kmp_int32 cncl_kind);
4105 if (auto *OMPRegionInfo =
4106 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataevb8c425c2016-03-28 09:53:43 +00004107 RegionCodeGenTy ThenGen = [this, Loc, CancelRegion, OMPRegionInfo](
4108 CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev87933c72015-09-18 08:07:34 +00004109 llvm::Value *Args[] = {
4110 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
4111 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
4112 // Ignore return result until untied tasks are supported.
4113 auto *Result =
4114 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
4115 // if (__kmpc_cancel()) {
4116 // __kmpc_cancel_barrier();
4117 // exit from construct;
4118 // }
4119 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4120 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4121 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4122 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4123 CGF.EmitBlock(ExitBB);
4124 // __kmpc_cancel_barrier();
4125 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
4126 // exit from construct;
4127 auto CancelDest =
4128 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
4129 CGF.EmitBranchThroughCleanup(CancelDest);
4130 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4131 };
4132 if (IfCond)
Alexey Bataevb8c425c2016-03-28 09:53:43 +00004133 emitOMPIfClause(CGF, IfCond, ThenGen,
4134 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataev87933c72015-09-18 08:07:34 +00004135 else
4136 ThenGen(CGF);
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004137 }
4138}
Samuel Antaobed3c462015-10-02 16:14:20 +00004139
Samuel Antaoee8fb302016-01-06 13:42:12 +00004140/// \brief Obtain information that uniquely identifies a target entry. This
Samuel Antao2de62b02016-02-13 23:35:10 +00004141/// consists of the file and device IDs as well as line number associated with
4142/// the relevant entry source location.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004143static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
4144 unsigned &DeviceID, unsigned &FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004145 unsigned &LineNum) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004146
4147 auto &SM = C.getSourceManager();
4148
4149 // The loc should be always valid and have a file ID (the user cannot use
4150 // #pragma directives in macros)
4151
4152 assert(Loc.isValid() && "Source location is expected to be always valid.");
4153 assert(Loc.isFileID() && "Source location is expected to refer to a file.");
4154
4155 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
4156 assert(PLoc.isValid() && "Source location is expected to be always valid.");
4157
4158 llvm::sys::fs::UniqueID ID;
4159 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
4160 llvm_unreachable("Source file with target region no longer exists!");
4161
4162 DeviceID = ID.getDevice();
4163 FileID = ID.getFile();
4164 LineNum = PLoc.getLine();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004165}
4166
4167void CGOpenMPRuntime::emitTargetOutlinedFunction(
4168 const OMPExecutableDirective &D, StringRef ParentName,
4169 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataevb8c425c2016-03-28 09:53:43 +00004170 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004171 assert(!ParentName.empty() && "Invalid target region parent name!");
4172
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004173 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
4174 IsOffloadEntry, CodeGen);
4175}
4176
4177void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
4178 const OMPExecutableDirective &D, StringRef ParentName,
4179 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
4180 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004181 // Create a unique name for the entry function using the source location
4182 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004183 //
Samuel Antao2de62b02016-02-13 23:35:10 +00004184 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00004185 //
4186 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00004187 // mangled name of the function that encloses the target region and BB is the
4188 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004189
4190 unsigned DeviceID;
4191 unsigned FileID;
4192 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004193 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004194 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004195 SmallString<64> EntryFnName;
4196 {
4197 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00004198 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
4199 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004200 }
4201
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004202 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4203
Samuel Antaobed3c462015-10-02 16:14:20 +00004204 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004205 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00004206 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004207
4208 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
4209
4210 // If this target outline function is not an offload entry, we don't need to
4211 // register it.
4212 if (!IsOffloadEntry)
4213 return;
4214
4215 // The target region ID is used by the runtime library to identify the current
4216 // target region, so it only has to be unique and not necessarily point to
4217 // anything. It could be the pointer to the outlined function that implements
4218 // the target region, but we aren't using that so that the compiler doesn't
4219 // need to keep that, and could therefore inline the host function if proven
4220 // worthwhile during optimization. In the other hand, if emitting code for the
4221 // device, the ID has to be the function address so that it can retrieved from
4222 // the offloading entry and launched by the runtime library. We also mark the
4223 // outlined function to have external linkage in case we are emitting code for
4224 // the device, because these functions will be entry points to the device.
4225
4226 if (CGM.getLangOpts().OpenMPIsDevice) {
4227 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
4228 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage);
4229 } else
4230 OutlinedFnID = new llvm::GlobalVariable(
4231 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
4232 llvm::GlobalValue::PrivateLinkage,
4233 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id");
4234
4235 // Register the information for the entry associated with this target region.
4236 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00004237 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID);
Samuel Antaobed3c462015-10-02 16:14:20 +00004238}
4239
Samuel Antaob68e2db2016-03-03 16:20:23 +00004240/// \brief Emit the num_teams clause of an enclosed teams directive at the
4241/// target region scope. If there is no teams directive associated with the
4242/// target directive, or if there is no num_teams clause associated with the
4243/// enclosed teams directive, return nullptr.
4244static llvm::Value *
4245emitNumTeamsClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4246 CodeGenFunction &CGF,
4247 const OMPExecutableDirective &D) {
4248
4249 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4250 "teams directive expected to be "
4251 "emitted only for the host!");
4252
4253 // FIXME: For the moment we do not support combined directives with target and
4254 // teams, so we do not expect to get any num_teams clause in the provided
4255 // directive. Once we support that, this assertion can be replaced by the
4256 // actual emission of the clause expression.
4257 assert(D.getSingleClause<OMPNumTeamsClause>() == nullptr &&
4258 "Not expecting clause in directive.");
4259
4260 // If the current target region has a teams region enclosed, we need to get
4261 // the number of teams to pass to the runtime function call. This is done
4262 // by generating the expression in a inlined region. This is required because
4263 // the expression is captured in the enclosing target environment when the
4264 // teams directive is not combined with target.
4265
4266 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4267
4268 // FIXME: Accommodate other combined directives with teams when they become
4269 // available.
4270 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) {
4271 if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) {
4272 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4273 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4274 llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams());
4275 return CGF.Builder.CreateIntCast(NumTeams, CGF.Int32Ty,
4276 /*IsSigned=*/true);
4277 }
4278
4279 // If we have an enclosed teams directive but no num_teams clause we use
4280 // the default value 0.
4281 return CGF.Builder.getInt32(0);
4282 }
4283
4284 // No teams associated with the directive.
4285 return nullptr;
4286}
4287
4288/// \brief Emit the thread_limit clause of an enclosed teams directive at the
4289/// target region scope. If there is no teams directive associated with the
4290/// target directive, or if there is no thread_limit clause associated with the
4291/// enclosed teams directive, return nullptr.
4292static llvm::Value *
4293emitThreadLimitClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4294 CodeGenFunction &CGF,
4295 const OMPExecutableDirective &D) {
4296
4297 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4298 "teams directive expected to be "
4299 "emitted only for the host!");
4300
4301 // FIXME: For the moment we do not support combined directives with target and
4302 // teams, so we do not expect to get any thread_limit clause in the provided
4303 // directive. Once we support that, this assertion can be replaced by the
4304 // actual emission of the clause expression.
4305 assert(D.getSingleClause<OMPThreadLimitClause>() == nullptr &&
4306 "Not expecting clause in directive.");
4307
4308 // If the current target region has a teams region enclosed, we need to get
4309 // the thread limit to pass to the runtime function call. This is done
4310 // by generating the expression in a inlined region. This is required because
4311 // the expression is captured in the enclosing target environment when the
4312 // teams directive is not combined with target.
4313
4314 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4315
4316 // FIXME: Accommodate other combined directives with teams when they become
4317 // available.
4318 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) {
4319 if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) {
4320 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4321 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4322 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit());
4323 return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty,
4324 /*IsSigned=*/true);
4325 }
4326
4327 // If we have an enclosed teams directive but no thread_limit clause we use
4328 // the default value 0.
4329 return CGF.Builder.getInt32(0);
4330 }
4331
4332 // No teams associated with the directive.
4333 return nullptr;
4334}
4335
Samuel Antaobed3c462015-10-02 16:14:20 +00004336void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
4337 const OMPExecutableDirective &D,
4338 llvm::Value *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00004339 llvm::Value *OutlinedFnID,
Samuel Antaobed3c462015-10-02 16:14:20 +00004340 const Expr *IfCond, const Expr *Device,
4341 ArrayRef<llvm::Value *> CapturedVars) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004342 if (!CGF.HaveInsertPoint())
4343 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00004344 /// \brief Values for bit flags used to specify the mapping type for
4345 /// offloading.
4346 enum OpenMPOffloadMappingFlags {
4347 /// \brief Allocate memory on the device and move data from host to device.
4348 OMP_MAP_TO = 0x01,
4349 /// \brief Allocate memory on the device and move data from device to host.
4350 OMP_MAP_FROM = 0x02,
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004351 /// \brief The element passed to the device is a pointer.
4352 OMP_MAP_PTR = 0x20,
4353 /// \brief Pass the element to the device by value.
4354 OMP_MAP_BYCOPY = 0x80,
Samuel Antaobed3c462015-10-02 16:14:20 +00004355 };
4356
4357 enum OpenMPOffloadingReservedDeviceIDs {
4358 /// \brief Device ID if the device was not defined, runtime should get it
4359 /// from environment variables in the spec.
4360 OMP_DEVICEID_UNDEF = -1,
4361 };
4362
Samuel Antaoee8fb302016-01-06 13:42:12 +00004363 assert(OutlinedFn && "Invalid outlined function!");
4364
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004365 auto &Ctx = CGF.getContext();
4366
Samuel Antaobed3c462015-10-02 16:14:20 +00004367 // Fill up the arrays with the all the captured variables.
4368 SmallVector<llvm::Value *, 16> BasePointers;
4369 SmallVector<llvm::Value *, 16> Pointers;
4370 SmallVector<llvm::Value *, 16> Sizes;
4371 SmallVector<unsigned, 16> MapTypes;
4372
4373 bool hasVLACaptures = false;
4374
4375 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4376 auto RI = CS.getCapturedRecordDecl()->field_begin();
4377 // auto II = CS.capture_init_begin();
4378 auto CV = CapturedVars.begin();
4379 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
4380 CE = CS.capture_end();
4381 CI != CE; ++CI, ++RI, ++CV) {
4382 StringRef Name;
4383 QualType Ty;
4384 llvm::Value *BasePointer;
4385 llvm::Value *Pointer;
4386 llvm::Value *Size;
4387 unsigned MapType;
4388
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004389 // VLA sizes are passed to the outlined region by copy.
Samuel Antaobed3c462015-10-02 16:14:20 +00004390 if (CI->capturesVariableArrayType()) {
4391 BasePointer = Pointer = *CV;
Alexey Bataev1189bd02016-01-26 12:20:39 +00004392 Size = CGF.getTypeSize(RI->getType());
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004393 // Copy to the device as an argument. No need to retrieve it.
4394 MapType = OMP_MAP_BYCOPY;
Samuel Antaobed3c462015-10-02 16:14:20 +00004395 hasVLACaptures = true;
Samuel Antaobed3c462015-10-02 16:14:20 +00004396 } else if (CI->capturesThis()) {
4397 BasePointer = Pointer = *CV;
4398 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr());
Alexey Bataev1189bd02016-01-26 12:20:39 +00004399 Size = CGF.getTypeSize(PtrTy->getPointeeType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004400 // Default map type.
4401 MapType = OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004402 } else if (CI->capturesVariableByCopy()) {
4403 MapType = OMP_MAP_BYCOPY;
4404 if (!RI->getType()->isAnyPointerType()) {
4405 // If the field is not a pointer, we need to save the actual value and
4406 // load it as a void pointer.
4407 auto DstAddr = CGF.CreateMemTemp(
4408 Ctx.getUIntPtrType(),
4409 Twine(CI->getCapturedVar()->getName()) + ".casted");
4410 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
4411
4412 auto *SrcAddrVal = CGF.EmitScalarConversion(
4413 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
4414 Ctx.getPointerType(RI->getType()), SourceLocation());
4415 LValue SrcLV =
4416 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType());
4417
4418 // Store the value using the source type pointer.
4419 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV);
4420
4421 // Load the value using the destination type pointer.
4422 BasePointer = Pointer =
4423 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
4424 } else {
4425 MapType |= OMP_MAP_PTR;
4426 BasePointer = Pointer = *CV;
4427 }
Alexey Bataev1189bd02016-01-26 12:20:39 +00004428 Size = CGF.getTypeSize(RI->getType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004429 } else {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004430 assert(CI->capturesVariable() && "Expected captured reference.");
Samuel Antaobed3c462015-10-02 16:14:20 +00004431 BasePointer = Pointer = *CV;
4432
4433 const ReferenceType *PtrTy =
4434 cast<ReferenceType>(RI->getType().getTypePtr());
4435 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00004436 Size = CGF.getTypeSize(ElementType);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004437 // The default map type for a scalar/complex type is 'to' because by
4438 // default the value doesn't have to be retrieved. For an aggregate type,
4439 // the default is 'tofrom'.
4440 MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
4441 : OMP_MAP_TO;
4442 if (ElementType->isAnyPointerType())
4443 MapType |= OMP_MAP_PTR;
Samuel Antaobed3c462015-10-02 16:14:20 +00004444 }
4445
4446 BasePointers.push_back(BasePointer);
4447 Pointers.push_back(Pointer);
4448 Sizes.push_back(Size);
4449 MapTypes.push_back(MapType);
4450 }
4451
4452 // Keep track on whether the host function has to be executed.
4453 auto OffloadErrorQType =
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004454 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004455 auto OffloadError = CGF.MakeAddrLValue(
4456 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
4457 OffloadErrorQType);
4458 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
4459 OffloadError);
4460
4461 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataevb8c425c2016-03-28 09:53:43 +00004462 RegionCodeGenTy ThenGen = [this, &Ctx, &BasePointers, &Pointers, &Sizes,
4463 &MapTypes, hasVLACaptures, Device, OutlinedFnID,
4464 OffloadError, OffloadErrorQType,
4465 &D](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00004466 unsigned PointerNumVal = BasePointers.size();
4467 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal);
4468 llvm::Value *BasePointersArray;
4469 llvm::Value *PointersArray;
4470 llvm::Value *SizesArray;
4471 llvm::Value *MapTypesArray;
4472
4473 if (PointerNumVal) {
4474 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004475 QualType PointerArrayType = Ctx.getConstantArrayType(
4476 Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004477 /*IndexTypeQuals=*/0);
4478
4479 BasePointersArray =
4480 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
4481 PointersArray =
4482 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
4483
4484 // If we don't have any VLA types, we can use a constant array for the map
4485 // sizes, otherwise we need to fill up the arrays as we do for the
4486 // pointers.
4487 if (hasVLACaptures) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004488 QualType SizeArrayType = Ctx.getConstantArrayType(
4489 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004490 /*IndexTypeQuals=*/0);
4491 SizesArray =
4492 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
4493 } else {
4494 // We expect all the sizes to be constant, so we collect them to create
4495 // a constant array.
4496 SmallVector<llvm::Constant *, 16> ConstSizes;
4497 for (auto S : Sizes)
4498 ConstSizes.push_back(cast<llvm::Constant>(S));
4499
4500 auto *SizesArrayInit = llvm::ConstantArray::get(
4501 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
4502 auto *SizesArrayGbl = new llvm::GlobalVariable(
4503 CGM.getModule(), SizesArrayInit->getType(),
4504 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4505 SizesArrayInit, ".offload_sizes");
4506 SizesArrayGbl->setUnnamedAddr(true);
4507 SizesArray = SizesArrayGbl;
4508 }
4509
4510 // The map types are always constant so we don't need to generate code to
4511 // fill arrays. Instead, we create an array constant.
4512 llvm::Constant *MapTypesArrayInit =
4513 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
4514 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
4515 CGM.getModule(), MapTypesArrayInit->getType(),
4516 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4517 MapTypesArrayInit, ".offload_maptypes");
4518 MapTypesArrayGbl->setUnnamedAddr(true);
4519 MapTypesArray = MapTypesArrayGbl;
4520
4521 for (unsigned i = 0; i < PointerNumVal; ++i) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004522 llvm::Value *BPVal = BasePointers[i];
4523 if (BPVal->getType()->isPointerTy())
4524 BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy);
4525 else {
4526 assert(BPVal->getType()->isIntegerTy() &&
4527 "If not a pointer, the value type must be an integer.");
4528 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy);
4529 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004530 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
4531 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal),
4532 BasePointersArray, 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004533 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4534 CGF.Builder.CreateStore(BPVal, BPAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004535
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004536 llvm::Value *PVal = Pointers[i];
4537 if (PVal->getType()->isPointerTy())
4538 PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy);
4539 else {
4540 assert(PVal->getType()->isIntegerTy() &&
4541 "If not a pointer, the value type must be an integer.");
4542 PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy);
4543 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004544 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
4545 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
4546 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004547 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4548 CGF.Builder.CreateStore(PVal, PAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004549
4550 if (hasVLACaptures) {
4551 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
4552 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
4553 /*Idx0=*/0,
4554 /*Idx1=*/i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004555 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
Samuel Antaobed3c462015-10-02 16:14:20 +00004556 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(
4557 Sizes[i], CGM.SizeTy, /*isSigned=*/true),
4558 SAddr);
4559 }
4560 }
4561
4562 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
4563 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), BasePointersArray,
4564 /*Idx0=*/0, /*Idx1=*/0);
4565 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
4566 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
4567 /*Idx0=*/0,
4568 /*Idx1=*/0);
4569 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
4570 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
4571 /*Idx0=*/0, /*Idx1=*/0);
4572 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
4573 llvm::ArrayType::get(CGM.Int32Ty, PointerNumVal), MapTypesArray,
4574 /*Idx0=*/0,
4575 /*Idx1=*/0);
4576
4577 } else {
4578 BasePointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
4579 PointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
4580 SizesArray = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
4581 MapTypesArray =
4582 llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo());
4583 }
4584
4585 // On top of the arrays that were filled up, the target offloading call
4586 // takes as arguments the device id as well as the host pointer. The host
4587 // pointer is used by the runtime library to identify the current target
4588 // region, so it only has to be unique and not necessarily point to
4589 // anything. It could be the pointer to the outlined function that
4590 // implements the target region, but we aren't using that so that the
4591 // compiler doesn't need to keep that, and could therefore inline the host
4592 // function if proven worthwhile during optimization.
4593
Samuel Antaoee8fb302016-01-06 13:42:12 +00004594 // From this point on, we need to have an ID of the target region defined.
4595 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00004596
4597 // Emit device ID if any.
4598 llvm::Value *DeviceID;
4599 if (Device)
4600 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
4601 CGM.Int32Ty, /*isSigned=*/true);
4602 else
4603 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
4604
Samuel Antaob68e2db2016-03-03 16:20:23 +00004605 // Return value of the runtime offloading call.
4606 llvm::Value *Return;
4607
4608 auto *NumTeams = emitNumTeamsClauseForTargetDirective(*this, CGF, D);
4609 auto *ThreadLimit = emitThreadLimitClauseForTargetDirective(*this, CGF, D);
4610
4611 // If we have NumTeams defined this means that we have an enclosed teams
4612 // region. Therefore we also expect to have ThreadLimit defined. These two
4613 // values should be defined in the presence of a teams directive, regardless
4614 // of having any clauses associated. If the user is using teams but no
4615 // clauses, these two values will be the default that should be passed to
4616 // the runtime library - a 32-bit integer with the value zero.
4617 if (NumTeams) {
4618 assert(ThreadLimit && "Thread limit expression should be available along "
4619 "with number of teams.");
4620 llvm::Value *OffloadingArgs[] = {
4621 DeviceID, OutlinedFnID, PointerNum,
4622 BasePointersArray, PointersArray, SizesArray,
4623 MapTypesArray, NumTeams, ThreadLimit};
4624 Return = CGF.EmitRuntimeCall(
4625 createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs);
4626 } else {
4627 llvm::Value *OffloadingArgs[] = {
4628 DeviceID, OutlinedFnID, PointerNum, BasePointersArray,
4629 PointersArray, SizesArray, MapTypesArray};
4630 Return = CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target),
4631 OffloadingArgs);
4632 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004633
4634 CGF.EmitStoreOfScalar(Return, OffloadError);
4635 };
4636
Samuel Antaoee8fb302016-01-06 13:42:12 +00004637 // Notify that the host version must be executed.
Alexey Bataevb8c425c2016-03-28 09:53:43 +00004638 RegionCodeGenTy ElseGen = [this, OffloadError, OffloadErrorQType](
4639 CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004640 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/-1u),
4641 OffloadError);
4642 };
4643
4644 // If we have a target function ID it means that we need to support
4645 // offloading, otherwise, just execute on the host. We need to execute on host
4646 // regardless of the conditional in the if clause if, e.g., the user do not
4647 // specify target triples.
4648 if (OutlinedFnID) {
Alexey Bataevb8c425c2016-03-28 09:53:43 +00004649 if (IfCond)
Samuel Antaoee8fb302016-01-06 13:42:12 +00004650 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataevb8c425c2016-03-28 09:53:43 +00004651 else
Samuel Antaoee8fb302016-01-06 13:42:12 +00004652 ThenGen(CGF);
Alexey Bataevb8c425c2016-03-28 09:53:43 +00004653 } else
Samuel Antaoee8fb302016-01-06 13:42:12 +00004654 ElseGen(CGF);
Samuel Antaobed3c462015-10-02 16:14:20 +00004655
4656 // Check the error code and execute the host version if required.
4657 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
4658 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
4659 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
4660 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
4661 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
4662
4663 CGF.EmitBlock(OffloadFailedBlock);
4664 CGF.Builder.CreateCall(OutlinedFn, BasePointers);
4665 CGF.EmitBranch(OffloadContBlock);
4666
4667 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004668}
Samuel Antaoee8fb302016-01-06 13:42:12 +00004669
4670void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
4671 StringRef ParentName) {
4672 if (!S)
4673 return;
4674
4675 // If we find a OMP target directive, codegen the outline function and
4676 // register the result.
4677 // FIXME: Add other directives with target when they become supported.
4678 bool isTargetDirective = isa<OMPTargetDirective>(S);
4679
4680 if (isTargetDirective) {
4681 auto *E = cast<OMPExecutableDirective>(S);
4682 unsigned DeviceID;
4683 unsigned FileID;
4684 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004685 getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004686 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004687
4688 // Is this a target region that should not be emitted as an entry point? If
4689 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00004690 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
4691 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004692 return;
4693
4694 llvm::Function *Fn;
4695 llvm::Constant *Addr;
Alexey Bataevb8c425c2016-03-28 09:53:43 +00004696 std::tie(Fn, Addr) =
4697 CodeGenFunction::EmitOMPTargetDirectiveOutlinedFunction(
4698 CGM, cast<OMPTargetDirective>(*E), ParentName,
4699 /*isOffloadEntry=*/true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004700 assert(Fn && Addr && "Target region emission failed.");
4701 return;
4702 }
4703
4704 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) {
4705 if (!E->getAssociatedStmt())
4706 return;
4707
4708 scanForTargetRegionsFunctions(
4709 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(),
4710 ParentName);
4711 return;
4712 }
4713
4714 // If this is a lambda function, look into its body.
4715 if (auto *L = dyn_cast<LambdaExpr>(S))
4716 S = L->getBody();
4717
4718 // Keep looking for target regions recursively.
4719 for (auto *II : S->children())
4720 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004721}
4722
4723bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
4724 auto &FD = *cast<FunctionDecl>(GD.getDecl());
4725
4726 // If emitting code for the host, we do not process FD here. Instead we do
4727 // the normal code generation.
4728 if (!CGM.getLangOpts().OpenMPIsDevice)
4729 return false;
4730
4731 // Try to detect target regions in the function.
4732 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
4733
4734 // We should not emit any function othen that the ones created during the
4735 // scanning. Therefore, we signal that this function is completely dealt
4736 // with.
4737 return true;
4738}
4739
4740bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
4741 if (!CGM.getLangOpts().OpenMPIsDevice)
4742 return false;
4743
4744 // Check if there are Ctors/Dtors in this declaration and look for target
4745 // regions in it. We use the complete variant to produce the kernel name
4746 // mangling.
4747 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
4748 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
4749 for (auto *Ctor : RD->ctors()) {
4750 StringRef ParentName =
4751 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
4752 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
4753 }
4754 auto *Dtor = RD->getDestructor();
4755 if (Dtor) {
4756 StringRef ParentName =
4757 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
4758 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
4759 }
4760 }
4761
4762 // If we are in target mode we do not emit any global (declare target is not
4763 // implemented yet). Therefore we signal that GD was processed in this case.
4764 return true;
4765}
4766
4767bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
4768 auto *VD = GD.getDecl();
4769 if (isa<FunctionDecl>(VD))
4770 return emitTargetFunctions(GD);
4771
4772 return emitTargetGlobalVariable(GD);
4773}
4774
4775llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
4776 // If we have offloading in the current module, we need to emit the entries
4777 // now and register the offloading descriptor.
4778 createOffloadEntriesAndInfoMetadata();
4779
4780 // Create and register the offloading binary descriptors. This is the main
4781 // entity that captures all the information about offloading in the current
4782 // compilation unit.
4783 return createOffloadingBinaryDescriptorRegistration();
4784}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004785
4786void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
4787 const OMPExecutableDirective &D,
4788 SourceLocation Loc,
4789 llvm::Value *OutlinedFn,
4790 ArrayRef<llvm::Value *> CapturedVars) {
4791 if (!CGF.HaveInsertPoint())
4792 return;
4793
4794 auto *RTLoc = emitUpdateLocation(CGF, Loc);
4795 CodeGenFunction::RunCleanupsScope Scope(CGF);
4796
4797 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
4798 llvm::Value *Args[] = {
4799 RTLoc,
4800 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
4801 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
4802 llvm::SmallVector<llvm::Value *, 16> RealArgs;
4803 RealArgs.append(std::begin(Args), std::end(Args));
4804 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
4805
4806 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
4807 CGF.EmitRuntimeCall(RTLFn, RealArgs);
4808}
4809
4810void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
4811 llvm::Value *NumTeams,
4812 llvm::Value *ThreadLimit,
4813 SourceLocation Loc) {
4814 if (!CGF.HaveInsertPoint())
4815 return;
4816
4817 auto *RTLoc = emitUpdateLocation(CGF, Loc);
4818
4819 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
4820 llvm::Value *PushNumTeamsArgs[] = {
4821 RTLoc, getThreadID(CGF, Loc), NumTeams, ThreadLimit};
4822 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
4823 PushNumTeamsArgs);
4824}