blob: c4eaabe6ac93c185410401d17bc73117981c84bc [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 Bataev6f1ffc02015-04-10 04:50:10 +0000255/// \brief RAII for emitting code of OpenMP constructs.
256class InlinedOpenMPRegionRAII {
257 CodeGenFunction &CGF;
258
259public:
260 /// \brief Constructs region for combined constructs.
261 /// \param CodeGen Code generation sequence for combined directives. Includes
262 /// a list of functions used for code generation of implicitly inlined
263 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000264 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000265 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000266 : CGF(CGF) {
267 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000268 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
269 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000270 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000271
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000272 ~InlinedOpenMPRegionRAII() {
273 // Restore original CapturedStmtInfo only if we're done with code emission.
274 auto *OldCSI =
275 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
276 delete CGF.CapturedStmtInfo;
277 CGF.CapturedStmtInfo = OldCSI;
278 }
279};
280
Alexey Bataev50b3c952016-02-19 10:38:26 +0000281/// \brief Values for bit flags used in the ident_t to describe the fields.
282/// All enumeric elements are named and described in accordance with the code
283/// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
284enum OpenMPLocationFlags {
285 /// \brief Use trampoline for internal microtask.
286 OMP_IDENT_IMD = 0x01,
287 /// \brief Use c-style ident structure.
288 OMP_IDENT_KMPC = 0x02,
289 /// \brief Atomic reduction option for kmpc_reduce.
290 OMP_ATOMIC_REDUCE = 0x10,
291 /// \brief Explicit 'barrier' directive.
292 OMP_IDENT_BARRIER_EXPL = 0x20,
293 /// \brief Implicit barrier in code.
294 OMP_IDENT_BARRIER_IMPL = 0x40,
295 /// \brief Implicit barrier in 'for' directive.
296 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
297 /// \brief Implicit barrier in 'sections' directive.
298 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
299 /// \brief Implicit barrier in 'single' directive.
300 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140
301};
302
303/// \brief Describes ident structure that describes a source location.
304/// All descriptions are taken from
305/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
306/// Original structure:
307/// typedef struct ident {
308/// kmp_int32 reserved_1; /**< might be used in Fortran;
309/// see above */
310/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
311/// KMP_IDENT_KMPC identifies this union
312/// member */
313/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
314/// see above */
315///#if USE_ITT_BUILD
316/// /* but currently used for storing
317/// region-specific ITT */
318/// /* contextual information. */
319///#endif /* USE_ITT_BUILD */
320/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
321/// C++ */
322/// char const *psource; /**< String describing the source location.
323/// The string is composed of semi-colon separated
324// fields which describe the source file,
325/// the function and a pair of line numbers that
326/// delimit the construct.
327/// */
328/// } ident_t;
329enum IdentFieldIndex {
330 /// \brief might be used in Fortran
331 IdentField_Reserved_1,
332 /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
333 IdentField_Flags,
334 /// \brief Not really used in Fortran any more
335 IdentField_Reserved_2,
336 /// \brief Source[4] in Fortran, do not use for C++
337 IdentField_Reserved_3,
338 /// \brief String describing the source location. The string is composed of
339 /// semi-colon separated fields which describe the source file, the function
340 /// and a pair of line numbers that delimit the construct.
341 IdentField_PSource
342};
343
344/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
345/// the enum sched_type in kmp.h).
346enum OpenMPSchedType {
347 /// \brief Lower bound for default (unordered) versions.
348 OMP_sch_lower = 32,
349 OMP_sch_static_chunked = 33,
350 OMP_sch_static = 34,
351 OMP_sch_dynamic_chunked = 35,
352 OMP_sch_guided_chunked = 36,
353 OMP_sch_runtime = 37,
354 OMP_sch_auto = 38,
355 /// \brief Lower bound for 'ordered' versions.
356 OMP_ord_lower = 64,
357 OMP_ord_static_chunked = 65,
358 OMP_ord_static = 66,
359 OMP_ord_dynamic_chunked = 67,
360 OMP_ord_guided_chunked = 68,
361 OMP_ord_runtime = 69,
362 OMP_ord_auto = 70,
363 OMP_sch_default = OMP_sch_static,
364};
365
366enum OpenMPRTLFunction {
367 /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
368 /// kmpc_micro microtask, ...);
369 OMPRTL__kmpc_fork_call,
370 /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc,
371 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
372 OMPRTL__kmpc_threadprivate_cached,
373 /// \brief Call to void __kmpc_threadprivate_register( ident_t *,
374 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
375 OMPRTL__kmpc_threadprivate_register,
376 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
377 OMPRTL__kmpc_global_thread_num,
378 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
379 // kmp_critical_name *crit);
380 OMPRTL__kmpc_critical,
381 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
382 // global_tid, kmp_critical_name *crit, uintptr_t hint);
383 OMPRTL__kmpc_critical_with_hint,
384 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
385 // kmp_critical_name *crit);
386 OMPRTL__kmpc_end_critical,
387 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
388 // global_tid);
389 OMPRTL__kmpc_cancel_barrier,
390 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
391 OMPRTL__kmpc_barrier,
392 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
393 OMPRTL__kmpc_for_static_fini,
394 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
395 // global_tid);
396 OMPRTL__kmpc_serialized_parallel,
397 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
398 // global_tid);
399 OMPRTL__kmpc_end_serialized_parallel,
400 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
401 // kmp_int32 num_threads);
402 OMPRTL__kmpc_push_num_threads,
403 // Call to void __kmpc_flush(ident_t *loc);
404 OMPRTL__kmpc_flush,
405 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
406 OMPRTL__kmpc_master,
407 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
408 OMPRTL__kmpc_end_master,
409 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
410 // int end_part);
411 OMPRTL__kmpc_omp_taskyield,
412 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
413 OMPRTL__kmpc_single,
414 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
415 OMPRTL__kmpc_end_single,
416 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
417 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
418 // kmp_routine_entry_t *task_entry);
419 OMPRTL__kmpc_omp_task_alloc,
420 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
421 // new_task);
422 OMPRTL__kmpc_omp_task,
423 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
424 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
425 // kmp_int32 didit);
426 OMPRTL__kmpc_copyprivate,
427 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
428 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
429 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
430 OMPRTL__kmpc_reduce,
431 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
432 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
433 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
434 // *lck);
435 OMPRTL__kmpc_reduce_nowait,
436 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
437 // kmp_critical_name *lck);
438 OMPRTL__kmpc_end_reduce,
439 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
440 // kmp_critical_name *lck);
441 OMPRTL__kmpc_end_reduce_nowait,
442 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
443 // kmp_task_t * new_task);
444 OMPRTL__kmpc_omp_task_begin_if0,
445 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
446 // kmp_task_t * new_task);
447 OMPRTL__kmpc_omp_task_complete_if0,
448 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
449 OMPRTL__kmpc_ordered,
450 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
451 OMPRTL__kmpc_end_ordered,
452 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
453 // global_tid);
454 OMPRTL__kmpc_omp_taskwait,
455 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
456 OMPRTL__kmpc_taskgroup,
457 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
458 OMPRTL__kmpc_end_taskgroup,
459 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
460 // int proc_bind);
461 OMPRTL__kmpc_push_proc_bind,
462 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
463 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
464 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
465 OMPRTL__kmpc_omp_task_with_deps,
466 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
467 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
468 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
469 OMPRTL__kmpc_omp_wait_deps,
470 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
471 // global_tid, kmp_int32 cncl_kind);
472 OMPRTL__kmpc_cancellationpoint,
473 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
474 // kmp_int32 cncl_kind);
475 OMPRTL__kmpc_cancel,
476
477 //
478 // Offloading related calls
479 //
480 // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
481 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
482 // *arg_types);
483 OMPRTL__tgt_target,
484 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
485 OMPRTL__tgt_register_lib,
486 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
487 OMPRTL__tgt_unregister_lib,
488};
489
Hans Wennborg7eb54642015-09-10 17:07:54 +0000490} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000491
492LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +0000493 return CGF.EmitLoadOfPointerLValue(
494 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
495 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +0000496}
497
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000498void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000499 if (!CGF.HaveInsertPoint())
500 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000501 // 1.2.2 OpenMP Language Terminology
502 // Structured block - An executable statement with a single entry at the
503 // top and a single exit at the bottom.
504 // The point of exit cannot be a branch out of the structured block.
505 // longjmp() and throw() must not violate the entry/exit criteria.
506 CGF.EHStack.pushTerminate();
507 {
508 CodeGenFunction::RunCleanupsScope Scope(CGF);
509 CodeGen(CGF);
510 }
511 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000512}
513
Alexey Bataev62b63b12015-03-10 07:28:44 +0000514LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
515 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000516 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
517 getThreadIDVariable()->getType(),
518 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000519}
520
Alexey Bataev9959db52014-05-06 10:08:46 +0000521CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
Samuel Antaoee8fb302016-01-06 13:42:12 +0000522 : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr),
523 OffloadEntriesInfoManager(CGM) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000524 IdentTy = llvm::StructType::create(
525 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
526 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000527 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000528 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
Alexey Bataev23b69422014-06-18 07:08:49 +0000529 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
530 llvm::PointerType::getUnqual(CGM.Int32Ty)};
Alexey Bataev9959db52014-05-06 10:08:46 +0000531 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000532 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +0000533
534 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +0000535}
536
Alexey Bataev91797552015-03-18 04:13:55 +0000537void CGOpenMPRuntime::clear() {
538 InternalVars.clear();
539}
540
John McCall7f416cc2015-09-08 08:05:57 +0000541// Layout information for ident_t.
542static CharUnits getIdentAlign(CodeGenModule &CGM) {
543 return CGM.getPointerAlign();
544}
545static CharUnits getIdentSize(CodeGenModule &CGM) {
546 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign()));
547 return CharUnits::fromQuantity(16) + CGM.getPointerSize();
548}
Alexey Bataev50b3c952016-02-19 10:38:26 +0000549static CharUnits getOffsetOfIdentField(IdentFieldIndex Field) {
John McCall7f416cc2015-09-08 08:05:57 +0000550 // All the fields except the last are i32, so this works beautifully.
551 return unsigned(Field) * CharUnits::fromQuantity(4);
552}
553static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000554 IdentFieldIndex Field,
John McCall7f416cc2015-09-08 08:05:57 +0000555 const llvm::Twine &Name = "") {
556 auto Offset = getOffsetOfIdentField(Field);
557 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
558}
559
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000560llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction(
561 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
562 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000563 assert(ThreadIDVar->getType()->isPointerType() &&
564 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +0000565 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
566 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +0000567 bool HasCancel = false;
568 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
569 HasCancel = OPD->hasCancel();
570 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
571 HasCancel = OPSD->hasCancel();
572 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
573 HasCancel = OPFD->hasCancel();
574 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
575 HasCancel);
Alexey Bataevd157d472015-06-24 03:35:38 +0000576 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000577 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +0000578}
579
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000580llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
581 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
582 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000583 assert(!ThreadIDVar->getType()->isPointerType() &&
584 "thread id variable must be of type kmp_int32 for tasks");
585 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
586 CodeGenFunction CGF(CGM, true);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000587 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000588 InnermostKind,
589 cast<OMPTaskDirective>(D).hasCancel());
Alexey Bataevd157d472015-06-24 03:35:38 +0000590 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000591 return CGF.GenerateCapturedStmtFunction(*CS);
592}
593
Alexey Bataev50b3c952016-02-19 10:38:26 +0000594Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
John McCall7f416cc2015-09-08 08:05:57 +0000595 CharUnits Align = getIdentAlign(CGM);
Alexey Bataev15007ba2014-05-07 06:18:01 +0000596 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000597 if (!Entry) {
598 if (!DefaultOpenMPPSource) {
599 // Initialize default location for psource field of ident_t structure of
600 // all ident_t objects. Format is ";file;function;line;column;;".
601 // Taken from
602 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
603 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +0000604 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000605 DefaultOpenMPPSource =
606 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
607 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000608 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
609 CGM.getModule(), IdentTy, /*isConstant*/ true,
610 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000611 DefaultOpenMPLocation->setUnnamedAddr(true);
John McCall7f416cc2015-09-08 08:05:57 +0000612 DefaultOpenMPLocation->setAlignment(Align.getQuantity());
Alexey Bataev9959db52014-05-06 10:08:46 +0000613
614 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000615 llvm::Constant *Values[] = {Zero,
616 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
617 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000618 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
619 DefaultOpenMPLocation->setInitializer(Init);
John McCall7f416cc2015-09-08 08:05:57 +0000620 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000621 }
John McCall7f416cc2015-09-08 08:05:57 +0000622 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +0000623}
624
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000625llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
626 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000627 unsigned Flags) {
628 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +0000629 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +0000630 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +0000631 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +0000632 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000633
634 assert(CGF.CurFn && "No function in current CodeGenFunction.");
635
John McCall7f416cc2015-09-08 08:05:57 +0000636 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000637 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
638 if (I != OpenMPLocThreadIDMap.end())
John McCall7f416cc2015-09-08 08:05:57 +0000639 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
640
Alexander Musmanc6388682014-12-15 07:07:06 +0000641 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
642 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +0000643 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000644 // Generate "ident_t .kmpc_loc.addr;"
John McCall7f416cc2015-09-08 08:05:57 +0000645 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
646 ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +0000647 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +0000648 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000649 LocValue = AI;
650
651 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
652 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000653 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
John McCall7f416cc2015-09-08 08:05:57 +0000654 CGM.getSize(getIdentSize(CGF.CGM)));
Alexey Bataev9959db52014-05-06 10:08:46 +0000655 }
656
657 // char **psource = &.kmpc_loc_<flags>.addr.psource;
John McCall7f416cc2015-09-08 08:05:57 +0000658 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000659
Alexey Bataevf002aca2014-05-30 05:48:40 +0000660 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
661 if (OMPDebugLoc == nullptr) {
662 SmallString<128> Buffer2;
663 llvm::raw_svector_ostream OS2(Buffer2);
664 // Build debug location
665 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
666 OS2 << ";" << PLoc.getFilename() << ";";
667 if (const FunctionDecl *FD =
668 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
669 OS2 << FD->getQualifiedNameAsString();
670 }
671 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
672 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
673 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000674 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000675 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000676 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
677
John McCall7f416cc2015-09-08 08:05:57 +0000678 // Our callers always pass this to a runtime function, so for
679 // convenience, go ahead and return a naked pointer.
680 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000681}
682
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000683llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
684 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000685 assert(CGF.CurFn && "No function in current CodeGenFunction.");
686
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000687 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000688 // Check whether we've already cached a load of the thread id in this
689 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000690 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000691 if (I != OpenMPLocThreadIDMap.end()) {
692 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000693 if (ThreadID != nullptr)
694 return ThreadID;
695 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +0000696 if (auto *OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000697 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000698 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000699 // Check if this an outlined function with thread id passed as argument.
700 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000701 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
702 // If value loaded in entry block, cache it and use it everywhere in
703 // function.
704 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
705 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
706 Elem.second.ThreadID = ThreadID;
707 }
708 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000709 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000710 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000711
712 // This is not an outlined function region - need to call __kmpc_int32
713 // kmpc_global_thread_num(ident_t *loc).
714 // Generate thread id value and cache this value for use across the
715 // function.
716 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
717 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
718 ThreadID =
719 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
720 emitUpdateLocation(CGF, Loc));
721 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
722 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000723 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000724}
725
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000726void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000727 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000728 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
729 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataev9959db52014-05-06 10:08:46 +0000730}
731
732llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
733 return llvm::PointerType::getUnqual(IdentTy);
734}
735
736llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
737 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
738}
739
740llvm::Constant *
Alexey Bataev50b3c952016-02-19 10:38:26 +0000741CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000742 llvm::Constant *RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +0000743 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000744 case OMPRTL__kmpc_fork_call: {
745 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
746 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +0000747 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
748 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000749 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000750 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +0000751 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
752 break;
753 }
754 case OMPRTL__kmpc_global_thread_num: {
755 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +0000756 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000757 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000758 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +0000759 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
760 break;
761 }
Alexey Bataev97720002014-11-11 04:05:39 +0000762 case OMPRTL__kmpc_threadprivate_cached: {
763 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
764 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
765 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
766 CGM.VoidPtrTy, CGM.SizeTy,
767 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
768 llvm::FunctionType *FnTy =
769 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
770 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
771 break;
772 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000773 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000774 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
775 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000776 llvm::Type *TypeParams[] = {
777 getIdentTyPointerTy(), CGM.Int32Ty,
778 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
779 llvm::FunctionType *FnTy =
780 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
781 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
782 break;
783 }
Alexey Bataevfc57d162015-12-15 10:55:09 +0000784 case OMPRTL__kmpc_critical_with_hint: {
785 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
786 // kmp_critical_name *crit, uintptr_t hint);
787 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
788 llvm::PointerType::getUnqual(KmpCriticalNameTy),
789 CGM.IntPtrTy};
790 llvm::FunctionType *FnTy =
791 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
792 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
793 break;
794 }
Alexey Bataev97720002014-11-11 04:05:39 +0000795 case OMPRTL__kmpc_threadprivate_register: {
796 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
797 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
798 // typedef void *(*kmpc_ctor)(void *);
799 auto KmpcCtorTy =
800 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
801 /*isVarArg*/ false)->getPointerTo();
802 // typedef void *(*kmpc_cctor)(void *, void *);
803 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
804 auto KmpcCopyCtorTy =
805 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
806 /*isVarArg*/ false)->getPointerTo();
807 // typedef void (*kmpc_dtor)(void *);
808 auto KmpcDtorTy =
809 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
810 ->getPointerTo();
811 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
812 KmpcCopyCtorTy, KmpcDtorTy};
813 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
814 /*isVarArg*/ false);
815 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
816 break;
817 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000818 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000819 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
820 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000821 llvm::Type *TypeParams[] = {
822 getIdentTyPointerTy(), CGM.Int32Ty,
823 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
824 llvm::FunctionType *FnTy =
825 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
826 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
827 break;
828 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000829 case OMPRTL__kmpc_cancel_barrier: {
830 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
831 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000832 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
833 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000834 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
835 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000836 break;
837 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000838 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +0000839 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000840 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
841 llvm::FunctionType *FnTy =
842 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
843 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
844 break;
845 }
Alexander Musmanc6388682014-12-15 07:07:06 +0000846 case OMPRTL__kmpc_for_static_fini: {
847 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
848 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
849 llvm::FunctionType *FnTy =
850 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
851 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
852 break;
853 }
Alexey Bataevb2059782014-10-13 08:23:51 +0000854 case OMPRTL__kmpc_push_num_threads: {
855 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
856 // kmp_int32 num_threads)
857 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
858 CGM.Int32Ty};
859 llvm::FunctionType *FnTy =
860 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
861 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
862 break;
863 }
Alexey Bataevd74d0602014-10-13 06:02:40 +0000864 case OMPRTL__kmpc_serialized_parallel: {
865 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
866 // global_tid);
867 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
868 llvm::FunctionType *FnTy =
869 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
870 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
871 break;
872 }
873 case OMPRTL__kmpc_end_serialized_parallel: {
874 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
875 // global_tid);
876 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
877 llvm::FunctionType *FnTy =
878 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
879 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
880 break;
881 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000882 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000883 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000884 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
885 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000886 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000887 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
888 break;
889 }
Alexey Bataev8d690652014-12-04 07:23:53 +0000890 case OMPRTL__kmpc_master: {
891 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
892 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
893 llvm::FunctionType *FnTy =
894 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
895 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
896 break;
897 }
898 case OMPRTL__kmpc_end_master: {
899 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
900 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
901 llvm::FunctionType *FnTy =
902 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
903 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
904 break;
905 }
Alexey Bataev9f797f32015-02-05 05:57:51 +0000906 case OMPRTL__kmpc_omp_taskyield: {
907 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
908 // int end_part);
909 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
910 llvm::FunctionType *FnTy =
911 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
912 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
913 break;
914 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +0000915 case OMPRTL__kmpc_single: {
916 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
917 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
918 llvm::FunctionType *FnTy =
919 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
920 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
921 break;
922 }
923 case OMPRTL__kmpc_end_single: {
924 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
925 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
926 llvm::FunctionType *FnTy =
927 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
928 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
929 break;
930 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000931 case OMPRTL__kmpc_omp_task_alloc: {
932 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
933 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
934 // kmp_routine_entry_t *task_entry);
935 assert(KmpRoutineEntryPtrTy != nullptr &&
936 "Type kmp_routine_entry_t must be created.");
937 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
938 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
939 // Return void * and then cast to particular kmp_task_t type.
940 llvm::FunctionType *FnTy =
941 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
942 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
943 break;
944 }
945 case OMPRTL__kmpc_omp_task: {
946 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
947 // *new_task);
948 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
949 CGM.VoidPtrTy};
950 llvm::FunctionType *FnTy =
951 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
952 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
953 break;
954 }
Alexey Bataeva63048e2015-03-23 06:18:07 +0000955 case OMPRTL__kmpc_copyprivate: {
956 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +0000957 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +0000958 // kmp_int32 didit);
959 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
960 auto *CpyFnTy =
961 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +0000962 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +0000963 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
964 CGM.Int32Ty};
965 llvm::FunctionType *FnTy =
966 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
967 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
968 break;
969 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +0000970 case OMPRTL__kmpc_reduce: {
971 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
972 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
973 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
974 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
975 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
976 /*isVarArg=*/false);
977 llvm::Type *TypeParams[] = {
978 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
979 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
980 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
981 llvm::FunctionType *FnTy =
982 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
983 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
984 break;
985 }
986 case OMPRTL__kmpc_reduce_nowait: {
987 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
988 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
989 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
990 // *lck);
991 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
992 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
993 /*isVarArg=*/false);
994 llvm::Type *TypeParams[] = {
995 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
996 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
997 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
998 llvm::FunctionType *FnTy =
999 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1000 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
1001 break;
1002 }
1003 case OMPRTL__kmpc_end_reduce: {
1004 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
1005 // kmp_critical_name *lck);
1006 llvm::Type *TypeParams[] = {
1007 getIdentTyPointerTy(), CGM.Int32Ty,
1008 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1009 llvm::FunctionType *FnTy =
1010 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1011 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
1012 break;
1013 }
1014 case OMPRTL__kmpc_end_reduce_nowait: {
1015 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
1016 // kmp_critical_name *lck);
1017 llvm::Type *TypeParams[] = {
1018 getIdentTyPointerTy(), CGM.Int32Ty,
1019 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1020 llvm::FunctionType *FnTy =
1021 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1022 RTLFn =
1023 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
1024 break;
1025 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001026 case OMPRTL__kmpc_omp_task_begin_if0: {
1027 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1028 // *new_task);
1029 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1030 CGM.VoidPtrTy};
1031 llvm::FunctionType *FnTy =
1032 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1033 RTLFn =
1034 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
1035 break;
1036 }
1037 case OMPRTL__kmpc_omp_task_complete_if0: {
1038 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1039 // *new_task);
1040 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1041 CGM.VoidPtrTy};
1042 llvm::FunctionType *FnTy =
1043 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1044 RTLFn = CGM.CreateRuntimeFunction(FnTy,
1045 /*Name=*/"__kmpc_omp_task_complete_if0");
1046 break;
1047 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001048 case OMPRTL__kmpc_ordered: {
1049 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
1050 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1051 llvm::FunctionType *FnTy =
1052 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1053 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
1054 break;
1055 }
1056 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001057 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001058 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1059 llvm::FunctionType *FnTy =
1060 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1061 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
1062 break;
1063 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00001064 case OMPRTL__kmpc_omp_taskwait: {
1065 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
1066 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1067 llvm::FunctionType *FnTy =
1068 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1069 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
1070 break;
1071 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001072 case OMPRTL__kmpc_taskgroup: {
1073 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
1074 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1075 llvm::FunctionType *FnTy =
1076 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1077 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
1078 break;
1079 }
1080 case OMPRTL__kmpc_end_taskgroup: {
1081 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
1082 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1083 llvm::FunctionType *FnTy =
1084 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1085 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
1086 break;
1087 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00001088 case OMPRTL__kmpc_push_proc_bind: {
1089 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
1090 // int proc_bind)
1091 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1092 llvm::FunctionType *FnTy =
1093 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1094 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
1095 break;
1096 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00001097 case OMPRTL__kmpc_omp_task_with_deps: {
1098 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
1099 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
1100 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
1101 llvm::Type *TypeParams[] = {
1102 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
1103 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
1104 llvm::FunctionType *FnTy =
1105 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1106 RTLFn =
1107 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
1108 break;
1109 }
1110 case OMPRTL__kmpc_omp_wait_deps: {
1111 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
1112 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
1113 // kmp_depend_info_t *noalias_dep_list);
1114 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1115 CGM.Int32Ty, CGM.VoidPtrTy,
1116 CGM.Int32Ty, CGM.VoidPtrTy};
1117 llvm::FunctionType *FnTy =
1118 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1119 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
1120 break;
1121 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00001122 case OMPRTL__kmpc_cancellationpoint: {
1123 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
1124 // global_tid, kmp_int32 cncl_kind)
1125 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1126 llvm::FunctionType *FnTy =
1127 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1128 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
1129 break;
1130 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001131 case OMPRTL__kmpc_cancel: {
1132 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
1133 // kmp_int32 cncl_kind)
1134 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1135 llvm::FunctionType *FnTy =
1136 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1137 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
1138 break;
1139 }
Samuel Antaobed3c462015-10-02 16:14:20 +00001140 case OMPRTL__tgt_target: {
1141 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
1142 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
1143 // *arg_types);
1144 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1145 CGM.VoidPtrTy,
1146 CGM.Int32Ty,
1147 CGM.VoidPtrPtrTy,
1148 CGM.VoidPtrPtrTy,
1149 CGM.SizeTy->getPointerTo(),
1150 CGM.Int32Ty->getPointerTo()};
1151 llvm::FunctionType *FnTy =
1152 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1153 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
1154 break;
1155 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00001156 case OMPRTL__tgt_register_lib: {
1157 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
1158 QualType ParamTy =
1159 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1160 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1161 llvm::FunctionType *FnTy =
1162 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1163 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
1164 break;
1165 }
1166 case OMPRTL__tgt_unregister_lib: {
1167 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
1168 QualType ParamTy =
1169 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1170 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1171 llvm::FunctionType *FnTy =
1172 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1173 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
1174 break;
1175 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001176 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00001177 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00001178 return RTLFn;
1179}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001180
Alexander Musman21212e42015-03-13 10:38:23 +00001181llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
1182 bool IVSigned) {
1183 assert((IVSize == 32 || IVSize == 64) &&
1184 "IV size is not compatible with the omp runtime");
1185 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
1186 : "__kmpc_for_static_init_4u")
1187 : (IVSigned ? "__kmpc_for_static_init_8"
1188 : "__kmpc_for_static_init_8u");
1189 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1190 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1191 llvm::Type *TypeParams[] = {
1192 getIdentTyPointerTy(), // loc
1193 CGM.Int32Ty, // tid
1194 CGM.Int32Ty, // schedtype
1195 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1196 PtrTy, // p_lower
1197 PtrTy, // p_upper
1198 PtrTy, // p_stride
1199 ITy, // incr
1200 ITy // chunk
1201 };
1202 llvm::FunctionType *FnTy =
1203 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1204 return CGM.CreateRuntimeFunction(FnTy, Name);
1205}
1206
Alexander Musman92bdaab2015-03-12 13:37:50 +00001207llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
1208 bool IVSigned) {
1209 assert((IVSize == 32 || IVSize == 64) &&
1210 "IV size is not compatible with the omp runtime");
1211 auto Name =
1212 IVSize == 32
1213 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
1214 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
1215 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1216 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
1217 CGM.Int32Ty, // tid
1218 CGM.Int32Ty, // schedtype
1219 ITy, // lower
1220 ITy, // upper
1221 ITy, // stride
1222 ITy // chunk
1223 };
1224 llvm::FunctionType *FnTy =
1225 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1226 return CGM.CreateRuntimeFunction(FnTy, Name);
1227}
1228
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001229llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
1230 bool IVSigned) {
1231 assert((IVSize == 32 || IVSize == 64) &&
1232 "IV size is not compatible with the omp runtime");
1233 auto Name =
1234 IVSize == 32
1235 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1236 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1237 llvm::Type *TypeParams[] = {
1238 getIdentTyPointerTy(), // loc
1239 CGM.Int32Ty, // tid
1240 };
1241 llvm::FunctionType *FnTy =
1242 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1243 return CGM.CreateRuntimeFunction(FnTy, Name);
1244}
1245
Alexander Musman92bdaab2015-03-12 13:37:50 +00001246llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
1247 bool IVSigned) {
1248 assert((IVSize == 32 || IVSize == 64) &&
1249 "IV size is not compatible with the omp runtime");
1250 auto Name =
1251 IVSize == 32
1252 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1253 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1254 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1255 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1256 llvm::Type *TypeParams[] = {
1257 getIdentTyPointerTy(), // loc
1258 CGM.Int32Ty, // tid
1259 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1260 PtrTy, // p_lower
1261 PtrTy, // p_upper
1262 PtrTy // p_stride
1263 };
1264 llvm::FunctionType *FnTy =
1265 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1266 return CGM.CreateRuntimeFunction(FnTy, Name);
1267}
1268
Alexey Bataev97720002014-11-11 04:05:39 +00001269llvm::Constant *
1270CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001271 assert(!CGM.getLangOpts().OpenMPUseTLS ||
1272 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00001273 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001274 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001275 Twine(CGM.getMangledName(VD)) + ".cache.");
1276}
1277
John McCall7f416cc2015-09-08 08:05:57 +00001278Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1279 const VarDecl *VD,
1280 Address VDAddr,
1281 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001282 if (CGM.getLangOpts().OpenMPUseTLS &&
1283 CGM.getContext().getTargetInfo().isTLSSupported())
1284 return VDAddr;
1285
John McCall7f416cc2015-09-08 08:05:57 +00001286 auto VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001287 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001288 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1289 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001290 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1291 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00001292 return Address(CGF.EmitRuntimeCall(
1293 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
1294 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00001295}
1296
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001297void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00001298 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00001299 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1300 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1301 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001302 auto OMPLoc = emitUpdateLocation(CGF, Loc);
1303 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00001304 OMPLoc);
1305 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1306 // to register constructor/destructor for variable.
1307 llvm::Value *Args[] = {OMPLoc,
John McCall7f416cc2015-09-08 08:05:57 +00001308 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1309 CGM.VoidPtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001310 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001311 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001312 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001313}
1314
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001315llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00001316 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00001317 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001318 if (CGM.getLangOpts().OpenMPUseTLS &&
1319 CGM.getContext().getTargetInfo().isTLSSupported())
1320 return nullptr;
1321
Alexey Bataev97720002014-11-11 04:05:39 +00001322 VD = VD->getDefinition(CGM.getContext());
1323 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
1324 ThreadPrivateWithDefinition.insert(VD);
1325 QualType ASTTy = VD->getType();
1326
1327 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1328 auto Init = VD->getAnyInitializer();
1329 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1330 // Generate function that re-emits the declaration's initializer into the
1331 // threadprivate copy of the variable VD
1332 CodeGenFunction CtorCGF(CGM);
1333 FunctionArgList Args;
1334 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1335 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1336 Args.push_back(&Dst);
1337
1338 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1339 CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(),
1340 /*isVariadic=*/false);
1341 auto FTy = CGM.getTypes().GetFunctionType(FI);
1342 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001343 FTy, ".__kmpc_global_ctor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001344 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1345 Args, SourceLocation());
1346 auto ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001347 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001348 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00001349 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1350 Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
1351 CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00001352 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1353 /*IsInitializer=*/true);
1354 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001355 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001356 CGM.getContext().VoidPtrTy, Dst.getLocation());
1357 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1358 CtorCGF.FinishFunction();
1359 Ctor = Fn;
1360 }
1361 if (VD->getType().isDestructedType() != QualType::DK_none) {
1362 // Generate function that emits destructor call for the threadprivate copy
1363 // of the variable VD
1364 CodeGenFunction DtorCGF(CGM);
1365 FunctionArgList Args;
1366 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1367 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1368 Args.push_back(&Dst);
1369
1370 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1371 CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(),
1372 /*isVariadic=*/false);
1373 auto FTy = CGM.getTypes().GetFunctionType(FI);
1374 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001375 FTy, ".__kmpc_global_dtor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001376 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1377 SourceLocation());
1378 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1379 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00001380 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1381 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001382 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1383 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1384 DtorCGF.FinishFunction();
1385 Dtor = Fn;
1386 }
1387 // Do not emit init function if it is not required.
1388 if (!Ctor && !Dtor)
1389 return nullptr;
1390
1391 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1392 auto CopyCtorTy =
1393 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1394 /*isVarArg=*/false)->getPointerTo();
1395 // Copying constructor for the threadprivate variable.
1396 // Must be NULL - reserved by runtime, but currently it requires that this
1397 // parameter is always NULL. Otherwise it fires assertion.
1398 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1399 if (Ctor == nullptr) {
1400 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1401 /*isVarArg=*/false)->getPointerTo();
1402 Ctor = llvm::Constant::getNullValue(CtorTy);
1403 }
1404 if (Dtor == nullptr) {
1405 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1406 /*isVarArg=*/false)->getPointerTo();
1407 Dtor = llvm::Constant::getNullValue(DtorTy);
1408 }
1409 if (!CGF) {
1410 auto InitFunctionTy =
1411 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1412 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001413 InitFunctionTy, ".__omp_threadprivate_init_.",
1414 CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00001415 CodeGenFunction InitCGF(CGM);
1416 FunctionArgList ArgList;
1417 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1418 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1419 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001420 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001421 InitCGF.FinishFunction();
1422 return InitFunction;
1423 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001424 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001425 }
1426 return nullptr;
1427}
1428
Alexey Bataev1d677132015-04-22 13:57:31 +00001429/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1430/// function. Here is the logic:
1431/// if (Cond) {
1432/// ThenGen();
1433/// } else {
1434/// ElseGen();
1435/// }
1436static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1437 const RegionCodeGenTy &ThenGen,
1438 const RegionCodeGenTy &ElseGen) {
1439 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1440
1441 // If the condition constant folds and can be elided, try to avoid emitting
1442 // the condition and the dead arm of the if/else.
1443 bool CondConstant;
1444 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
1445 CodeGenFunction::RunCleanupsScope Scope(CGF);
1446 if (CondConstant) {
1447 ThenGen(CGF);
1448 } else {
1449 ElseGen(CGF);
1450 }
1451 return;
1452 }
1453
1454 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1455 // emit the conditional branch.
1456 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1457 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1458 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1459 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1460
1461 // Emit the 'then' code.
1462 CGF.EmitBlock(ThenBlock);
1463 {
1464 CodeGenFunction::RunCleanupsScope ThenScope(CGF);
1465 ThenGen(CGF);
1466 }
1467 CGF.EmitBranch(ContBlock);
1468 // Emit the 'else' code if present.
1469 {
1470 // There is no need to emit line number for unconditional branch.
1471 auto NL = ApplyDebugLocation::CreateEmpty(CGF);
1472 CGF.EmitBlock(ElseBlock);
1473 }
1474 {
1475 CodeGenFunction::RunCleanupsScope ThenScope(CGF);
1476 ElseGen(CGF);
1477 }
1478 {
1479 // There is no need to emit line number for unconditional branch.
1480 auto NL = ApplyDebugLocation::CreateEmpty(CGF);
1481 CGF.EmitBranch(ContBlock);
1482 }
1483 // Emit the continuation block for code after the if.
1484 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001485}
1486
Alexey Bataev1d677132015-04-22 13:57:31 +00001487void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1488 llvm::Value *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001489 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00001490 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001491 if (!CGF.HaveInsertPoint())
1492 return;
Alexey Bataev1d677132015-04-22 13:57:31 +00001493 auto *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001494 auto &&ThenGen = [this, OutlinedFn, CapturedVars,
1495 RTLoc](CodeGenFunction &CGF) {
1496 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
1497 llvm::Value *Args[] = {
1498 RTLoc,
1499 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
1500 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
1501 llvm::SmallVector<llvm::Value *, 16> RealArgs;
1502 RealArgs.append(std::begin(Args), std::end(Args));
1503 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1504
1505 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
1506 CGF.EmitRuntimeCall(RTLFn, RealArgs);
1507 };
1508 auto &&ElseGen = [this, OutlinedFn, CapturedVars, RTLoc,
1509 Loc](CodeGenFunction &CGF) {
Alexey Bataev1d677132015-04-22 13:57:31 +00001510 auto ThreadID = getThreadID(CGF, Loc);
1511 // Build calls:
1512 // __kmpc_serialized_parallel(&Loc, GTid);
1513 llvm::Value *Args[] = {RTLoc, ThreadID};
1514 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel),
1515 Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001516
Alexey Bataev1d677132015-04-22 13:57:31 +00001517 // OutlinedFn(&GTid, &zero, CapturedStruct);
1518 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00001519 Address ZeroAddr =
1520 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
1521 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00001522 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00001523 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
1524 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
1525 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1526 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev1d677132015-04-22 13:57:31 +00001527 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001528
Alexey Bataev1d677132015-04-22 13:57:31 +00001529 // __kmpc_end_serialized_parallel(&Loc, GTid);
1530 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID};
1531 CGF.EmitRuntimeCall(
1532 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs);
1533 };
1534 if (IfCond) {
1535 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
1536 } else {
1537 CodeGenFunction::RunCleanupsScope Scope(CGF);
1538 ThenGen(CGF);
1539 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001540}
1541
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001542// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001543// thread-ID variable (it is passed in a first argument of the outlined function
1544// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1545// regular serial code region, get thread ID by calling kmp_int32
1546// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1547// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00001548Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
1549 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00001550 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001551 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001552 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001553 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001554
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001555 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001556 auto Int32Ty =
1557 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1558 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1559 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00001560 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00001561
1562 return ThreadIDTemp;
1563}
1564
Alexey Bataev97720002014-11-11 04:05:39 +00001565llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001566CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001567 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001568 SmallString<256> Buffer;
1569 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001570 Out << Name;
1571 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001572 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1573 if (Elem.second) {
1574 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001575 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001576 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001577 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001578
David Blaikie13156b62014-11-19 03:06:06 +00001579 return Elem.second = new llvm::GlobalVariable(
1580 CGM.getModule(), Ty, /*IsConstant*/ false,
1581 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1582 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001583}
1584
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001585llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001586 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001587 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001588}
1589
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001590namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00001591template <size_t N> class CallEndCleanup final : public EHScopeStack::Cleanup {
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001592 llvm::Value *Callee;
Alexey Bataeva744ff52015-05-05 09:24:37 +00001593 llvm::Value *Args[N];
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001594
1595public:
Alexey Bataeva744ff52015-05-05 09:24:37 +00001596 CallEndCleanup(llvm::Value *Callee, ArrayRef<llvm::Value *> CleanupArgs)
1597 : Callee(Callee) {
1598 assert(CleanupArgs.size() == N);
1599 std::copy(CleanupArgs.begin(), CleanupArgs.end(), std::begin(Args));
1600 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001601
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001602 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001603 if (!CGF.HaveInsertPoint())
1604 return;
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001605 CGF.EmitRuntimeCall(Callee, Args);
1606 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001607};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001608} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001609
1610void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1611 StringRef CriticalName,
1612 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00001613 SourceLocation Loc, const Expr *Hint) {
1614 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001615 // CriticalOpGen();
1616 // __kmpc_end_critical(ident_t *, gtid, Lock);
1617 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00001618 if (!CGF.HaveInsertPoint())
1619 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00001620 CodeGenFunction::RunCleanupsScope Scope(CGF);
1621 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1622 getCriticalRegionLock(CriticalName)};
1623 if (Hint) {
1624 llvm::SmallVector<llvm::Value *, 8> ArgsWithHint(std::begin(Args),
1625 std::end(Args));
1626 auto *HintVal = CGF.EmitScalarExpr(Hint);
1627 ArgsWithHint.push_back(
1628 CGF.Builder.CreateIntCast(HintVal, CGM.IntPtrTy, /*isSigned=*/false));
1629 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical_with_hint),
1630 ArgsWithHint);
1631 } else
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001632 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
Alexey Bataevfc57d162015-12-15 10:55:09 +00001633 // Build a call to __kmpc_end_critical
1634 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
1635 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
1636 llvm::makeArrayRef(Args));
1637 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001638}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001639
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001640static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001641 OpenMPDirectiveKind Kind, SourceLocation Loc,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001642 const RegionCodeGenTy &BodyOpGen) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001643 llvm::Value *CallBool = CGF.EmitScalarConversion(
1644 IfCond,
1645 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001646 CGF.getContext().BoolTy, Loc);
Alexey Bataev8d690652014-12-04 07:23:53 +00001647
1648 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1649 auto *ContBlock = CGF.createBasicBlock("omp_if.end");
1650 // Generate the branch (If-stmt)
1651 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1652 CGF.EmitBlock(ThenBlock);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001653 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen);
Alexey Bataev8d690652014-12-04 07:23:53 +00001654 // Emit the rest of bblocks/branches
1655 CGF.EmitBranch(ContBlock);
1656 CGF.EmitBlock(ContBlock, true);
1657}
1658
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001659void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001660 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001661 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001662 if (!CGF.HaveInsertPoint())
1663 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00001664 // if(__kmpc_master(ident_t *, gtid)) {
1665 // MasterOpGen();
1666 // __kmpc_end_master(ident_t *, gtid);
1667 // }
1668 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001669 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001670 auto *IsMaster =
1671 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
Alexey Bataeva744ff52015-05-05 09:24:37 +00001672 typedef CallEndCleanup<std::extent<decltype(Args)>::value>
1673 MasterCallEndCleanup;
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001674 emitIfStmt(
1675 CGF, IsMaster, OMPD_master, Loc, [&](CodeGenFunction &CGF) -> void {
1676 CodeGenFunction::RunCleanupsScope Scope(CGF);
1677 CGF.EHStack.pushCleanup<MasterCallEndCleanup>(
1678 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
1679 llvm::makeArrayRef(Args));
1680 MasterOpGen(CGF);
1681 });
Alexey Bataev8d690652014-12-04 07:23:53 +00001682}
1683
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001684void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
1685 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001686 if (!CGF.HaveInsertPoint())
1687 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00001688 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
1689 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001690 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00001691 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001692 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev9f797f32015-02-05 05:57:51 +00001693}
1694
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001695void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
1696 const RegionCodeGenTy &TaskgroupOpGen,
1697 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001698 if (!CGF.HaveInsertPoint())
1699 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001700 // __kmpc_taskgroup(ident_t *, gtid);
1701 // TaskgroupOpGen();
1702 // __kmpc_end_taskgroup(ident_t *, gtid);
1703 // Prepare arguments and build a call to __kmpc_taskgroup
1704 {
1705 CodeGenFunction::RunCleanupsScope Scope(CGF);
1706 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1707 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args);
1708 // Build a call to __kmpc_end_taskgroup
1709 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
1710 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
1711 llvm::makeArrayRef(Args));
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001712 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001713 }
1714}
1715
John McCall7f416cc2015-09-08 08:05:57 +00001716/// Given an array of pointers to variables, project the address of a
1717/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001718static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
1719 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00001720 // Pull out the pointer to the variable.
1721 Address PtrAddr =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001722 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00001723 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
1724
1725 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001726 Addr = CGF.Builder.CreateElementBitCast(
1727 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00001728 return Addr;
1729}
1730
Alexey Bataeva63048e2015-03-23 06:18:07 +00001731static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00001732 CodeGenModule &CGM, llvm::Type *ArgsType,
1733 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
1734 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00001735 auto &C = CGM.getContext();
1736 // void copy_func(void *LHSArg, void *RHSArg);
1737 FunctionArgList Args;
1738 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1739 C.VoidPtrTy);
1740 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1741 C.VoidPtrTy);
1742 Args.push_back(&LHSArg);
1743 Args.push_back(&RHSArg);
1744 FunctionType::ExtInfo EI;
1745 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1746 C.VoidTy, Args, EI, /*isVariadic=*/false);
1747 auto *Fn = llvm::Function::Create(
1748 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
1749 ".omp.copyprivate.copy_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00001750 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001751 CodeGenFunction CGF(CGM);
1752 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00001753 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001754 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00001755 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1756 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
1757 ArgsType), CGF.getPointerAlign());
1758 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1759 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
1760 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00001761 // *(Type0*)Dst[0] = *(Type0*)Src[0];
1762 // *(Type1*)Dst[1] = *(Type1*)Src[1];
1763 // ...
1764 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00001765 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00001766 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
1767 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
1768
1769 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
1770 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
1771
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001772 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
1773 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00001774 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001775 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001776 CGF.FinishFunction();
1777 return Fn;
1778}
1779
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001780void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001781 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001782 SourceLocation Loc,
1783 ArrayRef<const Expr *> CopyprivateVars,
1784 ArrayRef<const Expr *> SrcExprs,
1785 ArrayRef<const Expr *> DstExprs,
1786 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001787 if (!CGF.HaveInsertPoint())
1788 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00001789 assert(CopyprivateVars.size() == SrcExprs.size() &&
1790 CopyprivateVars.size() == DstExprs.size() &&
1791 CopyprivateVars.size() == AssignmentOps.size());
1792 auto &C = CGM.getContext();
1793 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001794 // if(__kmpc_single(ident_t *, gtid)) {
1795 // SingleOpGen();
1796 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001797 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001798 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001799 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1800 // <copy_func>, did_it);
1801
John McCall7f416cc2015-09-08 08:05:57 +00001802 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00001803 if (!CopyprivateVars.empty()) {
1804 // int32 did_it = 0;
1805 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1806 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00001807 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001808 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001809 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001810 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001811 auto *IsSingle =
1812 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
Alexey Bataeva744ff52015-05-05 09:24:37 +00001813 typedef CallEndCleanup<std::extent<decltype(Args)>::value>
1814 SingleCallEndCleanup;
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001815 emitIfStmt(
1816 CGF, IsSingle, OMPD_single, Loc, [&](CodeGenFunction &CGF) -> void {
1817 CodeGenFunction::RunCleanupsScope Scope(CGF);
1818 CGF.EHStack.pushCleanup<SingleCallEndCleanup>(
1819 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
1820 llvm::makeArrayRef(Args));
1821 SingleOpGen(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00001822 if (DidIt.isValid()) {
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001823 // did_it = 1;
John McCall7f416cc2015-09-08 08:05:57 +00001824 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001825 }
1826 });
Alexey Bataeva63048e2015-03-23 06:18:07 +00001827 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1828 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00001829 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00001830 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
1831 auto CopyprivateArrayTy =
1832 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
1833 /*IndexTypeQuals=*/0);
1834 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00001835 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00001836 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
1837 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00001838 Address Elem = CGF.Builder.CreateConstArrayGEP(
1839 CopyprivateList, I, CGF.getPointerSize());
1840 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00001841 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00001842 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
1843 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001844 }
1845 // Build function that copies private values from single region to all other
1846 // threads in the corresponding parallel region.
1847 auto *CpyFn = emitCopyprivateCopyFunction(
1848 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00001849 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataev1189bd02016-01-26 12:20:39 +00001850 auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00001851 Address CL =
1852 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
1853 CGF.VoidPtrTy);
1854 auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001855 llvm::Value *Args[] = {
1856 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
1857 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00001858 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00001859 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00001860 CpyFn, // void (*) (void *, void *) <copy_func>
1861 DidItVal // i32 did_it
1862 };
1863 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
1864 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001865}
1866
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001867void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
1868 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00001869 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001870 if (!CGF.HaveInsertPoint())
1871 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001872 // __kmpc_ordered(ident_t *, gtid);
1873 // OrderedOpGen();
1874 // __kmpc_end_ordered(ident_t *, gtid);
1875 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00001876 CodeGenFunction::RunCleanupsScope Scope(CGF);
1877 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001878 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1879 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_ordered), Args);
1880 // Build a call to __kmpc_end_ordered
Alexey Bataeva744ff52015-05-05 09:24:37 +00001881 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001882 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered),
1883 llvm::makeArrayRef(Args));
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001884 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00001885 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001886}
1887
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001888void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev25e5b442015-09-15 12:52:43 +00001889 OpenMPDirectiveKind Kind, bool EmitChecks,
1890 bool ForceSimpleCall) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001891 if (!CGF.HaveInsertPoint())
1892 return;
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001893 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001894 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataev50b3c952016-02-19 10:38:26 +00001895 unsigned Flags;
1896 if (Kind == OMPD_for)
1897 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
1898 else if (Kind == OMPD_sections)
1899 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
1900 else if (Kind == OMPD_single)
1901 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
1902 else if (Kind == OMPD_barrier)
1903 Flags = OMP_IDENT_BARRIER_EXPL;
1904 else
1905 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001906 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
1907 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001908 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
1909 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00001910 if (auto *OMPRegionInfo =
1911 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00001912 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001913 auto *Result = CGF.EmitRuntimeCall(
1914 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001915 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001916 // if (__kmpc_cancel_barrier()) {
1917 // exit from construct;
1918 // }
1919 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
1920 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
1921 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
1922 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
1923 CGF.EmitBlock(ExitBB);
1924 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00001925 auto CancelDestination =
1926 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001927 CGF.EmitBranchThroughCleanup(CancelDestination);
1928 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
1929 }
1930 return;
1931 }
1932 }
1933 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001934}
1935
Alexander Musmanc6388682014-12-15 07:07:06 +00001936/// \brief Map the OpenMP loop schedule to the runtime enumeration.
1937static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001938 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001939 switch (ScheduleKind) {
1940 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001941 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
1942 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00001943 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001944 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00001945 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001946 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00001947 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001948 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
1949 case OMPC_SCHEDULE_auto:
1950 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00001951 case OMPC_SCHEDULE_unknown:
1952 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001953 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00001954 }
1955 llvm_unreachable("Unexpected runtime schedule");
1956}
1957
1958bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
1959 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001960 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00001961 return Schedule == OMP_sch_static;
1962}
1963
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001964bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001965 auto Schedule =
1966 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001967 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
1968 return Schedule != OMP_sch_static;
1969}
1970
John McCall7f416cc2015-09-08 08:05:57 +00001971void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
1972 SourceLocation Loc,
1973 OpenMPScheduleClauseKind ScheduleKind,
1974 unsigned IVSize, bool IVSigned,
1975 bool Ordered, llvm::Value *UB,
1976 llvm::Value *Chunk) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001977 if (!CGF.HaveInsertPoint())
1978 return;
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001979 OpenMPSchedType Schedule =
1980 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00001981 assert(Ordered ||
1982 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
1983 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
1984 // Call __kmpc_dispatch_init(
1985 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
1986 // kmp_int[32|64] lower, kmp_int[32|64] upper,
1987 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00001988
John McCall7f416cc2015-09-08 08:05:57 +00001989 // If the Chunk was not specified in the clause - use default value 1.
1990 if (Chunk == nullptr)
1991 Chunk = CGF.Builder.getIntN(IVSize, 1);
1992 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00001993 emitUpdateLocation(CGF, Loc),
1994 getThreadID(CGF, Loc),
1995 CGF.Builder.getInt32(Schedule), // Schedule type
1996 CGF.Builder.getIntN(IVSize, 0), // Lower
1997 UB, // Upper
1998 CGF.Builder.getIntN(IVSize, 1), // Stride
1999 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00002000 };
2001 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
2002}
2003
2004void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
2005 SourceLocation Loc,
2006 OpenMPScheduleClauseKind ScheduleKind,
2007 unsigned IVSize, bool IVSigned,
2008 bool Ordered, Address IL, Address LB,
2009 Address UB, Address ST,
2010 llvm::Value *Chunk) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002011 if (!CGF.HaveInsertPoint())
2012 return;
John McCall7f416cc2015-09-08 08:05:57 +00002013 OpenMPSchedType Schedule =
2014 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
2015 assert(!Ordered);
2016 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2017 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked);
2018
2019 // Call __kmpc_for_static_init(
2020 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
2021 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
2022 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
2023 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
2024 if (Chunk == nullptr) {
2025 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static) &&
2026 "expected static non-chunked schedule");
Alexander Musman92bdaab2015-03-12 13:37:50 +00002027 // If the Chunk was not specified in the clause - use default value 1.
Alexander Musman92bdaab2015-03-12 13:37:50 +00002028 Chunk = CGF.Builder.getIntN(IVSize, 1);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002029 } else {
John McCall7f416cc2015-09-08 08:05:57 +00002030 assert((Schedule == OMP_sch_static_chunked ||
2031 Schedule == OMP_ord_static_chunked) &&
2032 "expected static chunked schedule");
Alexander Musman92bdaab2015-03-12 13:37:50 +00002033 }
John McCall7f416cc2015-09-08 08:05:57 +00002034 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002035 emitUpdateLocation(CGF, Loc),
2036 getThreadID(CGF, Loc),
2037 CGF.Builder.getInt32(Schedule), // Schedule type
2038 IL.getPointer(), // &isLastIter
2039 LB.getPointer(), // &LB
2040 UB.getPointer(), // &UB
2041 ST.getPointer(), // &Stride
2042 CGF.Builder.getIntN(IVSize, 1), // Incr
2043 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00002044 };
2045 CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00002046}
2047
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002048void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
2049 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002050 if (!CGF.HaveInsertPoint())
2051 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00002052 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002053 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002054 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
2055 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00002056}
2057
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002058void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
2059 SourceLocation Loc,
2060 unsigned IVSize,
2061 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002062 if (!CGF.HaveInsertPoint())
2063 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002064 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002065 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002066 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
2067}
2068
Alexander Musman92bdaab2015-03-12 13:37:50 +00002069llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
2070 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00002071 bool IVSigned, Address IL,
2072 Address LB, Address UB,
2073 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002074 // Call __kmpc_dispatch_next(
2075 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2076 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2077 // kmp_int[32|64] *p_stride);
2078 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002079 emitUpdateLocation(CGF, Loc),
2080 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002081 IL.getPointer(), // &isLastIter
2082 LB.getPointer(), // &Lower
2083 UB.getPointer(), // &Upper
2084 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00002085 };
2086 llvm::Value *Call =
2087 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
2088 return CGF.EmitScalarConversion(
2089 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00002090 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002091}
2092
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002093void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
2094 llvm::Value *NumThreads,
2095 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002096 if (!CGF.HaveInsertPoint())
2097 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00002098 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
2099 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002100 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00002101 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002102 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
2103 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00002104}
2105
Alexey Bataev7f210c62015-06-18 13:40:03 +00002106void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
2107 OpenMPProcBindClauseKind ProcBind,
2108 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002109 if (!CGF.HaveInsertPoint())
2110 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00002111 // Constants for proc bind value accepted by the runtime.
2112 enum ProcBindTy {
2113 ProcBindFalse = 0,
2114 ProcBindTrue,
2115 ProcBindMaster,
2116 ProcBindClose,
2117 ProcBindSpread,
2118 ProcBindIntel,
2119 ProcBindDefault
2120 } RuntimeProcBind;
2121 switch (ProcBind) {
2122 case OMPC_PROC_BIND_master:
2123 RuntimeProcBind = ProcBindMaster;
2124 break;
2125 case OMPC_PROC_BIND_close:
2126 RuntimeProcBind = ProcBindClose;
2127 break;
2128 case OMPC_PROC_BIND_spread:
2129 RuntimeProcBind = ProcBindSpread;
2130 break;
2131 case OMPC_PROC_BIND_unknown:
2132 llvm_unreachable("Unsupported proc_bind value.");
2133 }
2134 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
2135 llvm::Value *Args[] = {
2136 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2137 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
2138 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
2139}
2140
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002141void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
2142 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002143 if (!CGF.HaveInsertPoint())
2144 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00002145 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002146 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
2147 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00002148}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002149
Alexey Bataev62b63b12015-03-10 07:28:44 +00002150namespace {
2151/// \brief Indexes of fields for type kmp_task_t.
2152enum KmpTaskTFields {
2153 /// \brief List of shared variables.
2154 KmpTaskTShareds,
2155 /// \brief Task routine.
2156 KmpTaskTRoutine,
2157 /// \brief Partition id for the untied tasks.
2158 KmpTaskTPartId,
2159 /// \brief Function with call of destructors for private variables.
2160 KmpTaskTDestructors,
2161};
Hans Wennborg7eb54642015-09-10 17:07:54 +00002162} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00002163
Samuel Antaoee8fb302016-01-06 13:42:12 +00002164bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
2165 // FIXME: Add other entries type when they become supported.
2166 return OffloadEntriesTargetRegion.empty();
2167}
2168
2169/// \brief Initialize target region entry.
2170void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2171 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2172 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002173 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002174 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
2175 "only required for the device "
2176 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002177 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002178 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr);
2179 ++OffloadingEntriesNum;
2180}
2181
2182void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2183 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2184 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002185 llvm::Constant *Addr, llvm::Constant *ID) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002186 // If we are emitting code for a target, the entry is already initialized,
2187 // only has to be registered.
2188 if (CGM.getLangOpts().OpenMPIsDevice) {
Samuel Antao2de62b02016-02-13 23:35:10 +00002189 assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) &&
Samuel Antaoee8fb302016-01-06 13:42:12 +00002190 "Entry must exist.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002191 auto &Entry =
2192 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00002193 assert(Entry.isValid() && "Entry not initialized!");
2194 Entry.setAddress(Addr);
2195 Entry.setID(ID);
2196 return;
2197 } else {
2198 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID);
Samuel Antao2de62b02016-02-13 23:35:10 +00002199 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002200 }
2201}
2202
2203bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00002204 unsigned DeviceID, unsigned FileID, StringRef ParentName,
2205 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002206 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
2207 if (PerDevice == OffloadEntriesTargetRegion.end())
2208 return false;
2209 auto PerFile = PerDevice->second.find(FileID);
2210 if (PerFile == PerDevice->second.end())
2211 return false;
2212 auto PerParentName = PerFile->second.find(ParentName);
2213 if (PerParentName == PerFile->second.end())
2214 return false;
2215 auto PerLine = PerParentName->second.find(LineNum);
2216 if (PerLine == PerParentName->second.end())
2217 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002218 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00002219 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00002220 return false;
2221 return true;
2222}
2223
2224void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
2225 const OffloadTargetRegionEntryInfoActTy &Action) {
2226 // Scan all target region entries and perform the provided action.
2227 for (auto &D : OffloadEntriesTargetRegion)
2228 for (auto &F : D.second)
2229 for (auto &P : F.second)
2230 for (auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00002231 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002232}
2233
2234/// \brief Create a Ctor/Dtor-like function whose body is emitted through
2235/// \a Codegen. This is used to emit the two functions that register and
2236/// unregister the descriptor of the current compilation unit.
2237static llvm::Function *
2238createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
2239 const RegionCodeGenTy &Codegen) {
2240 auto &C = CGM.getContext();
2241 FunctionArgList Args;
2242 ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(),
2243 /*Id=*/nullptr, C.VoidPtrTy);
2244 Args.push_back(&DummyPtr);
2245
2246 CodeGenFunction CGF(CGM);
2247 GlobalDecl();
2248 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
2249 C.VoidTy, Args, FunctionType::ExtInfo(),
2250 /*isVariadic=*/false);
2251 auto FTy = CGM.getTypes().GetFunctionType(FI);
2252 auto *Fn =
2253 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation());
2254 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation());
2255 Codegen(CGF);
2256 CGF.FinishFunction();
2257 return Fn;
2258}
2259
2260llvm::Function *
2261CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
2262
2263 // If we don't have entries or if we are emitting code for the device, we
2264 // don't need to do anything.
2265 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
2266 return nullptr;
2267
2268 auto &M = CGM.getModule();
2269 auto &C = CGM.getContext();
2270
2271 // Get list of devices we care about
2272 auto &Devices = CGM.getLangOpts().OMPTargetTriples;
2273
2274 // We should be creating an offloading descriptor only if there are devices
2275 // specified.
2276 assert(!Devices.empty() && "No OpenMP offloading devices??");
2277
2278 // Create the external variables that will point to the begin and end of the
2279 // host entries section. These will be defined by the linker.
2280 auto *OffloadEntryTy =
2281 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
2282 llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable(
2283 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002284 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002285 ".omp_offloading.entries_begin");
2286 llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable(
2287 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002288 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002289 ".omp_offloading.entries_end");
2290
2291 // Create all device images
2292 llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires;
2293 auto *DeviceImageTy = cast<llvm::StructType>(
2294 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
2295
2296 for (unsigned i = 0; i < Devices.size(); ++i) {
2297 StringRef T = Devices[i].getTriple();
2298 auto *ImgBegin = new llvm::GlobalVariable(
2299 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002300 /*Initializer=*/nullptr,
2301 Twine(".omp_offloading.img_start.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002302 auto *ImgEnd = new llvm::GlobalVariable(
2303 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002304 /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002305
2306 llvm::Constant *Dev =
2307 llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd,
2308 HostEntriesBegin, HostEntriesEnd, nullptr);
2309 DeviceImagesEntires.push_back(Dev);
2310 }
2311
2312 // Create device images global array.
2313 llvm::ArrayType *DeviceImagesInitTy =
2314 llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size());
2315 llvm::Constant *DeviceImagesInit =
2316 llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires);
2317
2318 llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable(
2319 M, DeviceImagesInitTy, /*isConstant=*/true,
2320 llvm::GlobalValue::InternalLinkage, DeviceImagesInit,
2321 ".omp_offloading.device_images");
2322 DeviceImages->setUnnamedAddr(true);
2323
2324 // This is a Zero array to be used in the creation of the constant expressions
2325 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
2326 llvm::Constant::getNullValue(CGM.Int32Ty)};
2327
2328 // Create the target region descriptor.
2329 auto *BinaryDescriptorTy = cast<llvm::StructType>(
2330 CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
2331 llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get(
2332 BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
2333 llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages,
2334 Index),
2335 HostEntriesBegin, HostEntriesEnd, nullptr);
2336
2337 auto *Desc = new llvm::GlobalVariable(
2338 M, BinaryDescriptorTy, /*isConstant=*/true,
2339 llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit,
2340 ".omp_offloading.descriptor");
2341
2342 // Emit code to register or unregister the descriptor at execution
2343 // startup or closing, respectively.
2344
2345 // Create a variable to drive the registration and unregistration of the
2346 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
2347 auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var");
2348 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(),
2349 IdentInfo, C.CharTy);
2350
2351 auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
2352 CGM, ".omp_offloading.descriptor_unreg", [&](CodeGenFunction &CGF) {
2353 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
2354 Desc);
2355 });
2356 auto *RegFn = createOffloadingBinaryDescriptorFunction(
2357 CGM, ".omp_offloading.descriptor_reg", [&](CodeGenFunction &CGF) {
2358 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib),
2359 Desc);
2360 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
2361 });
2362 return RegFn;
2363}
2364
Samuel Antao2de62b02016-02-13 23:35:10 +00002365void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID,
2366 llvm::Constant *Addr, uint64_t Size) {
2367 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00002368 auto *TgtOffloadEntryType = cast<llvm::StructType>(
2369 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()));
2370 llvm::LLVMContext &C = CGM.getModule().getContext();
2371 llvm::Module &M = CGM.getModule();
2372
2373 // Make sure the address has the right type.
Samuel Antao2de62b02016-02-13 23:35:10 +00002374 llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002375
2376 // Create constant string with the name.
2377 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
2378
2379 llvm::GlobalVariable *Str =
2380 new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true,
2381 llvm::GlobalValue::InternalLinkage, StrPtrInit,
2382 ".omp_offloading.entry_name");
2383 Str->setUnnamedAddr(true);
2384 llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy);
2385
2386 // Create the entry struct.
2387 llvm::Constant *EntryInit = llvm::ConstantStruct::get(
2388 TgtOffloadEntryType, AddrPtr, StrPtr,
2389 llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr);
2390 llvm::GlobalVariable *Entry = new llvm::GlobalVariable(
2391 M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage,
2392 EntryInit, ".omp_offloading.entry");
2393
2394 // The entry has to be created in the section the linker expects it to be.
2395 Entry->setSection(".omp_offloading.entries");
2396 // We can't have any padding between symbols, so we need to have 1-byte
2397 // alignment.
2398 Entry->setAlignment(1);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002399}
2400
2401void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
2402 // Emit the offloading entries and metadata so that the device codegen side
2403 // can
2404 // easily figure out what to emit. The produced metadata looks like this:
2405 //
2406 // !omp_offload.info = !{!1, ...}
2407 //
2408 // Right now we only generate metadata for function that contain target
2409 // regions.
2410
2411 // If we do not have entries, we dont need to do anything.
2412 if (OffloadEntriesInfoManager.empty())
2413 return;
2414
2415 llvm::Module &M = CGM.getModule();
2416 llvm::LLVMContext &C = M.getContext();
2417 SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
2418 OrderedEntries(OffloadEntriesInfoManager.size());
2419
2420 // Create the offloading info metadata node.
2421 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
2422
2423 // Auxiliar methods to create metadata values and strings.
2424 auto getMDInt = [&](unsigned v) {
2425 return llvm::ConstantAsMetadata::get(
2426 llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v));
2427 };
2428
2429 auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); };
2430
2431 // Create function that emits metadata for each target region entry;
2432 auto &&TargetRegionMetadataEmitter = [&](
2433 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002434 OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
2435 llvm::SmallVector<llvm::Metadata *, 32> Ops;
2436 // Generate metadata for target regions. Each entry of this metadata
2437 // contains:
2438 // - Entry 0 -> Kind of this type of metadata (0).
2439 // - Entry 1 -> Device ID of the file where the entry was identified.
2440 // - Entry 2 -> File ID of the file where the entry was identified.
2441 // - Entry 3 -> Mangled name of the function where the entry was identified.
2442 // - Entry 4 -> Line in the file where the entry was identified.
Samuel Antao2de62b02016-02-13 23:35:10 +00002443 // - Entry 5 -> Order the entry was created.
Samuel Antaoee8fb302016-01-06 13:42:12 +00002444 // The first element of the metadata node is the kind.
2445 Ops.push_back(getMDInt(E.getKind()));
2446 Ops.push_back(getMDInt(DeviceID));
2447 Ops.push_back(getMDInt(FileID));
2448 Ops.push_back(getMDString(ParentName));
2449 Ops.push_back(getMDInt(Line));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002450 Ops.push_back(getMDInt(E.getOrder()));
2451
2452 // Save this entry in the right position of the ordered entries array.
2453 OrderedEntries[E.getOrder()] = &E;
2454
2455 // Add metadata to the named metadata node.
2456 MD->addOperand(llvm::MDNode::get(C, Ops));
2457 };
2458
2459 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
2460 TargetRegionMetadataEmitter);
2461
2462 for (auto *E : OrderedEntries) {
2463 assert(E && "All ordered entries must exist!");
2464 if (auto *CE =
2465 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
2466 E)) {
2467 assert(CE->getID() && CE->getAddress() &&
2468 "Entry ID and Addr are invalid!");
Samuel Antao2de62b02016-02-13 23:35:10 +00002469 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002470 } else
2471 llvm_unreachable("Unsupported entry kind.");
2472 }
2473}
2474
2475/// \brief Loads all the offload entries information from the host IR
2476/// metadata.
2477void CGOpenMPRuntime::loadOffloadInfoMetadata() {
2478 // If we are in target mode, load the metadata from the host IR. This code has
2479 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
2480
2481 if (!CGM.getLangOpts().OpenMPIsDevice)
2482 return;
2483
2484 if (CGM.getLangOpts().OMPHostIRFile.empty())
2485 return;
2486
2487 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
2488 if (Buf.getError())
2489 return;
2490
2491 llvm::LLVMContext C;
2492 auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C);
2493
2494 if (ME.getError())
2495 return;
2496
2497 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
2498 if (!MD)
2499 return;
2500
2501 for (auto I : MD->operands()) {
2502 llvm::MDNode *MN = cast<llvm::MDNode>(I);
2503
2504 auto getMDInt = [&](unsigned Idx) {
2505 llvm::ConstantAsMetadata *V =
2506 cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
2507 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
2508 };
2509
2510 auto getMDString = [&](unsigned Idx) {
2511 llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx));
2512 return V->getString();
2513 };
2514
2515 switch (getMDInt(0)) {
2516 default:
2517 llvm_unreachable("Unexpected metadata!");
2518 break;
2519 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
2520 OFFLOAD_ENTRY_INFO_TARGET_REGION:
2521 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
2522 /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2),
2523 /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4),
Samuel Antao2de62b02016-02-13 23:35:10 +00002524 /*Order=*/getMDInt(5));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002525 break;
2526 }
2527 }
2528}
2529
Alexey Bataev62b63b12015-03-10 07:28:44 +00002530void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
2531 if (!KmpRoutineEntryPtrTy) {
2532 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
2533 auto &C = CGM.getContext();
2534 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
2535 FunctionProtoType::ExtProtoInfo EPI;
2536 KmpRoutineEntryPtrQTy = C.getPointerType(
2537 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2538 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
2539 }
2540}
2541
Alexey Bataevc71a4092015-09-11 10:29:41 +00002542static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
2543 QualType FieldTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002544 auto *Field = FieldDecl::Create(
2545 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
2546 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
2547 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
2548 Field->setAccess(AS_public);
2549 DC->addDecl(Field);
Alexey Bataevc71a4092015-09-11 10:29:41 +00002550 return Field;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002551}
2552
Samuel Antaoee8fb302016-01-06 13:42:12 +00002553QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
2554
2555 // Make sure the type of the entry is already created. This is the type we
2556 // have to create:
2557 // struct __tgt_offload_entry{
2558 // void *addr; // Pointer to the offload entry info.
2559 // // (function or global)
2560 // char *name; // Name of the function or global.
2561 // size_t size; // Size of the entry info (0 if it a function).
2562 // };
2563 if (TgtOffloadEntryQTy.isNull()) {
2564 ASTContext &C = CGM.getContext();
2565 auto *RD = C.buildImplicitRecord("__tgt_offload_entry");
2566 RD->startDefinition();
2567 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2568 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
2569 addFieldToRecordDecl(C, RD, C.getSizeType());
2570 RD->completeDefinition();
2571 TgtOffloadEntryQTy = C.getRecordType(RD);
2572 }
2573 return TgtOffloadEntryQTy;
2574}
2575
2576QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
2577 // These are the types we need to build:
2578 // struct __tgt_device_image{
2579 // void *ImageStart; // Pointer to the target code start.
2580 // void *ImageEnd; // Pointer to the target code end.
2581 // // We also add the host entries to the device image, as it may be useful
2582 // // for the target runtime to have access to that information.
2583 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
2584 // // the entries.
2585 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2586 // // entries (non inclusive).
2587 // };
2588 if (TgtDeviceImageQTy.isNull()) {
2589 ASTContext &C = CGM.getContext();
2590 auto *RD = C.buildImplicitRecord("__tgt_device_image");
2591 RD->startDefinition();
2592 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2593 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2594 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2595 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2596 RD->completeDefinition();
2597 TgtDeviceImageQTy = C.getRecordType(RD);
2598 }
2599 return TgtDeviceImageQTy;
2600}
2601
2602QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
2603 // struct __tgt_bin_desc{
2604 // int32_t NumDevices; // Number of devices supported.
2605 // __tgt_device_image *DeviceImages; // Arrays of device images
2606 // // (one per device).
2607 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
2608 // // entries.
2609 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2610 // // entries (non inclusive).
2611 // };
2612 if (TgtBinaryDescriptorQTy.isNull()) {
2613 ASTContext &C = CGM.getContext();
2614 auto *RD = C.buildImplicitRecord("__tgt_bin_desc");
2615 RD->startDefinition();
2616 addFieldToRecordDecl(
2617 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
2618 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
2619 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2620 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2621 RD->completeDefinition();
2622 TgtBinaryDescriptorQTy = C.getRecordType(RD);
2623 }
2624 return TgtBinaryDescriptorQTy;
2625}
2626
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002627namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00002628struct PrivateHelpersTy {
2629 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
2630 const VarDecl *PrivateElemInit)
2631 : Original(Original), PrivateCopy(PrivateCopy),
2632 PrivateElemInit(PrivateElemInit) {}
2633 const VarDecl *Original;
2634 const VarDecl *PrivateCopy;
2635 const VarDecl *PrivateElemInit;
2636};
2637typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00002638} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002639
Alexey Bataev9e034042015-05-05 04:05:12 +00002640static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00002641createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002642 if (!Privates.empty()) {
2643 auto &C = CGM.getContext();
2644 // Build struct .kmp_privates_t. {
2645 // /* private vars */
2646 // };
2647 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
2648 RD->startDefinition();
2649 for (auto &&Pair : Privates) {
Alexey Bataevc71a4092015-09-11 10:29:41 +00002650 auto *VD = Pair.second.Original;
2651 auto Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002652 Type = Type.getNonReferenceType();
Alexey Bataevc71a4092015-09-11 10:29:41 +00002653 auto *FD = addFieldToRecordDecl(C, RD, Type);
2654 if (VD->hasAttrs()) {
2655 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
2656 E(VD->getAttrs().end());
2657 I != E; ++I)
2658 FD->addAttr(*I);
2659 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002660 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002661 RD->completeDefinition();
2662 return RD;
2663 }
2664 return nullptr;
2665}
2666
Alexey Bataev9e034042015-05-05 04:05:12 +00002667static RecordDecl *
2668createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002669 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002670 auto &C = CGM.getContext();
2671 // Build struct kmp_task_t {
2672 // void * shareds;
2673 // kmp_routine_entry_t routine;
2674 // kmp_int32 part_id;
2675 // kmp_routine_entry_t destructors;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002676 // };
2677 auto *RD = C.buildImplicitRecord("kmp_task_t");
2678 RD->startDefinition();
2679 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2680 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
2681 addFieldToRecordDecl(C, RD, KmpInt32Ty);
2682 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002683 RD->completeDefinition();
2684 return RD;
2685}
2686
2687static RecordDecl *
2688createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00002689 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002690 auto &C = CGM.getContext();
2691 // Build struct kmp_task_t_with_privates {
2692 // kmp_task_t task_data;
2693 // .kmp_privates_t. privates;
2694 // };
2695 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
2696 RD->startDefinition();
2697 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002698 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
2699 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
2700 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002701 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002702 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002703}
2704
2705/// \brief Emit a proxy function which accepts kmp_task_t as the second
2706/// argument.
2707/// \code
2708/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002709/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map,
2710/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002711/// return 0;
2712/// }
2713/// \endcode
2714static llvm::Value *
2715emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002716 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
2717 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002718 QualType SharedsPtrTy, llvm::Value *TaskFunction,
2719 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002720 auto &C = CGM.getContext();
2721 FunctionArgList Args;
2722 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
2723 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002724 /*Id=*/nullptr,
2725 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002726 Args.push_back(&GtidArg);
2727 Args.push_back(&TaskTypeArg);
2728 FunctionType::ExtInfo Info;
2729 auto &TaskEntryFnInfo =
2730 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
2731 /*isVariadic=*/false);
2732 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
2733 auto *TaskEntry =
2734 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
2735 ".omp_task_entry.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002736 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002737 CodeGenFunction CGF(CGM);
2738 CGF.disableDebugInfo();
2739 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
2740
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002741 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
2742 // tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002743 auto *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002744 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00002745 LValue TDBase = CGF.EmitLoadOfPointerLValue(
2746 CGF.GetAddrOfLocalVar(&TaskTypeArg),
2747 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002748 auto *KmpTaskTWithPrivatesQTyRD =
2749 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002750 LValue Base =
2751 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002752 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
2753 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
2754 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
2755 auto *PartidParam = CGF.EmitLoadOfLValue(PartIdLVal, Loc).getScalarVal();
2756
2757 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
2758 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002759 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002760 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002761 CGF.ConvertTypeForMem(SharedsPtrTy));
2762
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002763 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
2764 llvm::Value *PrivatesParam;
2765 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
2766 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
2767 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002768 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002769 } else {
2770 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2771 }
2772
2773 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam,
2774 TaskPrivatesMap, SharedsParam};
Alexey Bataev62b63b12015-03-10 07:28:44 +00002775 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
2776 CGF.EmitStoreThroughLValue(
2777 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
John McCall7f416cc2015-09-08 08:05:57 +00002778 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00002779 CGF.FinishFunction();
2780 return TaskEntry;
2781}
2782
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002783static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
2784 SourceLocation Loc,
2785 QualType KmpInt32Ty,
2786 QualType KmpTaskTWithPrivatesPtrQTy,
2787 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002788 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002789 FunctionArgList Args;
2790 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
2791 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002792 /*Id=*/nullptr,
2793 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002794 Args.push_back(&GtidArg);
2795 Args.push_back(&TaskTypeArg);
2796 FunctionType::ExtInfo Info;
2797 auto &DestructorFnInfo =
2798 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
2799 /*isVariadic=*/false);
2800 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
2801 auto *DestructorFn =
2802 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
2803 ".omp_task_destructor.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002804 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
2805 DestructorFnInfo);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002806 CodeGenFunction CGF(CGM);
2807 CGF.disableDebugInfo();
2808 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
2809 Args);
2810
Alexey Bataev31300ed2016-02-04 11:27:03 +00002811 LValue Base = CGF.EmitLoadOfPointerLValue(
2812 CGF.GetAddrOfLocalVar(&TaskTypeArg),
2813 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002814 auto *KmpTaskTWithPrivatesQTyRD =
2815 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
2816 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002817 Base = CGF.EmitLValueForField(Base, *FI);
2818 for (auto *Field :
2819 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
2820 if (auto DtorKind = Field->getType().isDestructedType()) {
2821 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
2822 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
2823 }
2824 }
2825 CGF.FinishFunction();
2826 return DestructorFn;
2827}
2828
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002829/// \brief Emit a privates mapping function for correct handling of private and
2830/// firstprivate variables.
2831/// \code
2832/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
2833/// **noalias priv1,..., <tyn> **noalias privn) {
2834/// *priv1 = &.privates.priv1;
2835/// ...;
2836/// *privn = &.privates.privn;
2837/// }
2838/// \endcode
2839static llvm::Value *
2840emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00002841 ArrayRef<const Expr *> PrivateVars,
2842 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002843 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00002844 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002845 auto &C = CGM.getContext();
2846 FunctionArgList Args;
2847 ImplicitParamDecl TaskPrivatesArg(
2848 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
2849 C.getPointerType(PrivatesQTy).withConst().withRestrict());
2850 Args.push_back(&TaskPrivatesArg);
2851 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
2852 unsigned Counter = 1;
2853 for (auto *E: PrivateVars) {
2854 Args.push_back(ImplicitParamDecl::Create(
2855 C, /*DC=*/nullptr, Loc,
2856 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
2857 .withConst()
2858 .withRestrict()));
2859 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2860 PrivateVarsPos[VD] = Counter;
2861 ++Counter;
2862 }
2863 for (auto *E : FirstprivateVars) {
2864 Args.push_back(ImplicitParamDecl::Create(
2865 C, /*DC=*/nullptr, Loc,
2866 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
2867 .withConst()
2868 .withRestrict()));
2869 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2870 PrivateVarsPos[VD] = Counter;
2871 ++Counter;
2872 }
2873 FunctionType::ExtInfo Info;
2874 auto &TaskPrivatesMapFnInfo =
2875 CGM.getTypes().arrangeFreeFunctionDeclaration(C.VoidTy, Args, Info,
2876 /*isVariadic=*/false);
2877 auto *TaskPrivatesMapTy =
2878 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
2879 auto *TaskPrivatesMap = llvm::Function::Create(
2880 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
2881 ".omp_task_privates_map.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002882 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
2883 TaskPrivatesMapFnInfo);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00002884 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002885 CodeGenFunction CGF(CGM);
2886 CGF.disableDebugInfo();
2887 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
2888 TaskPrivatesMapFnInfo, Args);
2889
2890 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00002891 LValue Base = CGF.EmitLoadOfPointerLValue(
2892 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
2893 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002894 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
2895 Counter = 0;
2896 for (auto *Field : PrivatesQTyRD->fields()) {
2897 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
2898 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
John McCall7f416cc2015-09-08 08:05:57 +00002899 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
Alexey Bataev31300ed2016-02-04 11:27:03 +00002900 auto RefLoadLVal = CGF.EmitLoadOfPointerLValue(
2901 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00002902 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002903 ++Counter;
2904 }
2905 CGF.FinishFunction();
2906 return TaskPrivatesMap;
2907}
2908
Alexey Bataev9e034042015-05-05 04:05:12 +00002909static int array_pod_sort_comparator(const PrivateDataTy *P1,
2910 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002911 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
2912}
2913
2914void CGOpenMPRuntime::emitTaskCall(
2915 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
2916 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
John McCall7f416cc2015-09-08 08:05:57 +00002917 llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002918 const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
2919 ArrayRef<const Expr *> PrivateCopies,
2920 ArrayRef<const Expr *> FirstprivateVars,
2921 ArrayRef<const Expr *> FirstprivateCopies,
2922 ArrayRef<const Expr *> FirstprivateInits,
2923 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002924 if (!CGF.HaveInsertPoint())
2925 return;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002926 auto &C = CGM.getContext();
Alexey Bataev9e034042015-05-05 04:05:12 +00002927 llvm::SmallVector<PrivateDataTy, 8> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002928 // Aggregate privates and sort them by the alignment.
Alexey Bataev9e034042015-05-05 04:05:12 +00002929 auto I = PrivateCopies.begin();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002930 for (auto *E : PrivateVars) {
2931 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2932 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00002933 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00002934 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
2935 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002936 ++I;
2937 }
Alexey Bataev9e034042015-05-05 04:05:12 +00002938 I = FirstprivateCopies.begin();
2939 auto IElemInitRef = FirstprivateInits.begin();
2940 for (auto *E : FirstprivateVars) {
2941 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2942 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00002943 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00002944 PrivateHelpersTy(
2945 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
2946 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
Richard Trieucc3949d2016-02-18 22:34:54 +00002947 ++I;
2948 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00002949 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002950 llvm::array_pod_sort(Privates.begin(), Privates.end(),
2951 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002952 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2953 // Build type kmp_routine_entry_t (if not built yet).
2954 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002955 // Build type kmp_task_t (if not built yet).
2956 if (KmpTaskTQTy.isNull()) {
2957 KmpTaskTQTy = C.getRecordType(
2958 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
2959 }
2960 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002961 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002962 auto *KmpTaskTWithPrivatesQTyRD =
2963 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
2964 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
2965 QualType KmpTaskTWithPrivatesPtrQTy =
2966 C.getPointerType(KmpTaskTWithPrivatesQTy);
2967 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
2968 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
Alexey Bataev1189bd02016-01-26 12:20:39 +00002969 auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002970 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
2971
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002972 // Emit initial values for private copies (if any).
2973 llvm::Value *TaskPrivatesMap = nullptr;
2974 auto *TaskPrivatesMapTy =
2975 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
2976 3)
2977 ->getType();
2978 if (!Privates.empty()) {
2979 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
2980 TaskPrivatesMap = emitTaskPrivateMappingFunction(
2981 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
2982 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2983 TaskPrivatesMap, TaskPrivatesMapTy);
2984 } else {
2985 TaskPrivatesMap = llvm::ConstantPointerNull::get(
2986 cast<llvm::PointerType>(TaskPrivatesMapTy));
2987 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002988 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
2989 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002990 auto *TaskEntry = emitProxyTaskFunction(
2991 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002992 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002993
2994 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
2995 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2996 // kmp_routine_entry_t *task_entry);
2997 // Task flags. Format is taken from
2998 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
2999 // description of kmp_tasking_flags struct.
3000 const unsigned TiedFlag = 0x1;
3001 const unsigned FinalFlag = 0x2;
3002 unsigned Flags = Tied ? TiedFlag : 0;
3003 auto *TaskFlags =
3004 Final.getPointer()
3005 ? CGF.Builder.CreateSelect(Final.getPointer(),
3006 CGF.Builder.getInt32(FinalFlag),
3007 CGF.Builder.getInt32(/*C=*/0))
3008 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
3009 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataev40e36f12015-11-24 13:01:44 +00003010 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003011 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
3012 getThreadID(CGF, Loc), TaskFlags,
3013 KmpTaskTWithPrivatesTySize, SharedsSize,
3014 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3015 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003016 auto *NewTask = CGF.EmitRuntimeCall(
3017 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003018 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3019 NewTask, KmpTaskTWithPrivatesPtrTy);
3020 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
3021 KmpTaskTWithPrivatesQTy);
3022 LValue TDBase =
3023 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003024 // Fill the data in the resulting kmp_task_t record.
3025 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00003026 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003027 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003028 KmpTaskSharedsPtr =
3029 Address(CGF.EmitLoadOfScalar(
3030 CGF.EmitLValueForField(
3031 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
3032 KmpTaskTShareds)),
3033 Loc),
3034 CGF.getNaturalTypeAlignment(SharedsTy));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003035 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003036 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003037 // Emit initial values for private copies (if any).
3038 bool NeedsCleanup = false;
3039 if (!Privates.empty()) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003040 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3041 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003042 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003043 LValue SharedsBase;
3044 if (!FirstprivateVars.empty()) {
John McCall7f416cc2015-09-08 08:05:57 +00003045 SharedsBase = CGF.MakeAddrLValue(
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003046 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3047 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
3048 SharedsTy);
3049 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003050 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
3051 cast<CapturedStmt>(*D.getAssociatedStmt()));
3052 for (auto &&Pair : Privates) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003053 auto *VD = Pair.second.PrivateCopy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003054 auto *Init = VD->getAnyInitializer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003055 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003056 if (Init) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003057 if (auto *Elem = Pair.second.PrivateElemInit) {
3058 auto *OriginalVD = Pair.second.Original;
3059 auto *SharedField = CapturesInfo.lookup(OriginalVD);
3060 auto SharedRefLValue =
3061 CGF.EmitLValueForField(SharedsBase, SharedField);
Alexey Bataevc71a4092015-09-11 10:29:41 +00003062 SharedRefLValue = CGF.MakeAddrLValue(
3063 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
3064 SharedRefLValue.getType(), AlignmentSource::Decl);
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003065 QualType Type = OriginalVD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003066 if (Type->isArrayType()) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003067 // Initialize firstprivate array.
3068 if (!isa<CXXConstructExpr>(Init) ||
3069 CGF.isTrivialInitializer(Init)) {
3070 // Perform simple memcpy.
3071 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003072 SharedRefLValue.getAddress(), Type);
Alexey Bataev9e034042015-05-05 04:05:12 +00003073 } else {
3074 // Initialize firstprivate array using element-by-element
3075 // intialization.
3076 CGF.EmitOMPAggregateAssign(
3077 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003078 Type, [&CGF, Elem, Init, &CapturesInfo](
John McCall7f416cc2015-09-08 08:05:57 +00003079 Address DestElement, Address SrcElement) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003080 // Clean up any temporaries needed by the initialization.
3081 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003082 InitScope.addPrivate(Elem, [SrcElement]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003083 return SrcElement;
3084 });
3085 (void)InitScope.Privatize();
3086 // Emit initialization for single element.
Alexey Bataevd157d472015-06-24 03:35:38 +00003087 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3088 CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003089 CGF.EmitAnyExprToMem(Init, DestElement,
3090 Init->getType().getQualifiers(),
3091 /*IsInitializer=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003092 });
3093 }
3094 } else {
3095 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003096 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003097 return SharedRefLValue.getAddress();
3098 });
3099 (void)InitScope.Privatize();
Alexey Bataevd157d472015-06-24 03:35:38 +00003100 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003101 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
3102 /*capturedByInit=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003103 }
3104 } else {
3105 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
3106 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003107 }
3108 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003109 ++FI;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003110 }
3111 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003112 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003113 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003114 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
3115 KmpTaskTWithPrivatesPtrQTy,
3116 KmpTaskTWithPrivatesQTy)
3117 : llvm::ConstantPointerNull::get(
3118 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
3119 LValue Destructor = CGF.EmitLValueForField(
3120 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
3121 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3122 DestructorFn, KmpRoutineEntryPtrTy),
3123 Destructor);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003124
3125 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00003126 Address DependenciesArray = Address::invalid();
3127 unsigned NumDependencies = Dependences.size();
3128 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003129 // Dependence kind for RTL.
Alexey Bataev92e82f92015-11-23 13:33:42 +00003130 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003131 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
3132 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003133 QualType FlagsTy =
3134 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003135 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
3136 if (KmpDependInfoTy.isNull()) {
3137 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
3138 KmpDependInfoRD->startDefinition();
3139 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
3140 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
3141 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
3142 KmpDependInfoRD->completeDefinition();
3143 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
3144 } else {
3145 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
3146 }
John McCall7f416cc2015-09-08 08:05:57 +00003147 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003148 // Define type kmp_depend_info[<Dependences.size()>];
3149 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00003150 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003151 ArrayType::Normal, /*IndexTypeQuals=*/0);
3152 // kmp_depend_info[<Dependences.size()>] deps;
John McCall7f416cc2015-09-08 08:05:57 +00003153 DependenciesArray = CGF.CreateMemTemp(KmpDependInfoArrayTy);
3154 for (unsigned i = 0; i < NumDependencies; ++i) {
3155 const Expr *E = Dependences[i].second;
3156 auto Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003157 llvm::Value *Size;
3158 QualType Ty = E->getType();
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003159 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
3160 LValue UpAddrLVal =
3161 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
3162 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00003163 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003164 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00003165 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003166 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
3167 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003168 } else
Alexey Bataev1189bd02016-01-26 12:20:39 +00003169 Size = CGF.getTypeSize(Ty);
John McCall7f416cc2015-09-08 08:05:57 +00003170 auto Base = CGF.MakeAddrLValue(
3171 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003172 KmpDependInfoTy);
3173 // deps[i].base_addr = &<Dependences[i].second>;
3174 auto BaseAddrLVal = CGF.EmitLValueForField(
3175 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00003176 CGF.EmitStoreOfScalar(
3177 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
3178 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003179 // deps[i].len = sizeof(<Dependences[i].second>);
3180 auto LenLVal = CGF.EmitLValueForField(
3181 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
3182 CGF.EmitStoreOfScalar(Size, LenLVal);
3183 // deps[i].flags = <Dependences[i].first>;
3184 RTLDependenceKindTy DepKind;
3185 switch (Dependences[i].first) {
3186 case OMPC_DEPEND_in:
3187 DepKind = DepIn;
3188 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00003189 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003190 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003191 case OMPC_DEPEND_inout:
3192 DepKind = DepInOut;
3193 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00003194 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00003195 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003196 case OMPC_DEPEND_unknown:
3197 llvm_unreachable("Unknown task dependence type");
3198 }
3199 auto FlagsLVal = CGF.EmitLValueForField(
3200 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
3201 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
3202 FlagsLVal);
3203 }
John McCall7f416cc2015-09-08 08:05:57 +00003204 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3205 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003206 CGF.VoidPtrTy);
3207 }
3208
Alexey Bataev62b63b12015-03-10 07:28:44 +00003209 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
3210 // libcall.
3211 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
3212 // *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003213 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
3214 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
3215 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
3216 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00003217 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003218 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00003219 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
3220 llvm::Value *DepTaskArgs[7];
3221 if (NumDependencies) {
3222 DepTaskArgs[0] = UpLoc;
3223 DepTaskArgs[1] = ThreadID;
3224 DepTaskArgs[2] = NewTask;
3225 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
3226 DepTaskArgs[4] = DependenciesArray.getPointer();
3227 DepTaskArgs[5] = CGF.Builder.getInt32(0);
3228 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3229 }
3230 auto &&ThenCodeGen = [this, NumDependencies,
3231 &TaskArgs, &DepTaskArgs](CodeGenFunction &CGF) {
3232 // TODO: add check for untied tasks.
3233 if (NumDependencies) {
3234 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps),
3235 DepTaskArgs);
3236 } else {
3237 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
3238 TaskArgs);
3239 }
Alexey Bataev1d677132015-04-22 13:57:31 +00003240 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00003241 typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value>
3242 IfCallEndCleanup;
John McCall7f416cc2015-09-08 08:05:57 +00003243
3244 llvm::Value *DepWaitTaskArgs[6];
3245 if (NumDependencies) {
3246 DepWaitTaskArgs[0] = UpLoc;
3247 DepWaitTaskArgs[1] = ThreadID;
3248 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
3249 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
3250 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
3251 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3252 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003253 auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
John McCall7f416cc2015-09-08 08:05:57 +00003254 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003255 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
3256 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
3257 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
3258 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
3259 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00003260 if (NumDependencies)
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003261 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
3262 DepWaitTaskArgs);
3263 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
3264 // kmp_task_t *new_task);
3265 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0),
3266 TaskArgs);
3267 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
3268 // kmp_task_t *new_task);
3269 CGF.EHStack.pushCleanup<IfCallEndCleanup>(
3270 NormalAndEHCleanup,
3271 createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0),
3272 llvm::makeArrayRef(TaskArgs));
Alexey Bataev1d677132015-04-22 13:57:31 +00003273
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003274 // Call proxy_task_entry(gtid, new_task);
3275 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
3276 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
3277 };
John McCall7f416cc2015-09-08 08:05:57 +00003278
Alexey Bataev1d677132015-04-22 13:57:31 +00003279 if (IfCond) {
3280 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
3281 } else {
3282 CodeGenFunction::RunCleanupsScope Scope(CGF);
3283 ThenCodeGen(CGF);
3284 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003285}
3286
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003287/// \brief Emit reduction operation for each element of array (required for
3288/// array sections) LHS op = RHS.
3289/// \param Type Type of array.
3290/// \param LHSVar Variable on the left side of the reduction operation
3291/// (references element of array in original variable).
3292/// \param RHSVar Variable on the right side of the reduction operation
3293/// (references element of array in original variable).
3294/// \param RedOpGen Generator of reduction operation with use of LHSVar and
3295/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00003296static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003297 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
3298 const VarDecl *RHSVar,
3299 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
3300 const Expr *, const Expr *)> &RedOpGen,
3301 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
3302 const Expr *UpExpr = nullptr) {
3303 // Perform element-by-element initialization.
3304 QualType ElementTy;
3305 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
3306 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
3307
3308 // Drill down to the base element type on both arrays.
3309 auto ArrayTy = Type->getAsArrayTypeUnsafe();
3310 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
3311
3312 auto RHSBegin = RHSAddr.getPointer();
3313 auto LHSBegin = LHSAddr.getPointer();
3314 // Cast from pointer to array type to pointer to single element.
3315 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
3316 // The basic structure here is a while-do loop.
3317 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
3318 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
3319 auto IsEmpty =
3320 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
3321 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
3322
3323 // Enter the loop body, making that address the current address.
3324 auto EntryBB = CGF.Builder.GetInsertBlock();
3325 CGF.EmitBlock(BodyBB);
3326
3327 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
3328
3329 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
3330 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
3331 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
3332 Address RHSElementCurrent =
3333 Address(RHSElementPHI,
3334 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3335
3336 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
3337 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
3338 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
3339 Address LHSElementCurrent =
3340 Address(LHSElementPHI,
3341 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3342
3343 // Emit copy.
3344 CodeGenFunction::OMPPrivateScope Scope(CGF);
3345 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
3346 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
3347 Scope.Privatize();
3348 RedOpGen(CGF, XExpr, EExpr, UpExpr);
3349 Scope.ForceCleanup();
3350
3351 // Shift the address forward by one element.
3352 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
3353 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
3354 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
3355 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
3356 // Check whether we've reached the end.
3357 auto Done =
3358 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
3359 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
3360 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
3361 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
3362
3363 // Done.
3364 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
3365}
3366
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003367static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
3368 llvm::Type *ArgsType,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003369 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003370 ArrayRef<const Expr *> LHSExprs,
3371 ArrayRef<const Expr *> RHSExprs,
3372 ArrayRef<const Expr *> ReductionOps) {
3373 auto &C = CGM.getContext();
3374
3375 // void reduction_func(void *LHSArg, void *RHSArg);
3376 FunctionArgList Args;
3377 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3378 C.VoidPtrTy);
3379 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3380 C.VoidPtrTy);
3381 Args.push_back(&LHSArg);
3382 Args.push_back(&RHSArg);
3383 FunctionType::ExtInfo EI;
3384 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
3385 C.VoidTy, Args, EI, /*isVariadic=*/false);
3386 auto *Fn = llvm::Function::Create(
3387 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
3388 ".omp.reduction.reduction_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003389 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003390 CodeGenFunction CGF(CGM);
3391 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
3392
3393 // Dst = (void*[n])(LHSArg);
3394 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003395 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3396 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3397 ArgsType), CGF.getPointerAlign());
3398 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3399 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3400 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003401
3402 // ...
3403 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
3404 // ...
3405 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003406 auto IPriv = Privates.begin();
3407 unsigned Idx = 0;
3408 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003409 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
3410 Scope.addPrivate(RHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003411 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003412 });
3413 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
3414 Scope.addPrivate(LHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003415 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003416 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003417 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003418 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003419 // Get array size and emit VLA type.
3420 ++Idx;
3421 Address Elem =
3422 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
3423 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003424 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy);
3425 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003426 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00003427 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003428 CGF.EmitVariablyModifiedType(PrivTy);
3429 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003430 }
3431 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003432 IPriv = Privates.begin();
3433 auto ILHS = LHSExprs.begin();
3434 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003435 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003436 if ((*IPriv)->getType()->isArrayType()) {
3437 // Emit reduction for array section.
3438 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3439 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3440 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3441 [=](CodeGenFunction &CGF, const Expr *,
3442 const Expr *,
3443 const Expr *) { CGF.EmitIgnoredExpr(E); });
3444 } else
3445 // Emit reduction for array subscript or single variable.
3446 CGF.EmitIgnoredExpr(E);
Richard Trieucc3949d2016-02-18 22:34:54 +00003447 ++IPriv;
3448 ++ILHS;
3449 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003450 }
3451 Scope.ForceCleanup();
3452 CGF.FinishFunction();
3453 return Fn;
3454}
3455
3456void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003457 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003458 ArrayRef<const Expr *> LHSExprs,
3459 ArrayRef<const Expr *> RHSExprs,
3460 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003461 bool WithNowait, bool SimpleReduction) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003462 if (!CGF.HaveInsertPoint())
3463 return;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003464 // Next code should be emitted for reduction:
3465 //
3466 // static kmp_critical_name lock = { 0 };
3467 //
3468 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
3469 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
3470 // ...
3471 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
3472 // *(Type<n>-1*)rhs[<n>-1]);
3473 // }
3474 //
3475 // ...
3476 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
3477 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
3478 // RedList, reduce_func, &<lock>)) {
3479 // case 1:
3480 // ...
3481 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3482 // ...
3483 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3484 // break;
3485 // case 2:
3486 // ...
3487 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
3488 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00003489 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003490 // break;
3491 // default:;
3492 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003493 //
3494 // if SimpleReduction is true, only the next code is generated:
3495 // ...
3496 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3497 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003498
3499 auto &C = CGM.getContext();
3500
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003501 if (SimpleReduction) {
3502 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003503 auto IPriv = Privates.begin();
3504 auto ILHS = LHSExprs.begin();
3505 auto IRHS = RHSExprs.begin();
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003506 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003507 if ((*IPriv)->getType()->isArrayType()) {
3508 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3509 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3510 EmitOMPAggregateReduction(
3511 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3512 [=](CodeGenFunction &CGF, const Expr *, const Expr *,
3513 const Expr *) { CGF.EmitIgnoredExpr(E); });
3514 } else
3515 CGF.EmitIgnoredExpr(E);
Richard Trieucc3949d2016-02-18 22:34:54 +00003516 ++IPriv;
3517 ++ILHS;
3518 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003519 }
3520 return;
3521 }
3522
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003523 // 1. Build a list of reduction variables.
3524 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003525 auto Size = RHSExprs.size();
3526 for (auto *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00003527 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003528 // Reserve place for array size.
3529 ++Size;
3530 }
3531 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003532 QualType ReductionArrayTy =
3533 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
3534 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00003535 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003536 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003537 auto IPriv = Privates.begin();
3538 unsigned Idx = 0;
3539 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003540 Address Elem =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003541 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00003542 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003543 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003544 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
3545 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003546 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003547 // Store array size.
3548 ++Idx;
3549 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
3550 CGF.getPointerSize());
Alexey Bataev1189bd02016-01-26 12:20:39 +00003551 llvm::Value *Size = CGF.Builder.CreateIntCast(
3552 CGF.getVLASize(
3553 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
3554 .first,
3555 CGF.SizeTy, /*isSigned=*/false);
3556 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
3557 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003558 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003559 }
3560
3561 // 2. Emit reduce_func().
3562 auto *ReductionFn = emitReductionFunction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003563 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
3564 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003565
3566 // 3. Create static kmp_critical_name lock = { 0 };
3567 auto *Lock = getCriticalRegionLock(".reduction");
3568
3569 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
3570 // RedList, reduce_func, &<lock>);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003571 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003572 auto *ThreadId = getThreadID(CGF, Loc);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003573 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003574 auto *RL =
3575 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
3576 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003577 llvm::Value *Args[] = {
3578 IdentTLoc, // ident_t *<loc>
3579 ThreadId, // i32 <gtid>
3580 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
3581 ReductionArrayTySize, // size_type sizeof(RedList)
3582 RL, // void *RedList
3583 ReductionFn, // void (*) (void *, void *) <reduce_func>
3584 Lock // kmp_critical_name *&<lock>
3585 };
3586 auto Res = CGF.EmitRuntimeCall(
3587 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
3588 : OMPRTL__kmpc_reduce),
3589 Args);
3590
3591 // 5. Build switch(res)
3592 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
3593 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
3594
3595 // 6. Build case 1:
3596 // ...
3597 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3598 // ...
3599 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3600 // break;
3601 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
3602 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
3603 CGF.EmitBlock(Case1BB);
3604
3605 {
3606 CodeGenFunction::RunCleanupsScope Scope(CGF);
3607 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3608 llvm::Value *EndArgs[] = {
3609 IdentTLoc, // ident_t *<loc>
3610 ThreadId, // i32 <gtid>
3611 Lock // kmp_critical_name *&<lock>
3612 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00003613 CGF.EHStack
3614 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
3615 NormalAndEHCleanup,
3616 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
3617 : OMPRTL__kmpc_end_reduce),
3618 llvm::makeArrayRef(EndArgs));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003619 auto IPriv = Privates.begin();
3620 auto ILHS = LHSExprs.begin();
3621 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003622 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003623 if ((*IPriv)->getType()->isArrayType()) {
3624 // Emit reduction for array section.
3625 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3626 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3627 EmitOMPAggregateReduction(
3628 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3629 [=](CodeGenFunction &CGF, const Expr *, const Expr *,
3630 const Expr *) { CGF.EmitIgnoredExpr(E); });
3631 } else
3632 // Emit reduction for array subscript or single variable.
3633 CGF.EmitIgnoredExpr(E);
Richard Trieucc3949d2016-02-18 22:34:54 +00003634 ++IPriv;
3635 ++ILHS;
3636 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003637 }
3638 }
3639
3640 CGF.EmitBranch(DefaultBB);
3641
3642 // 7. Build case 2:
3643 // ...
3644 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
3645 // ...
3646 // break;
3647 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
3648 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
3649 CGF.EmitBlock(Case2BB);
3650
3651 {
3652 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataev69a47792015-05-07 03:54:03 +00003653 if (!WithNowait) {
3654 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
3655 llvm::Value *EndArgs[] = {
3656 IdentTLoc, // ident_t *<loc>
3657 ThreadId, // i32 <gtid>
3658 Lock // kmp_critical_name *&<lock>
3659 };
3660 CGF.EHStack
3661 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
3662 NormalAndEHCleanup,
3663 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
3664 llvm::makeArrayRef(EndArgs));
3665 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003666 auto ILHS = LHSExprs.begin();
3667 auto IRHS = RHSExprs.begin();
3668 auto IPriv = Privates.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003669 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003670 const Expr *XExpr = nullptr;
3671 const Expr *EExpr = nullptr;
3672 const Expr *UpExpr = nullptr;
3673 BinaryOperatorKind BO = BO_Comma;
3674 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
3675 if (BO->getOpcode() == BO_Assign) {
3676 XExpr = BO->getLHS();
3677 UpExpr = BO->getRHS();
3678 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003679 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003680 // Try to emit update expression as a simple atomic.
3681 auto *RHSExpr = UpExpr;
3682 if (RHSExpr) {
3683 // Analyze RHS part of the whole expression.
3684 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
3685 RHSExpr->IgnoreParenImpCasts())) {
3686 // If this is a conditional operator, analyze its condition for
3687 // min/max reduction operator.
3688 RHSExpr = ACO->getCond();
3689 }
3690 if (auto *BORHS =
3691 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
3692 EExpr = BORHS->getRHS();
3693 BO = BORHS->getOpcode();
3694 }
Alexey Bataev69a47792015-05-07 03:54:03 +00003695 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003696 if (XExpr) {
3697 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3698 auto &&AtomicRedGen = [this, BO, VD, IPriv,
3699 Loc](CodeGenFunction &CGF, const Expr *XExpr,
3700 const Expr *EExpr, const Expr *UpExpr) {
3701 LValue X = CGF.EmitLValue(XExpr);
3702 RValue E;
3703 if (EExpr)
3704 E = CGF.EmitAnyExpr(EExpr);
3705 CGF.EmitOMPAtomicSimpleUpdateExpr(
3706 X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
Alexey Bataev8524d152016-01-21 12:35:58 +00003707 [&CGF, UpExpr, VD, IPriv, Loc](RValue XRValue) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003708 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataev8524d152016-01-21 12:35:58 +00003709 PrivateScope.addPrivate(
3710 VD, [&CGF, VD, XRValue, Loc]() -> Address {
3711 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
3712 CGF.emitOMPSimpleStore(
3713 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
3714 VD->getType().getNonReferenceType(), Loc);
3715 return LHSTemp;
3716 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003717 (void)PrivateScope.Privatize();
3718 return CGF.EmitAnyExpr(UpExpr);
3719 });
3720 };
3721 if ((*IPriv)->getType()->isArrayType()) {
3722 // Emit atomic reduction for array section.
3723 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3724 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
3725 AtomicRedGen, XExpr, EExpr, UpExpr);
3726 } else
3727 // Emit atomic reduction for array subscript or single variable.
3728 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
3729 } else {
3730 // Emit as a critical region.
3731 auto &&CritRedGen = [this, E, Loc](CodeGenFunction &CGF, const Expr *,
3732 const Expr *, const Expr *) {
3733 emitCriticalRegion(
3734 CGF, ".atomic_reduction",
3735 [E](CodeGenFunction &CGF) { CGF.EmitIgnoredExpr(E); }, Loc);
3736 };
3737 if ((*IPriv)->getType()->isArrayType()) {
3738 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3739 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3740 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3741 CritRedGen);
3742 } else
3743 CritRedGen(CGF, nullptr, nullptr, nullptr);
3744 }
Richard Trieucc3949d2016-02-18 22:34:54 +00003745 ++ILHS;
3746 ++IRHS;
3747 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003748 }
3749 }
3750
3751 CGF.EmitBranch(DefaultBB);
3752 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
3753}
3754
Alexey Bataev8b8e2022015-04-27 05:22:09 +00003755void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
3756 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003757 if (!CGF.HaveInsertPoint())
3758 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00003759 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
3760 // global_tid);
3761 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3762 // Ignore return result until untied tasks are supported.
3763 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
3764}
3765
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003766void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003767 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00003768 const RegionCodeGenTy &CodeGen,
3769 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003770 if (!CGF.HaveInsertPoint())
3771 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00003772 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003773 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003774}
3775
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003776namespace {
3777enum RTCancelKind {
3778 CancelNoreq = 0,
3779 CancelParallel = 1,
3780 CancelLoop = 2,
3781 CancelSections = 3,
3782 CancelTaskgroup = 4
3783};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00003784} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003785
3786static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
3787 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00003788 if (CancelRegion == OMPD_parallel)
3789 CancelKind = CancelParallel;
3790 else if (CancelRegion == OMPD_for)
3791 CancelKind = CancelLoop;
3792 else if (CancelRegion == OMPD_sections)
3793 CancelKind = CancelSections;
3794 else {
3795 assert(CancelRegion == OMPD_taskgroup);
3796 CancelKind = CancelTaskgroup;
3797 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003798 return CancelKind;
3799}
3800
3801void CGOpenMPRuntime::emitCancellationPointCall(
3802 CodeGenFunction &CGF, SourceLocation Loc,
3803 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003804 if (!CGF.HaveInsertPoint())
3805 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003806 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
3807 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003808 if (auto *OMPRegionInfo =
3809 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003810 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003811 llvm::Value *Args[] = {
3812 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3813 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003814 // Ignore return result until untied tasks are supported.
3815 auto *Result = CGF.EmitRuntimeCall(
3816 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
3817 // if (__kmpc_cancellationpoint()) {
3818 // __kmpc_cancel_barrier();
3819 // exit from construct;
3820 // }
3821 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
3822 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
3823 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
3824 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3825 CGF.EmitBlock(ExitBB);
3826 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00003827 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003828 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00003829 auto CancelDest =
3830 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003831 CGF.EmitBranchThroughCleanup(CancelDest);
3832 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3833 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00003834 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00003835}
3836
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003837void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00003838 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003839 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003840 if (!CGF.HaveInsertPoint())
3841 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003842 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
3843 // kmp_int32 cncl_kind);
3844 if (auto *OMPRegionInfo =
3845 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev87933c72015-09-18 08:07:34 +00003846 auto &&ThenGen = [this, Loc, CancelRegion,
3847 OMPRegionInfo](CodeGenFunction &CGF) {
3848 llvm::Value *Args[] = {
3849 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3850 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
3851 // Ignore return result until untied tasks are supported.
3852 auto *Result =
3853 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
3854 // if (__kmpc_cancel()) {
3855 // __kmpc_cancel_barrier();
3856 // exit from construct;
3857 // }
3858 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
3859 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
3860 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
3861 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3862 CGF.EmitBlock(ExitBB);
3863 // __kmpc_cancel_barrier();
3864 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
3865 // exit from construct;
3866 auto CancelDest =
3867 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
3868 CGF.EmitBranchThroughCleanup(CancelDest);
3869 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3870 };
3871 if (IfCond)
3872 emitOMPIfClause(CGF, IfCond, ThenGen, [](CodeGenFunction &) {});
3873 else
3874 ThenGen(CGF);
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003875 }
3876}
Samuel Antaobed3c462015-10-02 16:14:20 +00003877
Samuel Antaoee8fb302016-01-06 13:42:12 +00003878/// \brief Obtain information that uniquely identifies a target entry. This
Samuel Antao2de62b02016-02-13 23:35:10 +00003879/// consists of the file and device IDs as well as line number associated with
3880/// the relevant entry source location.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003881static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
3882 unsigned &DeviceID, unsigned &FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00003883 unsigned &LineNum) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003884
3885 auto &SM = C.getSourceManager();
3886
3887 // The loc should be always valid and have a file ID (the user cannot use
3888 // #pragma directives in macros)
3889
3890 assert(Loc.isValid() && "Source location is expected to be always valid.");
3891 assert(Loc.isFileID() && "Source location is expected to refer to a file.");
3892
3893 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
3894 assert(PLoc.isValid() && "Source location is expected to be always valid.");
3895
3896 llvm::sys::fs::UniqueID ID;
3897 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
3898 llvm_unreachable("Source file with target region no longer exists!");
3899
3900 DeviceID = ID.getDevice();
3901 FileID = ID.getFile();
3902 LineNum = PLoc.getLine();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003903}
3904
3905void CGOpenMPRuntime::emitTargetOutlinedFunction(
3906 const OMPExecutableDirective &D, StringRef ParentName,
3907 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
3908 bool IsOffloadEntry) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003909 assert(!ParentName.empty() && "Invalid target region parent name!");
3910
Samuel Antaobed3c462015-10-02 16:14:20 +00003911 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
3912
Samuel Antaoee8fb302016-01-06 13:42:12 +00003913 // Emit target region as a standalone region.
3914 auto &&CodeGen = [&CS](CodeGenFunction &CGF) {
3915 CGF.EmitStmt(CS.getCapturedStmt());
3916 };
3917
Samuel Antao2de62b02016-02-13 23:35:10 +00003918 // Create a unique name for the entry function using the source location
3919 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00003920 //
Samuel Antao2de62b02016-02-13 23:35:10 +00003921 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00003922 //
3923 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00003924 // mangled name of the function that encloses the target region and BB is the
3925 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003926
3927 unsigned DeviceID;
3928 unsigned FileID;
3929 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003930 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00003931 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003932 SmallString<64> EntryFnName;
3933 {
3934 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00003935 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
3936 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003937 }
3938
Samuel Antaobed3c462015-10-02 16:14:20 +00003939 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003940 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00003941 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003942
3943 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
3944
3945 // If this target outline function is not an offload entry, we don't need to
3946 // register it.
3947 if (!IsOffloadEntry)
3948 return;
3949
3950 // The target region ID is used by the runtime library to identify the current
3951 // target region, so it only has to be unique and not necessarily point to
3952 // anything. It could be the pointer to the outlined function that implements
3953 // the target region, but we aren't using that so that the compiler doesn't
3954 // need to keep that, and could therefore inline the host function if proven
3955 // worthwhile during optimization. In the other hand, if emitting code for the
3956 // device, the ID has to be the function address so that it can retrieved from
3957 // the offloading entry and launched by the runtime library. We also mark the
3958 // outlined function to have external linkage in case we are emitting code for
3959 // the device, because these functions will be entry points to the device.
3960
3961 if (CGM.getLangOpts().OpenMPIsDevice) {
3962 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
3963 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage);
3964 } else
3965 OutlinedFnID = new llvm::GlobalVariable(
3966 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
3967 llvm::GlobalValue::PrivateLinkage,
3968 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id");
3969
3970 // Register the information for the entry associated with this target region.
3971 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003972 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID);
Samuel Antaobed3c462015-10-02 16:14:20 +00003973}
3974
3975void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
3976 const OMPExecutableDirective &D,
3977 llvm::Value *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00003978 llvm::Value *OutlinedFnID,
Samuel Antaobed3c462015-10-02 16:14:20 +00003979 const Expr *IfCond, const Expr *Device,
3980 ArrayRef<llvm::Value *> CapturedVars) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003981 if (!CGF.HaveInsertPoint())
3982 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00003983 /// \brief Values for bit flags used to specify the mapping type for
3984 /// offloading.
3985 enum OpenMPOffloadMappingFlags {
3986 /// \brief Allocate memory on the device and move data from host to device.
3987 OMP_MAP_TO = 0x01,
3988 /// \brief Allocate memory on the device and move data from device to host.
3989 OMP_MAP_FROM = 0x02,
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003990 /// \brief The element passed to the device is a pointer.
3991 OMP_MAP_PTR = 0x20,
3992 /// \brief Pass the element to the device by value.
3993 OMP_MAP_BYCOPY = 0x80,
Samuel Antaobed3c462015-10-02 16:14:20 +00003994 };
3995
3996 enum OpenMPOffloadingReservedDeviceIDs {
3997 /// \brief Device ID if the device was not defined, runtime should get it
3998 /// from environment variables in the spec.
3999 OMP_DEVICEID_UNDEF = -1,
4000 };
4001
Samuel Antaoee8fb302016-01-06 13:42:12 +00004002 assert(OutlinedFn && "Invalid outlined function!");
4003
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004004 auto &Ctx = CGF.getContext();
4005
Samuel Antaobed3c462015-10-02 16:14:20 +00004006 // Fill up the arrays with the all the captured variables.
4007 SmallVector<llvm::Value *, 16> BasePointers;
4008 SmallVector<llvm::Value *, 16> Pointers;
4009 SmallVector<llvm::Value *, 16> Sizes;
4010 SmallVector<unsigned, 16> MapTypes;
4011
4012 bool hasVLACaptures = false;
4013
4014 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4015 auto RI = CS.getCapturedRecordDecl()->field_begin();
4016 // auto II = CS.capture_init_begin();
4017 auto CV = CapturedVars.begin();
4018 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
4019 CE = CS.capture_end();
4020 CI != CE; ++CI, ++RI, ++CV) {
4021 StringRef Name;
4022 QualType Ty;
4023 llvm::Value *BasePointer;
4024 llvm::Value *Pointer;
4025 llvm::Value *Size;
4026 unsigned MapType;
4027
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004028 // VLA sizes are passed to the outlined region by copy.
Samuel Antaobed3c462015-10-02 16:14:20 +00004029 if (CI->capturesVariableArrayType()) {
4030 BasePointer = Pointer = *CV;
Alexey Bataev1189bd02016-01-26 12:20:39 +00004031 Size = CGF.getTypeSize(RI->getType());
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004032 // Copy to the device as an argument. No need to retrieve it.
4033 MapType = OMP_MAP_BYCOPY;
Samuel Antaobed3c462015-10-02 16:14:20 +00004034 hasVLACaptures = true;
Samuel Antaobed3c462015-10-02 16:14:20 +00004035 } else if (CI->capturesThis()) {
4036 BasePointer = Pointer = *CV;
4037 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr());
Alexey Bataev1189bd02016-01-26 12:20:39 +00004038 Size = CGF.getTypeSize(PtrTy->getPointeeType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004039 // Default map type.
4040 MapType = OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004041 } else if (CI->capturesVariableByCopy()) {
4042 MapType = OMP_MAP_BYCOPY;
4043 if (!RI->getType()->isAnyPointerType()) {
4044 // If the field is not a pointer, we need to save the actual value and
4045 // load it as a void pointer.
4046 auto DstAddr = CGF.CreateMemTemp(
4047 Ctx.getUIntPtrType(),
4048 Twine(CI->getCapturedVar()->getName()) + ".casted");
4049 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
4050
4051 auto *SrcAddrVal = CGF.EmitScalarConversion(
4052 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
4053 Ctx.getPointerType(RI->getType()), SourceLocation());
4054 LValue SrcLV =
4055 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType());
4056
4057 // Store the value using the source type pointer.
4058 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV);
4059
4060 // Load the value using the destination type pointer.
4061 BasePointer = Pointer =
4062 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
4063 } else {
4064 MapType |= OMP_MAP_PTR;
4065 BasePointer = Pointer = *CV;
4066 }
Alexey Bataev1189bd02016-01-26 12:20:39 +00004067 Size = CGF.getTypeSize(RI->getType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004068 } else {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004069 assert(CI->capturesVariable() && "Expected captured reference.");
Samuel Antaobed3c462015-10-02 16:14:20 +00004070 BasePointer = Pointer = *CV;
4071
4072 const ReferenceType *PtrTy =
4073 cast<ReferenceType>(RI->getType().getTypePtr());
4074 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00004075 Size = CGF.getTypeSize(ElementType);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004076 // The default map type for a scalar/complex type is 'to' because by
4077 // default the value doesn't have to be retrieved. For an aggregate type,
4078 // the default is 'tofrom'.
4079 MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
4080 : OMP_MAP_TO;
4081 if (ElementType->isAnyPointerType())
4082 MapType |= OMP_MAP_PTR;
Samuel Antaobed3c462015-10-02 16:14:20 +00004083 }
4084
4085 BasePointers.push_back(BasePointer);
4086 Pointers.push_back(Pointer);
4087 Sizes.push_back(Size);
4088 MapTypes.push_back(MapType);
4089 }
4090
4091 // Keep track on whether the host function has to be executed.
4092 auto OffloadErrorQType =
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004093 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004094 auto OffloadError = CGF.MakeAddrLValue(
4095 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
4096 OffloadErrorQType);
4097 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
4098 OffloadError);
4099
4100 // Fill up the pointer arrays and transfer execution to the device.
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004101 auto &&ThenGen = [this, &Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes,
Samuel Antaoee8fb302016-01-06 13:42:12 +00004102 hasVLACaptures, Device, OutlinedFnID, OffloadError,
Samuel Antaobed3c462015-10-02 16:14:20 +00004103 OffloadErrorQType](CodeGenFunction &CGF) {
4104 unsigned PointerNumVal = BasePointers.size();
4105 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal);
4106 llvm::Value *BasePointersArray;
4107 llvm::Value *PointersArray;
4108 llvm::Value *SizesArray;
4109 llvm::Value *MapTypesArray;
4110
4111 if (PointerNumVal) {
4112 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004113 QualType PointerArrayType = Ctx.getConstantArrayType(
4114 Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004115 /*IndexTypeQuals=*/0);
4116
4117 BasePointersArray =
4118 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
4119 PointersArray =
4120 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
4121
4122 // If we don't have any VLA types, we can use a constant array for the map
4123 // sizes, otherwise we need to fill up the arrays as we do for the
4124 // pointers.
4125 if (hasVLACaptures) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004126 QualType SizeArrayType = Ctx.getConstantArrayType(
4127 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004128 /*IndexTypeQuals=*/0);
4129 SizesArray =
4130 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
4131 } else {
4132 // We expect all the sizes to be constant, so we collect them to create
4133 // a constant array.
4134 SmallVector<llvm::Constant *, 16> ConstSizes;
4135 for (auto S : Sizes)
4136 ConstSizes.push_back(cast<llvm::Constant>(S));
4137
4138 auto *SizesArrayInit = llvm::ConstantArray::get(
4139 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
4140 auto *SizesArrayGbl = new llvm::GlobalVariable(
4141 CGM.getModule(), SizesArrayInit->getType(),
4142 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4143 SizesArrayInit, ".offload_sizes");
4144 SizesArrayGbl->setUnnamedAddr(true);
4145 SizesArray = SizesArrayGbl;
4146 }
4147
4148 // The map types are always constant so we don't need to generate code to
4149 // fill arrays. Instead, we create an array constant.
4150 llvm::Constant *MapTypesArrayInit =
4151 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
4152 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
4153 CGM.getModule(), MapTypesArrayInit->getType(),
4154 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4155 MapTypesArrayInit, ".offload_maptypes");
4156 MapTypesArrayGbl->setUnnamedAddr(true);
4157 MapTypesArray = MapTypesArrayGbl;
4158
4159 for (unsigned i = 0; i < PointerNumVal; ++i) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004160 llvm::Value *BPVal = BasePointers[i];
4161 if (BPVal->getType()->isPointerTy())
4162 BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy);
4163 else {
4164 assert(BPVal->getType()->isIntegerTy() &&
4165 "If not a pointer, the value type must be an integer.");
4166 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy);
4167 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004168 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
4169 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal),
4170 BasePointersArray, 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004171 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4172 CGF.Builder.CreateStore(BPVal, BPAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004173
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004174 llvm::Value *PVal = Pointers[i];
4175 if (PVal->getType()->isPointerTy())
4176 PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy);
4177 else {
4178 assert(PVal->getType()->isIntegerTy() &&
4179 "If not a pointer, the value type must be an integer.");
4180 PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy);
4181 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004182 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
4183 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
4184 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004185 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4186 CGF.Builder.CreateStore(PVal, PAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004187
4188 if (hasVLACaptures) {
4189 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
4190 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
4191 /*Idx0=*/0,
4192 /*Idx1=*/i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004193 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
Samuel Antaobed3c462015-10-02 16:14:20 +00004194 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(
4195 Sizes[i], CGM.SizeTy, /*isSigned=*/true),
4196 SAddr);
4197 }
4198 }
4199
4200 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
4201 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), BasePointersArray,
4202 /*Idx0=*/0, /*Idx1=*/0);
4203 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
4204 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
4205 /*Idx0=*/0,
4206 /*Idx1=*/0);
4207 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
4208 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
4209 /*Idx0=*/0, /*Idx1=*/0);
4210 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
4211 llvm::ArrayType::get(CGM.Int32Ty, PointerNumVal), MapTypesArray,
4212 /*Idx0=*/0,
4213 /*Idx1=*/0);
4214
4215 } else {
4216 BasePointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
4217 PointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
4218 SizesArray = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
4219 MapTypesArray =
4220 llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo());
4221 }
4222
4223 // On top of the arrays that were filled up, the target offloading call
4224 // takes as arguments the device id as well as the host pointer. The host
4225 // pointer is used by the runtime library to identify the current target
4226 // region, so it only has to be unique and not necessarily point to
4227 // anything. It could be the pointer to the outlined function that
4228 // implements the target region, but we aren't using that so that the
4229 // compiler doesn't need to keep that, and could therefore inline the host
4230 // function if proven worthwhile during optimization.
4231
Samuel Antaoee8fb302016-01-06 13:42:12 +00004232 // From this point on, we need to have an ID of the target region defined.
4233 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00004234
4235 // Emit device ID if any.
4236 llvm::Value *DeviceID;
4237 if (Device)
4238 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
4239 CGM.Int32Ty, /*isSigned=*/true);
4240 else
4241 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
4242
4243 llvm::Value *OffloadingArgs[] = {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004244 DeviceID, OutlinedFnID, PointerNum, BasePointersArray,
4245 PointersArray, SizesArray, MapTypesArray};
Samuel Antaobed3c462015-10-02 16:14:20 +00004246 auto Return = CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target),
4247 OffloadingArgs);
4248
4249 CGF.EmitStoreOfScalar(Return, OffloadError);
4250 };
4251
Samuel Antaoee8fb302016-01-06 13:42:12 +00004252 // Notify that the host version must be executed.
4253 auto &&ElseGen = [this, OffloadError,
4254 OffloadErrorQType](CodeGenFunction &CGF) {
4255 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/-1u),
4256 OffloadError);
4257 };
4258
4259 // If we have a target function ID it means that we need to support
4260 // offloading, otherwise, just execute on the host. We need to execute on host
4261 // regardless of the conditional in the if clause if, e.g., the user do not
4262 // specify target triples.
4263 if (OutlinedFnID) {
4264 if (IfCond) {
4265 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
4266 } else {
4267 CodeGenFunction::RunCleanupsScope Scope(CGF);
4268 ThenGen(CGF);
4269 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004270 } else {
4271 CodeGenFunction::RunCleanupsScope Scope(CGF);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004272 ElseGen(CGF);
Samuel Antaobed3c462015-10-02 16:14:20 +00004273 }
4274
4275 // Check the error code and execute the host version if required.
4276 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
4277 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
4278 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
4279 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
4280 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
4281
4282 CGF.EmitBlock(OffloadFailedBlock);
4283 CGF.Builder.CreateCall(OutlinedFn, BasePointers);
4284 CGF.EmitBranch(OffloadContBlock);
4285
4286 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004287}
Samuel Antaoee8fb302016-01-06 13:42:12 +00004288
4289void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
4290 StringRef ParentName) {
4291 if (!S)
4292 return;
4293
4294 // If we find a OMP target directive, codegen the outline function and
4295 // register the result.
4296 // FIXME: Add other directives with target when they become supported.
4297 bool isTargetDirective = isa<OMPTargetDirective>(S);
4298
4299 if (isTargetDirective) {
4300 auto *E = cast<OMPExecutableDirective>(S);
4301 unsigned DeviceID;
4302 unsigned FileID;
4303 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004304 getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004305 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004306
4307 // Is this a target region that should not be emitted as an entry point? If
4308 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00004309 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
4310 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004311 return;
4312
4313 llvm::Function *Fn;
4314 llvm::Constant *Addr;
4315 emitTargetOutlinedFunction(*E, ParentName, Fn, Addr,
4316 /*isOffloadEntry=*/true);
4317 assert(Fn && Addr && "Target region emission failed.");
4318 return;
4319 }
4320
4321 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) {
4322 if (!E->getAssociatedStmt())
4323 return;
4324
4325 scanForTargetRegionsFunctions(
4326 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(),
4327 ParentName);
4328 return;
4329 }
4330
4331 // If this is a lambda function, look into its body.
4332 if (auto *L = dyn_cast<LambdaExpr>(S))
4333 S = L->getBody();
4334
4335 // Keep looking for target regions recursively.
4336 for (auto *II : S->children())
4337 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004338}
4339
4340bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
4341 auto &FD = *cast<FunctionDecl>(GD.getDecl());
4342
4343 // If emitting code for the host, we do not process FD here. Instead we do
4344 // the normal code generation.
4345 if (!CGM.getLangOpts().OpenMPIsDevice)
4346 return false;
4347
4348 // Try to detect target regions in the function.
4349 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
4350
4351 // We should not emit any function othen that the ones created during the
4352 // scanning. Therefore, we signal that this function is completely dealt
4353 // with.
4354 return true;
4355}
4356
4357bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
4358 if (!CGM.getLangOpts().OpenMPIsDevice)
4359 return false;
4360
4361 // Check if there are Ctors/Dtors in this declaration and look for target
4362 // regions in it. We use the complete variant to produce the kernel name
4363 // mangling.
4364 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
4365 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
4366 for (auto *Ctor : RD->ctors()) {
4367 StringRef ParentName =
4368 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
4369 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
4370 }
4371 auto *Dtor = RD->getDestructor();
4372 if (Dtor) {
4373 StringRef ParentName =
4374 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
4375 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
4376 }
4377 }
4378
4379 // If we are in target mode we do not emit any global (declare target is not
4380 // implemented yet). Therefore we signal that GD was processed in this case.
4381 return true;
4382}
4383
4384bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
4385 auto *VD = GD.getDecl();
4386 if (isa<FunctionDecl>(VD))
4387 return emitTargetFunctions(GD);
4388
4389 return emitTargetGlobalVariable(GD);
4390}
4391
4392llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
4393 // If we have offloading in the current module, we need to emit the entries
4394 // now and register the offloading descriptor.
4395 createOffloadEntriesAndInfoMetadata();
4396
4397 // Create and register the offloading binary descriptors. This is the main
4398 // entity that captures all the information about offloading in the current
4399 // compilation unit.
4400 return createOffloadingBinaryDescriptorRegistration();
4401}