blob: 6ffcb715c95abb2d0df911a42ffb649496991330 [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
14#include "CGOpenMPRuntime.h"
15#include "CodeGenFunction.h"
Alexey Bataev36bf0112015-03-10 05:15:26 +000016#include "CGCleanup.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000017#include "clang/AST/Decl.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000018#include "clang/AST/StmtOpenMP.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000019#include "llvm/ADT/ArrayRef.h"
Alexey Bataevd74d0602014-10-13 06:02:40 +000020#include "llvm/IR/CallSite.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000021#include "llvm/IR/DerivedTypes.h"
22#include "llvm/IR/GlobalValue.h"
23#include "llvm/IR/Value.h"
24#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000025#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000026
27using namespace clang;
28using namespace CodeGen;
29
Benjamin Kramerc52193f2014-10-10 13:57:57 +000030namespace {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000031/// \brief Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000032class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
33public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000034 /// \brief Kinds of OpenMP regions used in codegen.
35 enum CGOpenMPRegionKind {
36 /// \brief Region with outlined function for standalone 'parallel'
37 /// directive.
38 ParallelOutlinedRegion,
39 /// \brief Region with outlined function for standalone 'task' directive.
40 TaskOutlinedRegion,
41 /// \brief Region for constructs that do not require function outlining,
42 /// like 'for', 'sections', 'atomic' etc. directives.
43 InlinedRegion,
44 };
Alexey Bataev18095712014-10-10 12:19:54 +000045
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000046 CGOpenMPRegionInfo(const CapturedStmt &CS,
47 const CGOpenMPRegionKind RegionKind,
Alexey Bataev81c7ea02015-07-03 09:56:58 +000048 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000049 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev81c7ea02015-07-03 09:56:58 +000050 CodeGen(CodeGen), Kind(Kind) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000051
52 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev81c7ea02015-07-03 09:56:58 +000053 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind)
54 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
55 Kind(Kind) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000056
57 /// \brief Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000058 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000059 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000060
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000061 /// \brief Emit the captured statement body.
62 virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
63
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000064 /// \brief Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000065 /// \return LValue for thread id variable. This LValue always has type int32*.
66 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000067
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000068 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000069
Alexey Bataev81c7ea02015-07-03 09:56:58 +000070 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
71
Alexey Bataev18095712014-10-10 12:19:54 +000072 static bool classof(const CGCapturedStmtInfo *Info) {
73 return Info->getKind() == CR_OpenMP;
74 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000075
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000076protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000077 CGOpenMPRegionKind RegionKind;
78 const RegionCodeGenTy &CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000079 OpenMPDirectiveKind Kind;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000080};
Alexey Bataev18095712014-10-10 12:19:54 +000081
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000082/// \brief API for captured statement code generation in OpenMP constructs.
83class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
84public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000085 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +000086 const RegionCodeGenTy &CodeGen,
87 OpenMPDirectiveKind Kind)
88 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000089 ThreadIDVar(ThreadIDVar) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000090 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
91 }
92 /// \brief Get a variable or parameter for storing global thread id
93 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +000094 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000095
Alexey Bataev18095712014-10-10 12:19:54 +000096 /// \brief Get the name of the capture helper.
Benjamin Kramerc52193f2014-10-10 13:57:57 +000097 StringRef getHelperName() const override { return ".omp_outlined."; }
Alexey Bataev18095712014-10-10 12:19:54 +000098
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000099 static bool classof(const CGCapturedStmtInfo *Info) {
100 return CGOpenMPRegionInfo::classof(Info) &&
101 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
102 ParallelOutlinedRegion;
103 }
104
Alexey Bataev18095712014-10-10 12:19:54 +0000105private:
106 /// \brief A variable or parameter storing global thread id for OpenMP
107 /// constructs.
108 const VarDecl *ThreadIDVar;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000109};
110
Alexey Bataev62b63b12015-03-10 07:28:44 +0000111/// \brief API for captured statement code generation in OpenMP constructs.
112class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo {
113public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000114 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000115 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000116 const RegionCodeGenTy &CodeGen,
117 OpenMPDirectiveKind Kind)
118 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000119 ThreadIDVar(ThreadIDVar) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000120 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
121 }
122 /// \brief Get a variable or parameter for storing global thread id
123 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000124 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000125
126 /// \brief Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000127 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000128
Alexey Bataev62b63b12015-03-10 07:28:44 +0000129 /// \brief Get the name of the capture helper.
130 StringRef getHelperName() const override { return ".omp_outlined."; }
131
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000132 static bool classof(const CGCapturedStmtInfo *Info) {
133 return CGOpenMPRegionInfo::classof(Info) &&
134 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
135 TaskOutlinedRegion;
136 }
137
Alexey Bataev62b63b12015-03-10 07:28:44 +0000138private:
139 /// \brief A variable or parameter storing global thread id for OpenMP
140 /// constructs.
141 const VarDecl *ThreadIDVar;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000142};
143
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000144/// \brief API for inlined captured statement code generation in OpenMP
145/// constructs.
146class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
147public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000148 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000149 const RegionCodeGenTy &CodeGen,
150 OpenMPDirectiveKind Kind)
151 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind), OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000152 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
153 // \brief Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000154 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000155 if (OuterRegionInfo)
156 return OuterRegionInfo->getContextValue();
157 llvm_unreachable("No context value for inlined OpenMP region");
158 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000159 virtual void setContextValue(llvm::Value *V) override {
160 if (OuterRegionInfo) {
161 OuterRegionInfo->setContextValue(V);
162 return;
163 }
164 llvm_unreachable("No context value for inlined OpenMP region");
165 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000166 /// \brief Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000167 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000168 if (OuterRegionInfo)
169 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000170 // If there is no outer outlined region,no need to lookup in a list of
171 // captured variables, we can use the original one.
172 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000173 }
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000174 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000175 if (OuterRegionInfo)
176 return OuterRegionInfo->getThisFieldDecl();
177 return nullptr;
178 }
179 /// \brief Get a variable or parameter for storing global thread id
180 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000181 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000182 if (OuterRegionInfo)
183 return OuterRegionInfo->getThreadIDVariable();
184 return nullptr;
185 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000186
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000187 /// \brief Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000188 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000189 if (auto *OuterRegionInfo = getOldCSI())
190 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000191 llvm_unreachable("No helper name for inlined OpenMP construct");
192 }
193
194 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
195
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000196 static bool classof(const CGCapturedStmtInfo *Info) {
197 return CGOpenMPRegionInfo::classof(Info) &&
198 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
199 }
200
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000201private:
202 /// \brief CodeGen info about outer OpenMP region.
203 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
204 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000205};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000206
207/// \brief RAII for emitting code of OpenMP constructs.
208class InlinedOpenMPRegionRAII {
209 CodeGenFunction &CGF;
210
211public:
212 /// \brief Constructs region for combined constructs.
213 /// \param CodeGen Code generation sequence for combined directives. Includes
214 /// a list of functions used for code generation of implicitly inlined
215 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000216 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
217 OpenMPDirectiveKind Kind)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000218 : CGF(CGF) {
219 // Start emission for the construct.
220 CGF.CapturedStmtInfo =
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000221 new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen, Kind);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000222 }
223 ~InlinedOpenMPRegionRAII() {
224 // Restore original CapturedStmtInfo only if we're done with code emission.
225 auto *OldCSI =
226 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
227 delete CGF.CapturedStmtInfo;
228 CGF.CapturedStmtInfo = OldCSI;
229 }
230};
231
Benjamin Kramerc52193f2014-10-10 13:57:57 +0000232} // namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000233
234LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
235 return CGF.MakeNaturalAlignAddrLValue(
Alexey Bataev62b63b12015-03-10 07:28:44 +0000236 CGF.Builder.CreateAlignedLoad(
237 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
238 CGF.PointerAlignInBytes),
239 getThreadIDVariable()
240 ->getType()
241 ->castAs<PointerType>()
242 ->getPointeeType());
Alexey Bataev18095712014-10-10 12:19:54 +0000243}
244
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000245void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
246 // 1.2.2 OpenMP Language Terminology
247 // Structured block - An executable statement with a single entry at the
248 // top and a single exit at the bottom.
249 // The point of exit cannot be a branch out of the structured block.
250 // longjmp() and throw() must not violate the entry/exit criteria.
251 CGF.EHStack.pushTerminate();
252 {
253 CodeGenFunction::RunCleanupsScope Scope(CGF);
254 CodeGen(CGF);
255 }
256 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000257}
258
Alexey Bataev62b63b12015-03-10 07:28:44 +0000259LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
260 CodeGenFunction &CGF) {
261 return CGF.MakeNaturalAlignAddrLValue(
262 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
263 getThreadIDVariable()->getType());
264}
265
Alexey Bataev9959db52014-05-06 10:08:46 +0000266CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
Alexey Bataev62b63b12015-03-10 07:28:44 +0000267 : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000268 IdentTy = llvm::StructType::create(
269 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
270 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000271 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000272 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
Alexey Bataev23b69422014-06-18 07:08:49 +0000273 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
274 llvm::PointerType::getUnqual(CGM.Int32Ty)};
Alexey Bataev9959db52014-05-06 10:08:46 +0000275 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000276 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Alexey Bataev9959db52014-05-06 10:08:46 +0000277}
278
Alexey Bataev91797552015-03-18 04:13:55 +0000279void CGOpenMPRuntime::clear() {
280 InternalVars.clear();
281}
282
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000283llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction(
284 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
285 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000286 assert(ThreadIDVar->getType()->isPointerType() &&
287 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +0000288 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
289 CodeGenFunction CGF(CGM, true);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000290 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind);
Alexey Bataevd157d472015-06-24 03:35:38 +0000291 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev18095712014-10-10 12:19:54 +0000292 return CGF.GenerateCapturedStmtFunction(*CS);
293}
294
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000295llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
296 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
297 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000298 assert(!ThreadIDVar->getType()->isPointerType() &&
299 "thread id variable must be of type kmp_int32 for tasks");
300 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
301 CodeGenFunction CGF(CGM, true);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000302 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
303 InnermostKind);
Alexey Bataevd157d472015-06-24 03:35:38 +0000304 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000305 return CGF.GenerateCapturedStmtFunction(*CS);
306}
307
308llvm::Value *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000309CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000310 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000311 if (!Entry) {
312 if (!DefaultOpenMPPSource) {
313 // Initialize default location for psource field of ident_t structure of
314 // all ident_t objects. Format is ";file;function;line;column;;".
315 // Taken from
316 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
317 DefaultOpenMPPSource =
318 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;");
319 DefaultOpenMPPSource =
320 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
321 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000322 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
323 CGM.getModule(), IdentTy, /*isConstant*/ true,
324 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000325 DefaultOpenMPLocation->setUnnamedAddr(true);
Alexey Bataev9959db52014-05-06 10:08:46 +0000326
327 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000328 llvm::Constant *Values[] = {Zero,
329 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
330 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000331 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
332 DefaultOpenMPLocation->setInitializer(Init);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000333 OpenMPDefaultLocMap[Flags] = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000334 return DefaultOpenMPLocation;
335 }
336 return Entry;
337}
338
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000339llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
340 SourceLocation Loc,
341 OpenMPLocationFlags Flags) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000342 // If no debug info is generated - return global default location.
343 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
344 Loc.isInvalid())
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000345 return getOrCreateDefaultLocation(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000346
347 assert(CGF.CurFn && "No function in current CodeGenFunction.");
348
Alexey Bataev9959db52014-05-06 10:08:46 +0000349 llvm::Value *LocValue = nullptr;
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000350 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
351 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataev18095712014-10-10 12:19:54 +0000352 LocValue = I->second.DebugLoc;
Alexander Musmanc6388682014-12-15 07:07:06 +0000353 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
354 // GetOpenMPThreadID was called before this routine.
355 if (LocValue == nullptr) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000356 // Generate "ident_t .kmpc_loc.addr;"
357 llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr");
Alexey Bataev9959db52014-05-06 10:08:46 +0000358 AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy));
Alexey Bataev18095712014-10-10 12:19:54 +0000359 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
360 Elem.second.DebugLoc = AI;
Alexey Bataev9959db52014-05-06 10:08:46 +0000361 LocValue = AI;
362
363 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
364 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000365 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataev9959db52014-05-06 10:08:46 +0000366 llvm::ConstantExpr::getSizeOf(IdentTy),
367 CGM.PointerAlignInBytes);
368 }
369
370 // char **psource = &.kmpc_loc_<flags>.addr.psource;
David Blaikie1ed728c2015-04-05 22:45:47 +0000371 auto *PSource = CGF.Builder.CreateConstInBoundsGEP2_32(IdentTy, LocValue, 0,
372 IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000373
Alexey Bataevf002aca2014-05-30 05:48:40 +0000374 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
375 if (OMPDebugLoc == nullptr) {
376 SmallString<128> Buffer2;
377 llvm::raw_svector_ostream OS2(Buffer2);
378 // Build debug location
379 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
380 OS2 << ";" << PLoc.getFilename() << ";";
381 if (const FunctionDecl *FD =
382 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
383 OS2 << FD->getQualifiedNameAsString();
384 }
385 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
386 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
387 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000388 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000389 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000390 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
391
Alexey Bataev9959db52014-05-06 10:08:46 +0000392 return LocValue;
393}
394
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000395llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
396 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000397 assert(CGF.CurFn && "No function in current CodeGenFunction.");
398
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000399 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000400 // Check whether we've already cached a load of the thread id in this
401 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000402 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000403 if (I != OpenMPLocThreadIDMap.end()) {
404 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000405 if (ThreadID != nullptr)
406 return ThreadID;
407 }
408 if (auto OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000409 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000410 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000411 // Check if this an outlined function with thread id passed as argument.
412 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000413 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
414 // If value loaded in entry block, cache it and use it everywhere in
415 // function.
416 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
417 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
418 Elem.second.ThreadID = ThreadID;
419 }
420 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000421 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000422 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000423
424 // This is not an outlined function region - need to call __kmpc_int32
425 // kmpc_global_thread_num(ident_t *loc).
426 // Generate thread id value and cache this value for use across the
427 // function.
428 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
429 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
430 ThreadID =
431 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
432 emitUpdateLocation(CGF, Loc));
433 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
434 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000435 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000436}
437
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000438void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000439 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000440 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
441 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataev9959db52014-05-06 10:08:46 +0000442}
443
444llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
445 return llvm::PointerType::getUnqual(IdentTy);
446}
447
448llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
449 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
450}
451
452llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000453CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000454 llvm::Constant *RTLFn = nullptr;
455 switch (Function) {
456 case OMPRTL__kmpc_fork_call: {
457 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
458 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +0000459 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
460 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000461 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000462 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +0000463 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
464 break;
465 }
466 case OMPRTL__kmpc_global_thread_num: {
467 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +0000468 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000469 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000470 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +0000471 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
472 break;
473 }
Alexey Bataev97720002014-11-11 04:05:39 +0000474 case OMPRTL__kmpc_threadprivate_cached: {
475 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
476 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
477 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
478 CGM.VoidPtrTy, CGM.SizeTy,
479 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
480 llvm::FunctionType *FnTy =
481 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
482 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
483 break;
484 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000485 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000486 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
487 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000488 llvm::Type *TypeParams[] = {
489 getIdentTyPointerTy(), CGM.Int32Ty,
490 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
491 llvm::FunctionType *FnTy =
492 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
493 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
494 break;
495 }
Alexey Bataev97720002014-11-11 04:05:39 +0000496 case OMPRTL__kmpc_threadprivate_register: {
497 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
498 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
499 // typedef void *(*kmpc_ctor)(void *);
500 auto KmpcCtorTy =
501 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
502 /*isVarArg*/ false)->getPointerTo();
503 // typedef void *(*kmpc_cctor)(void *, void *);
504 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
505 auto KmpcCopyCtorTy =
506 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
507 /*isVarArg*/ false)->getPointerTo();
508 // typedef void (*kmpc_dtor)(void *);
509 auto KmpcDtorTy =
510 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
511 ->getPointerTo();
512 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
513 KmpcCopyCtorTy, KmpcDtorTy};
514 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
515 /*isVarArg*/ false);
516 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
517 break;
518 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000519 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000520 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
521 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000522 llvm::Type *TypeParams[] = {
523 getIdentTyPointerTy(), CGM.Int32Ty,
524 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
525 llvm::FunctionType *FnTy =
526 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
527 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
528 break;
529 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000530 case OMPRTL__kmpc_cancel_barrier: {
531 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
532 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000533 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
534 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000535 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
536 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000537 break;
538 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000539 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +0000540 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000541 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
542 llvm::FunctionType *FnTy =
543 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
544 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
545 break;
546 }
Alexander Musmanc6388682014-12-15 07:07:06 +0000547 case OMPRTL__kmpc_for_static_fini: {
548 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
549 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
550 llvm::FunctionType *FnTy =
551 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
552 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
553 break;
554 }
Alexey Bataevb2059782014-10-13 08:23:51 +0000555 case OMPRTL__kmpc_push_num_threads: {
556 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
557 // kmp_int32 num_threads)
558 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
559 CGM.Int32Ty};
560 llvm::FunctionType *FnTy =
561 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
562 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
563 break;
564 }
Alexey Bataevd74d0602014-10-13 06:02:40 +0000565 case OMPRTL__kmpc_serialized_parallel: {
566 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
567 // global_tid);
568 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
569 llvm::FunctionType *FnTy =
570 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
571 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
572 break;
573 }
574 case OMPRTL__kmpc_end_serialized_parallel: {
575 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
576 // global_tid);
577 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
578 llvm::FunctionType *FnTy =
579 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
580 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
581 break;
582 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000583 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000584 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000585 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
586 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000587 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000588 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
589 break;
590 }
Alexey Bataev8d690652014-12-04 07:23:53 +0000591 case OMPRTL__kmpc_master: {
592 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
593 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
594 llvm::FunctionType *FnTy =
595 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
596 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
597 break;
598 }
599 case OMPRTL__kmpc_end_master: {
600 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
601 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
602 llvm::FunctionType *FnTy =
603 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
604 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
605 break;
606 }
Alexey Bataev9f797f32015-02-05 05:57:51 +0000607 case OMPRTL__kmpc_omp_taskyield: {
608 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
609 // int end_part);
610 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
611 llvm::FunctionType *FnTy =
612 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
613 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
614 break;
615 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +0000616 case OMPRTL__kmpc_single: {
617 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
618 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
619 llvm::FunctionType *FnTy =
620 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
621 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
622 break;
623 }
624 case OMPRTL__kmpc_end_single: {
625 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
626 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
627 llvm::FunctionType *FnTy =
628 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
629 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
630 break;
631 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000632 case OMPRTL__kmpc_omp_task_alloc: {
633 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
634 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
635 // kmp_routine_entry_t *task_entry);
636 assert(KmpRoutineEntryPtrTy != nullptr &&
637 "Type kmp_routine_entry_t must be created.");
638 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
639 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
640 // Return void * and then cast to particular kmp_task_t type.
641 llvm::FunctionType *FnTy =
642 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
643 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
644 break;
645 }
646 case OMPRTL__kmpc_omp_task: {
647 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
648 // *new_task);
649 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
650 CGM.VoidPtrTy};
651 llvm::FunctionType *FnTy =
652 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
653 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
654 break;
655 }
Alexey Bataeva63048e2015-03-23 06:18:07 +0000656 case OMPRTL__kmpc_copyprivate: {
657 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +0000658 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +0000659 // kmp_int32 didit);
660 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
661 auto *CpyFnTy =
662 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +0000663 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +0000664 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
665 CGM.Int32Ty};
666 llvm::FunctionType *FnTy =
667 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
668 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
669 break;
670 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +0000671 case OMPRTL__kmpc_reduce: {
672 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
673 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
674 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
675 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
676 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
677 /*isVarArg=*/false);
678 llvm::Type *TypeParams[] = {
679 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
680 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
681 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
682 llvm::FunctionType *FnTy =
683 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
684 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
685 break;
686 }
687 case OMPRTL__kmpc_reduce_nowait: {
688 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
689 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
690 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
691 // *lck);
692 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
693 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
694 /*isVarArg=*/false);
695 llvm::Type *TypeParams[] = {
696 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
697 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
698 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
699 llvm::FunctionType *FnTy =
700 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
701 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
702 break;
703 }
704 case OMPRTL__kmpc_end_reduce: {
705 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
706 // kmp_critical_name *lck);
707 llvm::Type *TypeParams[] = {
708 getIdentTyPointerTy(), CGM.Int32Ty,
709 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
710 llvm::FunctionType *FnTy =
711 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
712 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
713 break;
714 }
715 case OMPRTL__kmpc_end_reduce_nowait: {
716 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
717 // kmp_critical_name *lck);
718 llvm::Type *TypeParams[] = {
719 getIdentTyPointerTy(), CGM.Int32Ty,
720 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
721 llvm::FunctionType *FnTy =
722 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
723 RTLFn =
724 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
725 break;
726 }
Alexey Bataev1d677132015-04-22 13:57:31 +0000727 case OMPRTL__kmpc_omp_task_begin_if0: {
728 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
729 // *new_task);
730 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
731 CGM.VoidPtrTy};
732 llvm::FunctionType *FnTy =
733 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
734 RTLFn =
735 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
736 break;
737 }
738 case OMPRTL__kmpc_omp_task_complete_if0: {
739 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
740 // *new_task);
741 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
742 CGM.VoidPtrTy};
743 llvm::FunctionType *FnTy =
744 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
745 RTLFn = CGM.CreateRuntimeFunction(FnTy,
746 /*Name=*/"__kmpc_omp_task_complete_if0");
747 break;
748 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000749 case OMPRTL__kmpc_ordered: {
750 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
751 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
752 llvm::FunctionType *FnTy =
753 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
754 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
755 break;
756 }
757 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +0000758 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000759 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
760 llvm::FunctionType *FnTy =
761 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
762 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
763 break;
764 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +0000765 case OMPRTL__kmpc_omp_taskwait: {
766 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
767 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
768 llvm::FunctionType *FnTy =
769 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
770 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
771 break;
772 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +0000773 case OMPRTL__kmpc_taskgroup: {
774 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
775 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
776 llvm::FunctionType *FnTy =
777 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
778 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
779 break;
780 }
781 case OMPRTL__kmpc_end_taskgroup: {
782 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
783 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
784 llvm::FunctionType *FnTy =
785 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
786 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
787 break;
788 }
Alexey Bataev7f210c62015-06-18 13:40:03 +0000789 case OMPRTL__kmpc_push_proc_bind: {
790 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
791 // int proc_bind)
792 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
793 llvm::FunctionType *FnTy =
794 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
795 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
796 break;
797 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +0000798 case OMPRTL__kmpc_omp_task_with_deps: {
799 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
800 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
801 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
802 llvm::Type *TypeParams[] = {
803 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
804 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
805 llvm::FunctionType *FnTy =
806 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
807 RTLFn =
808 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
809 break;
810 }
811 case OMPRTL__kmpc_omp_wait_deps: {
812 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
813 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
814 // kmp_depend_info_t *noalias_dep_list);
815 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
816 CGM.Int32Ty, CGM.VoidPtrTy,
817 CGM.Int32Ty, CGM.VoidPtrTy};
818 llvm::FunctionType *FnTy =
819 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
820 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
821 break;
822 }
Alexey Bataev0f34da12015-07-02 04:17:07 +0000823 case OMPRTL__kmpc_cancellationpoint: {
824 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
825 // global_tid, kmp_int32 cncl_kind)
826 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
827 llvm::FunctionType *FnTy =
828 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
829 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
830 break;
831 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +0000832 case OMPRTL__kmpc_cancel: {
833 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
834 // kmp_int32 cncl_kind)
835 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
836 llvm::FunctionType *FnTy =
837 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
838 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
839 break;
840 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000841 }
842 return RTLFn;
843}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000844
Alexander Musman21212e42015-03-13 10:38:23 +0000845llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
846 bool IVSigned) {
847 assert((IVSize == 32 || IVSize == 64) &&
848 "IV size is not compatible with the omp runtime");
849 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
850 : "__kmpc_for_static_init_4u")
851 : (IVSigned ? "__kmpc_for_static_init_8"
852 : "__kmpc_for_static_init_8u");
853 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
854 auto PtrTy = llvm::PointerType::getUnqual(ITy);
855 llvm::Type *TypeParams[] = {
856 getIdentTyPointerTy(), // loc
857 CGM.Int32Ty, // tid
858 CGM.Int32Ty, // schedtype
859 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
860 PtrTy, // p_lower
861 PtrTy, // p_upper
862 PtrTy, // p_stride
863 ITy, // incr
864 ITy // chunk
865 };
866 llvm::FunctionType *FnTy =
867 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
868 return CGM.CreateRuntimeFunction(FnTy, Name);
869}
870
Alexander Musman92bdaab2015-03-12 13:37:50 +0000871llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
872 bool IVSigned) {
873 assert((IVSize == 32 || IVSize == 64) &&
874 "IV size is not compatible with the omp runtime");
875 auto Name =
876 IVSize == 32
877 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
878 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
879 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
880 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
881 CGM.Int32Ty, // tid
882 CGM.Int32Ty, // schedtype
883 ITy, // lower
884 ITy, // upper
885 ITy, // stride
886 ITy // chunk
887 };
888 llvm::FunctionType *FnTy =
889 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
890 return CGM.CreateRuntimeFunction(FnTy, Name);
891}
892
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000893llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
894 bool IVSigned) {
895 assert((IVSize == 32 || IVSize == 64) &&
896 "IV size is not compatible with the omp runtime");
897 auto Name =
898 IVSize == 32
899 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
900 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
901 llvm::Type *TypeParams[] = {
902 getIdentTyPointerTy(), // loc
903 CGM.Int32Ty, // tid
904 };
905 llvm::FunctionType *FnTy =
906 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
907 return CGM.CreateRuntimeFunction(FnTy, Name);
908}
909
Alexander Musman92bdaab2015-03-12 13:37:50 +0000910llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
911 bool IVSigned) {
912 assert((IVSize == 32 || IVSize == 64) &&
913 "IV size is not compatible with the omp runtime");
914 auto Name =
915 IVSize == 32
916 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
917 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
918 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
919 auto PtrTy = llvm::PointerType::getUnqual(ITy);
920 llvm::Type *TypeParams[] = {
921 getIdentTyPointerTy(), // loc
922 CGM.Int32Ty, // tid
923 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
924 PtrTy, // p_lower
925 PtrTy, // p_upper
926 PtrTy // p_stride
927 };
928 llvm::FunctionType *FnTy =
929 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
930 return CGM.CreateRuntimeFunction(FnTy, Name);
931}
932
Alexey Bataev97720002014-11-11 04:05:39 +0000933llvm::Constant *
934CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +0000935 assert(!CGM.getLangOpts().OpenMPUseTLS ||
936 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +0000937 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000938 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +0000939 Twine(CGM.getMangledName(VD)) + ".cache.");
940}
941
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000942llvm::Value *CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
943 const VarDecl *VD,
944 llvm::Value *VDAddr,
945 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +0000946 if (CGM.getLangOpts().OpenMPUseTLS &&
947 CGM.getContext().getTargetInfo().isTLSSupported())
948 return VDAddr;
949
Alexey Bataev97720002014-11-11 04:05:39 +0000950 auto VarTy = VDAddr->getType()->getPointerElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000951 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev97720002014-11-11 04:05:39 +0000952 CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy),
953 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
954 getOrCreateThreadPrivateCache(VD)};
955 return CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000956 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args);
Alexey Bataev97720002014-11-11 04:05:39 +0000957}
958
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000959void CGOpenMPRuntime::emitThreadPrivateVarInit(
Alexey Bataev97720002014-11-11 04:05:39 +0000960 CodeGenFunction &CGF, llvm::Value *VDAddr, llvm::Value *Ctor,
961 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
962 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
963 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000964 auto OMPLoc = emitUpdateLocation(CGF, Loc);
965 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +0000966 OMPLoc);
967 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
968 // to register constructor/destructor for variable.
969 llvm::Value *Args[] = {OMPLoc,
970 CGF.Builder.CreatePointerCast(VDAddr, CGM.VoidPtrTy),
971 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000972 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000973 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +0000974}
975
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000976llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
Alexey Bataev97720002014-11-11 04:05:39 +0000977 const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc,
978 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +0000979 if (CGM.getLangOpts().OpenMPUseTLS &&
980 CGM.getContext().getTargetInfo().isTLSSupported())
981 return nullptr;
982
Alexey Bataev97720002014-11-11 04:05:39 +0000983 VD = VD->getDefinition(CGM.getContext());
984 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
985 ThreadPrivateWithDefinition.insert(VD);
986 QualType ASTTy = VD->getType();
987
988 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
989 auto Init = VD->getAnyInitializer();
990 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
991 // Generate function that re-emits the declaration's initializer into the
992 // threadprivate copy of the variable VD
993 CodeGenFunction CtorCGF(CGM);
994 FunctionArgList Args;
995 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
996 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
997 Args.push_back(&Dst);
998
999 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1000 CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(),
1001 /*isVariadic=*/false);
1002 auto FTy = CGM.getTypes().GetFunctionType(FI);
1003 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
1004 FTy, ".__kmpc_global_ctor_.", Loc);
1005 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1006 Args, SourceLocation());
1007 auto ArgVal = CtorCGF.EmitLoadOfScalar(
1008 CtorCGF.GetAddrOfLocalVar(&Dst),
1009 /*Volatile=*/false, CGM.PointerAlignInBytes,
1010 CGM.getContext().VoidPtrTy, Dst.getLocation());
1011 auto Arg = CtorCGF.Builder.CreatePointerCast(
1012 ArgVal,
1013 CtorCGF.ConvertTypeForMem(CGM.getContext().getPointerType(ASTTy)));
1014 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1015 /*IsInitializer=*/true);
1016 ArgVal = CtorCGF.EmitLoadOfScalar(
1017 CtorCGF.GetAddrOfLocalVar(&Dst),
1018 /*Volatile=*/false, CGM.PointerAlignInBytes,
1019 CGM.getContext().VoidPtrTy, Dst.getLocation());
1020 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1021 CtorCGF.FinishFunction();
1022 Ctor = Fn;
1023 }
1024 if (VD->getType().isDestructedType() != QualType::DK_none) {
1025 // Generate function that emits destructor call for the threadprivate copy
1026 // of the variable VD
1027 CodeGenFunction DtorCGF(CGM);
1028 FunctionArgList Args;
1029 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1030 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1031 Args.push_back(&Dst);
1032
1033 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1034 CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(),
1035 /*isVariadic=*/false);
1036 auto FTy = CGM.getTypes().GetFunctionType(FI);
1037 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
1038 FTy, ".__kmpc_global_dtor_.", Loc);
1039 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1040 SourceLocation());
1041 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1042 DtorCGF.GetAddrOfLocalVar(&Dst),
1043 /*Volatile=*/false, CGM.PointerAlignInBytes,
1044 CGM.getContext().VoidPtrTy, Dst.getLocation());
1045 DtorCGF.emitDestroy(ArgVal, ASTTy,
1046 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1047 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1048 DtorCGF.FinishFunction();
1049 Dtor = Fn;
1050 }
1051 // Do not emit init function if it is not required.
1052 if (!Ctor && !Dtor)
1053 return nullptr;
1054
1055 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1056 auto CopyCtorTy =
1057 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1058 /*isVarArg=*/false)->getPointerTo();
1059 // Copying constructor for the threadprivate variable.
1060 // Must be NULL - reserved by runtime, but currently it requires that this
1061 // parameter is always NULL. Otherwise it fires assertion.
1062 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1063 if (Ctor == nullptr) {
1064 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1065 /*isVarArg=*/false)->getPointerTo();
1066 Ctor = llvm::Constant::getNullValue(CtorTy);
1067 }
1068 if (Dtor == nullptr) {
1069 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1070 /*isVarArg=*/false)->getPointerTo();
1071 Dtor = llvm::Constant::getNullValue(DtorTy);
1072 }
1073 if (!CGF) {
1074 auto InitFunctionTy =
1075 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1076 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
1077 InitFunctionTy, ".__omp_threadprivate_init_.");
1078 CodeGenFunction InitCGF(CGM);
1079 FunctionArgList ArgList;
1080 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1081 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1082 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001083 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001084 InitCGF.FinishFunction();
1085 return InitFunction;
1086 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001087 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001088 }
1089 return nullptr;
1090}
1091
Alexey Bataev1d677132015-04-22 13:57:31 +00001092/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1093/// function. Here is the logic:
1094/// if (Cond) {
1095/// ThenGen();
1096/// } else {
1097/// ElseGen();
1098/// }
1099static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1100 const RegionCodeGenTy &ThenGen,
1101 const RegionCodeGenTy &ElseGen) {
1102 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1103
1104 // If the condition constant folds and can be elided, try to avoid emitting
1105 // the condition and the dead arm of the if/else.
1106 bool CondConstant;
1107 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
1108 CodeGenFunction::RunCleanupsScope Scope(CGF);
1109 if (CondConstant) {
1110 ThenGen(CGF);
1111 } else {
1112 ElseGen(CGF);
1113 }
1114 return;
1115 }
1116
1117 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1118 // emit the conditional branch.
1119 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1120 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1121 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1122 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1123
1124 // Emit the 'then' code.
1125 CGF.EmitBlock(ThenBlock);
1126 {
1127 CodeGenFunction::RunCleanupsScope ThenScope(CGF);
1128 ThenGen(CGF);
1129 }
1130 CGF.EmitBranch(ContBlock);
1131 // Emit the 'else' code if present.
1132 {
1133 // There is no need to emit line number for unconditional branch.
1134 auto NL = ApplyDebugLocation::CreateEmpty(CGF);
1135 CGF.EmitBlock(ElseBlock);
1136 }
1137 {
1138 CodeGenFunction::RunCleanupsScope ThenScope(CGF);
1139 ElseGen(CGF);
1140 }
1141 {
1142 // There is no need to emit line number for unconditional branch.
1143 auto NL = ApplyDebugLocation::CreateEmpty(CGF);
1144 CGF.EmitBranch(ContBlock);
1145 }
1146 // Emit the continuation block for code after the if.
1147 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001148}
1149
Alexey Bataev1d677132015-04-22 13:57:31 +00001150void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1151 llvm::Value *OutlinedFn,
1152 llvm::Value *CapturedStruct,
1153 const Expr *IfCond) {
1154 auto *RTLoc = emitUpdateLocation(CGF, Loc);
1155 auto &&ThenGen =
1156 [this, OutlinedFn, CapturedStruct, RTLoc](CodeGenFunction &CGF) {
1157 // Build call __kmpc_fork_call(loc, 1, microtask,
1158 // captured_struct/*context*/)
1159 llvm::Value *Args[] = {
1160 RTLoc,
1161 CGF.Builder.getInt32(
1162 1), // Number of arguments after 'microtask' argument
1163 // (there is only one additional argument - 'context')
1164 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()),
1165 CGF.EmitCastToVoidPtr(CapturedStruct)};
1166 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
1167 CGF.EmitRuntimeCall(RTLFn, Args);
1168 };
1169 auto &&ElseGen = [this, OutlinedFn, CapturedStruct, RTLoc, Loc](
1170 CodeGenFunction &CGF) {
1171 auto ThreadID = getThreadID(CGF, Loc);
1172 // Build calls:
1173 // __kmpc_serialized_parallel(&Loc, GTid);
1174 llvm::Value *Args[] = {RTLoc, ThreadID};
1175 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel),
1176 Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001177
Alexey Bataev1d677132015-04-22 13:57:31 +00001178 // OutlinedFn(&GTid, &zero, CapturedStruct);
1179 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
1180 auto Int32Ty = CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32,
1181 /*Signed*/ true);
1182 auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr");
1183 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
1184 llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct};
1185 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001186
Alexey Bataev1d677132015-04-22 13:57:31 +00001187 // __kmpc_end_serialized_parallel(&Loc, GTid);
1188 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID};
1189 CGF.EmitRuntimeCall(
1190 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs);
1191 };
1192 if (IfCond) {
1193 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
1194 } else {
1195 CodeGenFunction::RunCleanupsScope Scope(CGF);
1196 ThenGen(CGF);
1197 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001198}
1199
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001200// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001201// thread-ID variable (it is passed in a first argument of the outlined function
1202// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1203// regular serial code region, get thread ID by calling kmp_int32
1204// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1205// return the address of that temp.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001206llvm::Value *CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
Alexey Bataevd74d0602014-10-13 06:02:40 +00001207 SourceLocation Loc) {
1208 if (auto OMPRegionInfo =
1209 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001210 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001211 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001212
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001213 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001214 auto Int32Ty =
1215 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1216 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1217 CGF.EmitStoreOfScalar(ThreadID,
1218 CGF.MakeNaturalAlignAddrLValue(ThreadIDTemp, Int32Ty));
1219
1220 return ThreadIDTemp;
1221}
1222
Alexey Bataev97720002014-11-11 04:05:39 +00001223llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001224CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001225 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001226 SmallString<256> Buffer;
1227 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001228 Out << Name;
1229 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001230 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1231 if (Elem.second) {
1232 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001233 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001234 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001235 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001236
David Blaikie13156b62014-11-19 03:06:06 +00001237 return Elem.second = new llvm::GlobalVariable(
1238 CGM.getModule(), Ty, /*IsConstant*/ false,
1239 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1240 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001241}
1242
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001243llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001244 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001245 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001246}
1247
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001248namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00001249template <size_t N> class CallEndCleanup final : public EHScopeStack::Cleanup {
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001250 llvm::Value *Callee;
Alexey Bataeva744ff52015-05-05 09:24:37 +00001251 llvm::Value *Args[N];
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001252
1253public:
Alexey Bataeva744ff52015-05-05 09:24:37 +00001254 CallEndCleanup(llvm::Value *Callee, ArrayRef<llvm::Value *> CleanupArgs)
1255 : Callee(Callee) {
1256 assert(CleanupArgs.size() == N);
1257 std::copy(CleanupArgs.begin(), CleanupArgs.end(), std::begin(Args));
1258 }
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001259 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
1260 CGF.EmitRuntimeCall(Callee, Args);
1261 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001262};
1263} // namespace
1264
1265void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1266 StringRef CriticalName,
1267 const RegionCodeGenTy &CriticalOpGen,
1268 SourceLocation Loc) {
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001269 // __kmpc_critical(ident_t *, gtid, Lock);
1270 // CriticalOpGen();
1271 // __kmpc_end_critical(ident_t *, gtid, Lock);
1272 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001273 {
1274 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001275 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1276 getCriticalRegionLock(CriticalName)};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001277 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001278 // Build a call to __kmpc_end_critical
Alexey Bataeva744ff52015-05-05 09:24:37 +00001279 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001280 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
1281 llvm::makeArrayRef(Args));
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001282 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001283 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001284}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001285
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001286static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001287 OpenMPDirectiveKind Kind, SourceLocation Loc,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001288 const RegionCodeGenTy &BodyOpGen) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001289 llvm::Value *CallBool = CGF.EmitScalarConversion(
1290 IfCond,
1291 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001292 CGF.getContext().BoolTy, Loc);
Alexey Bataev8d690652014-12-04 07:23:53 +00001293
1294 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1295 auto *ContBlock = CGF.createBasicBlock("omp_if.end");
1296 // Generate the branch (If-stmt)
1297 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1298 CGF.EmitBlock(ThenBlock);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001299 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen);
Alexey Bataev8d690652014-12-04 07:23:53 +00001300 // Emit the rest of bblocks/branches
1301 CGF.EmitBranch(ContBlock);
1302 CGF.EmitBlock(ContBlock, true);
1303}
1304
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001305void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001306 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001307 SourceLocation Loc) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001308 // if(__kmpc_master(ident_t *, gtid)) {
1309 // MasterOpGen();
1310 // __kmpc_end_master(ident_t *, gtid);
1311 // }
1312 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001313 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001314 auto *IsMaster =
1315 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
Alexey Bataeva744ff52015-05-05 09:24:37 +00001316 typedef CallEndCleanup<std::extent<decltype(Args)>::value>
1317 MasterCallEndCleanup;
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001318 emitIfStmt(
1319 CGF, IsMaster, OMPD_master, Loc, [&](CodeGenFunction &CGF) -> void {
1320 CodeGenFunction::RunCleanupsScope Scope(CGF);
1321 CGF.EHStack.pushCleanup<MasterCallEndCleanup>(
1322 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
1323 llvm::makeArrayRef(Args));
1324 MasterOpGen(CGF);
1325 });
Alexey Bataev8d690652014-12-04 07:23:53 +00001326}
1327
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001328void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
1329 SourceLocation Loc) {
Alexey Bataev9f797f32015-02-05 05:57:51 +00001330 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
1331 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001332 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00001333 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001334 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev9f797f32015-02-05 05:57:51 +00001335}
1336
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001337void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
1338 const RegionCodeGenTy &TaskgroupOpGen,
1339 SourceLocation Loc) {
1340 // __kmpc_taskgroup(ident_t *, gtid);
1341 // TaskgroupOpGen();
1342 // __kmpc_end_taskgroup(ident_t *, gtid);
1343 // Prepare arguments and build a call to __kmpc_taskgroup
1344 {
1345 CodeGenFunction::RunCleanupsScope Scope(CGF);
1346 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1347 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args);
1348 // Build a call to __kmpc_end_taskgroup
1349 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
1350 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
1351 llvm::makeArrayRef(Args));
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001352 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001353 }
1354}
1355
Alexey Bataeva63048e2015-03-23 06:18:07 +00001356static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00001357 CodeGenModule &CGM, llvm::Type *ArgsType,
1358 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
1359 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00001360 auto &C = CGM.getContext();
1361 // void copy_func(void *LHSArg, void *RHSArg);
1362 FunctionArgList Args;
1363 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1364 C.VoidPtrTy);
1365 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1366 C.VoidPtrTy);
1367 Args.push_back(&LHSArg);
1368 Args.push_back(&RHSArg);
1369 FunctionType::ExtInfo EI;
1370 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1371 C.VoidTy, Args, EI, /*isVariadic=*/false);
1372 auto *Fn = llvm::Function::Create(
1373 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
1374 ".omp.copyprivate.copy_func", &CGM.getModule());
1375 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
1376 CodeGenFunction CGF(CGM);
1377 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00001378 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001379 // Src = (void*[n])(RHSArg);
1380 auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1381 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
1382 CGF.PointerAlignInBytes),
1383 ArgsType);
1384 auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1385 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
1386 CGF.PointerAlignInBytes),
1387 ArgsType);
1388 // *(Type0*)Dst[0] = *(Type0*)Src[0];
1389 // *(Type1*)Dst[1] = *(Type1*)Src[1];
1390 // ...
1391 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00001392 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataev420d45b2015-04-14 05:11:24 +00001393 auto *DestAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1394 CGF.Builder.CreateAlignedLoad(
1395 CGF.Builder.CreateStructGEP(nullptr, LHS, I),
1396 CGM.PointerAlignInBytes),
1397 CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
1398 auto *SrcAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1399 CGF.Builder.CreateAlignedLoad(
1400 CGF.Builder.CreateStructGEP(nullptr, RHS, I),
1401 CGM.PointerAlignInBytes),
1402 CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001403 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
1404 QualType Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001405 CGF.EmitOMPCopy(CGF, Type, DestAddr, SrcAddr,
Alexey Bataev420d45b2015-04-14 05:11:24 +00001406 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()),
1407 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()),
1408 AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001409 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001410 CGF.FinishFunction();
1411 return Fn;
1412}
1413
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001414void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001415 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001416 SourceLocation Loc,
1417 ArrayRef<const Expr *> CopyprivateVars,
1418 ArrayRef<const Expr *> SrcExprs,
1419 ArrayRef<const Expr *> DstExprs,
1420 ArrayRef<const Expr *> AssignmentOps) {
1421 assert(CopyprivateVars.size() == SrcExprs.size() &&
1422 CopyprivateVars.size() == DstExprs.size() &&
1423 CopyprivateVars.size() == AssignmentOps.size());
1424 auto &C = CGM.getContext();
1425 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001426 // if(__kmpc_single(ident_t *, gtid)) {
1427 // SingleOpGen();
1428 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001429 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001430 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001431 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1432 // <copy_func>, did_it);
1433
1434 llvm::AllocaInst *DidIt = nullptr;
1435 if (!CopyprivateVars.empty()) {
1436 // int32 did_it = 0;
1437 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1438 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
Alexey Bataev66beaa92015-04-30 03:47:32 +00001439 CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(0), DidIt,
1440 DidIt->getAlignment());
Alexey Bataeva63048e2015-03-23 06:18:07 +00001441 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001442 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001443 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001444 auto *IsSingle =
1445 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
Alexey Bataeva744ff52015-05-05 09:24:37 +00001446 typedef CallEndCleanup<std::extent<decltype(Args)>::value>
1447 SingleCallEndCleanup;
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001448 emitIfStmt(
1449 CGF, IsSingle, OMPD_single, Loc, [&](CodeGenFunction &CGF) -> void {
1450 CodeGenFunction::RunCleanupsScope Scope(CGF);
1451 CGF.EHStack.pushCleanup<SingleCallEndCleanup>(
1452 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
1453 llvm::makeArrayRef(Args));
1454 SingleOpGen(CGF);
1455 if (DidIt) {
1456 // did_it = 1;
1457 CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(1), DidIt,
1458 DidIt->getAlignment());
1459 }
1460 });
Alexey Bataeva63048e2015-03-23 06:18:07 +00001461 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1462 // <copy_func>, did_it);
1463 if (DidIt) {
1464 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
1465 auto CopyprivateArrayTy =
1466 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
1467 /*IndexTypeQuals=*/0);
1468 // Create a list of all private variables for copyprivate.
1469 auto *CopyprivateList =
1470 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
1471 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
David Blaikie1ed728c2015-04-05 22:45:47 +00001472 auto *Elem = CGF.Builder.CreateStructGEP(
1473 CopyprivateList->getAllocatedType(), CopyprivateList, I);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001474 CGF.Builder.CreateAlignedStore(
1475 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1476 CGF.EmitLValue(CopyprivateVars[I]).getAddress(), CGF.VoidPtrTy),
1477 Elem, CGM.PointerAlignInBytes);
1478 }
1479 // Build function that copies private values from single region to all other
1480 // threads in the corresponding parallel region.
1481 auto *CpyFn = emitCopyprivateCopyFunction(
1482 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00001483 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001484 auto *BufSize = llvm::ConstantInt::get(
1485 CGM.SizeTy, C.getTypeSizeInChars(CopyprivateArrayTy).getQuantity());
Alexey Bataeva63048e2015-03-23 06:18:07 +00001486 auto *CL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
1487 CGF.VoidPtrTy);
1488 auto *DidItVal =
1489 CGF.Builder.CreateAlignedLoad(DidIt, CGF.PointerAlignInBytes);
1490 llvm::Value *Args[] = {
1491 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
1492 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00001493 BufSize, // size_t <buf_size>
Alexey Bataeva63048e2015-03-23 06:18:07 +00001494 CL, // void *<copyprivate list>
1495 CpyFn, // void (*) (void *, void *) <copy_func>
1496 DidItVal // i32 did_it
1497 };
1498 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
1499 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001500}
1501
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001502void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
1503 const RegionCodeGenTy &OrderedOpGen,
1504 SourceLocation Loc) {
1505 // __kmpc_ordered(ident_t *, gtid);
1506 // OrderedOpGen();
1507 // __kmpc_end_ordered(ident_t *, gtid);
1508 // Prepare arguments and build a call to __kmpc_ordered
1509 {
1510 CodeGenFunction::RunCleanupsScope Scope(CGF);
1511 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1512 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_ordered), Args);
1513 // Build a call to __kmpc_end_ordered
Alexey Bataeva744ff52015-05-05 09:24:37 +00001514 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001515 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered),
1516 llvm::makeArrayRef(Args));
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001517 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001518 }
1519}
1520
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001521void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001522 OpenMPDirectiveKind Kind,
1523 bool CheckForCancel) {
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001524 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001525 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataevf2685682015-03-30 04:30:22 +00001526 OpenMPLocationFlags Flags = OMP_IDENT_KMPC;
1527 if (Kind == OMPD_for) {
1528 Flags =
1529 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_FOR);
1530 } else if (Kind == OMPD_sections) {
1531 Flags = static_cast<OpenMPLocationFlags>(Flags |
1532 OMP_IDENT_BARRIER_IMPL_SECTIONS);
1533 } else if (Kind == OMPD_single) {
1534 Flags =
1535 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_SINGLE);
1536 } else if (Kind == OMPD_barrier) {
1537 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_EXPL);
1538 } else {
1539 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL);
1540 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001541 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
1542 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001543 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
1544 getThreadID(CGF, Loc)};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001545 if (auto *OMPRegionInfo =
1546 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1547 auto CancelDestination =
1548 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
1549 if (CancelDestination.isValid()) {
1550 auto *Result = CGF.EmitRuntimeCall(
1551 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
1552 if (CheckForCancel) {
1553 // if (__kmpc_cancel_barrier()) {
1554 // exit from construct;
1555 // }
1556 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
1557 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
1558 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
1559 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
1560 CGF.EmitBlock(ExitBB);
1561 // exit from construct;
1562 CGF.EmitBranchThroughCleanup(CancelDestination);
1563 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
1564 }
1565 return;
1566 }
1567 }
1568 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001569}
1570
Alexander Musmanc6388682014-12-15 07:07:06 +00001571/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
1572/// the enum sched_type in kmp.h).
1573enum OpenMPSchedType {
1574 /// \brief Lower bound for default (unordered) versions.
1575 OMP_sch_lower = 32,
1576 OMP_sch_static_chunked = 33,
1577 OMP_sch_static = 34,
1578 OMP_sch_dynamic_chunked = 35,
1579 OMP_sch_guided_chunked = 36,
1580 OMP_sch_runtime = 37,
1581 OMP_sch_auto = 38,
1582 /// \brief Lower bound for 'ordered' versions.
1583 OMP_ord_lower = 64,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001584 OMP_ord_static_chunked = 65,
1585 OMP_ord_static = 66,
1586 OMP_ord_dynamic_chunked = 67,
1587 OMP_ord_guided_chunked = 68,
1588 OMP_ord_runtime = 69,
1589 OMP_ord_auto = 70,
1590 OMP_sch_default = OMP_sch_static,
Alexander Musmanc6388682014-12-15 07:07:06 +00001591};
1592
1593/// \brief Map the OpenMP loop schedule to the runtime enumeration.
1594static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001595 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001596 switch (ScheduleKind) {
1597 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001598 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
1599 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00001600 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001601 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00001602 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001603 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00001604 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001605 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
1606 case OMPC_SCHEDULE_auto:
1607 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00001608 case OMPC_SCHEDULE_unknown:
1609 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001610 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00001611 }
1612 llvm_unreachable("Unexpected runtime schedule");
1613}
1614
1615bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
1616 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001617 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00001618 return Schedule == OMP_sch_static;
1619}
1620
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001621bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001622 auto Schedule =
1623 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001624 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
1625 return Schedule != OMP_sch_static;
1626}
1627
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001628void CGOpenMPRuntime::emitForInit(CodeGenFunction &CGF, SourceLocation Loc,
1629 OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001630 unsigned IVSize, bool IVSigned, bool Ordered,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001631 llvm::Value *IL, llvm::Value *LB,
1632 llvm::Value *UB, llvm::Value *ST,
1633 llvm::Value *Chunk) {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001634 OpenMPSchedType Schedule =
1635 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
1636 if (Ordered ||
1637 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
1638 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked)) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00001639 // Call __kmpc_dispatch_init(
1640 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
1641 // kmp_int[32|64] lower, kmp_int[32|64] upper,
1642 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00001643
Alexander Musman92bdaab2015-03-12 13:37:50 +00001644 // If the Chunk was not specified in the clause - use default value 1.
1645 if (Chunk == nullptr)
1646 Chunk = CGF.Builder.getIntN(IVSize, 1);
1647 llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1648 getThreadID(CGF, Loc),
1649 CGF.Builder.getInt32(Schedule), // Schedule type
1650 CGF.Builder.getIntN(IVSize, 0), // Lower
1651 UB, // Upper
1652 CGF.Builder.getIntN(IVSize, 1), // Stride
1653 Chunk // Chunk
1654 };
1655 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
1656 } else {
1657 // Call __kmpc_for_static_init(
1658 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
1659 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
1660 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
1661 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
1662 if (Chunk == nullptr) {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001663 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static) &&
Alexander Musman92bdaab2015-03-12 13:37:50 +00001664 "expected static non-chunked schedule");
1665 // If the Chunk was not specified in the clause - use default value 1.
1666 Chunk = CGF.Builder.getIntN(IVSize, 1);
1667 } else
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001668 assert((Schedule == OMP_sch_static_chunked ||
1669 Schedule == OMP_ord_static_chunked) &&
Alexander Musman92bdaab2015-03-12 13:37:50 +00001670 "expected static chunked schedule");
1671 llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1672 getThreadID(CGF, Loc),
1673 CGF.Builder.getInt32(Schedule), // Schedule type
1674 IL, // &isLastIter
1675 LB, // &LB
1676 UB, // &UB
1677 ST, // &Stride
1678 CGF.Builder.getIntN(IVSize, 1), // Incr
1679 Chunk // Chunk
1680 };
Alexander Musman21212e42015-03-13 10:38:23 +00001681 CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args);
Alexander Musman92bdaab2015-03-12 13:37:50 +00001682 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001683}
1684
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001685void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
1686 SourceLocation Loc) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001687 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001688 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1689 getThreadID(CGF, Loc)};
1690 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
1691 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00001692}
1693
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001694void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
1695 SourceLocation Loc,
1696 unsigned IVSize,
1697 bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001698 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
1699 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1700 getThreadID(CGF, Loc)};
1701 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
1702}
1703
Alexander Musman92bdaab2015-03-12 13:37:50 +00001704llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
1705 SourceLocation Loc, unsigned IVSize,
1706 bool IVSigned, llvm::Value *IL,
1707 llvm::Value *LB, llvm::Value *UB,
1708 llvm::Value *ST) {
1709 // Call __kmpc_dispatch_next(
1710 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
1711 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
1712 // kmp_int[32|64] *p_stride);
1713 llvm::Value *Args[] = {
1714 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc),
1715 IL, // &isLastIter
1716 LB, // &Lower
1717 UB, // &Upper
1718 ST // &Stride
1719 };
1720 llvm::Value *Call =
1721 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
1722 return CGF.EmitScalarConversion(
1723 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001724 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00001725}
1726
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001727void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
1728 llvm::Value *NumThreads,
1729 SourceLocation Loc) {
Alexey Bataevb2059782014-10-13 08:23:51 +00001730 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
1731 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001732 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00001733 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001734 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
1735 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00001736}
1737
Alexey Bataev7f210c62015-06-18 13:40:03 +00001738void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
1739 OpenMPProcBindClauseKind ProcBind,
1740 SourceLocation Loc) {
1741 // Constants for proc bind value accepted by the runtime.
1742 enum ProcBindTy {
1743 ProcBindFalse = 0,
1744 ProcBindTrue,
1745 ProcBindMaster,
1746 ProcBindClose,
1747 ProcBindSpread,
1748 ProcBindIntel,
1749 ProcBindDefault
1750 } RuntimeProcBind;
1751 switch (ProcBind) {
1752 case OMPC_PROC_BIND_master:
1753 RuntimeProcBind = ProcBindMaster;
1754 break;
1755 case OMPC_PROC_BIND_close:
1756 RuntimeProcBind = ProcBindClose;
1757 break;
1758 case OMPC_PROC_BIND_spread:
1759 RuntimeProcBind = ProcBindSpread;
1760 break;
1761 case OMPC_PROC_BIND_unknown:
1762 llvm_unreachable("Unsupported proc_bind value.");
1763 }
1764 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
1765 llvm::Value *Args[] = {
1766 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1767 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
1768 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
1769}
1770
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001771void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
1772 SourceLocation Loc) {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001773 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001774 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
1775 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001776}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001777
Alexey Bataev62b63b12015-03-10 07:28:44 +00001778namespace {
1779/// \brief Indexes of fields for type kmp_task_t.
1780enum KmpTaskTFields {
1781 /// \brief List of shared variables.
1782 KmpTaskTShareds,
1783 /// \brief Task routine.
1784 KmpTaskTRoutine,
1785 /// \brief Partition id for the untied tasks.
1786 KmpTaskTPartId,
1787 /// \brief Function with call of destructors for private variables.
1788 KmpTaskTDestructors,
1789};
1790} // namespace
1791
1792void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
1793 if (!KmpRoutineEntryPtrTy) {
1794 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
1795 auto &C = CGM.getContext();
1796 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
1797 FunctionProtoType::ExtProtoInfo EPI;
1798 KmpRoutineEntryPtrQTy = C.getPointerType(
1799 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
1800 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
1801 }
1802}
1803
1804static void addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1805 QualType FieldTy) {
1806 auto *Field = FieldDecl::Create(
1807 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1808 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1809 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1810 Field->setAccess(AS_public);
1811 DC->addDecl(Field);
1812}
1813
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001814namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00001815struct PrivateHelpersTy {
1816 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
1817 const VarDecl *PrivateElemInit)
1818 : Original(Original), PrivateCopy(PrivateCopy),
1819 PrivateElemInit(PrivateElemInit) {}
1820 const VarDecl *Original;
1821 const VarDecl *PrivateCopy;
1822 const VarDecl *PrivateElemInit;
1823};
1824typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001825} // namespace
1826
Alexey Bataev9e034042015-05-05 04:05:12 +00001827static RecordDecl *
1828createPrivatesRecordDecl(CodeGenModule &CGM,
1829 const ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001830 if (!Privates.empty()) {
1831 auto &C = CGM.getContext();
1832 // Build struct .kmp_privates_t. {
1833 // /* private vars */
1834 // };
1835 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
1836 RD->startDefinition();
1837 for (auto &&Pair : Privates) {
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001838 auto Type = Pair.second.Original->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001839 Type = Type.getNonReferenceType();
1840 addFieldToRecordDecl(C, RD, Type);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001841 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001842 RD->completeDefinition();
1843 return RD;
1844 }
1845 return nullptr;
1846}
1847
Alexey Bataev9e034042015-05-05 04:05:12 +00001848static RecordDecl *
1849createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001850 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001851 auto &C = CGM.getContext();
1852 // Build struct kmp_task_t {
1853 // void * shareds;
1854 // kmp_routine_entry_t routine;
1855 // kmp_int32 part_id;
1856 // kmp_routine_entry_t destructors;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001857 // };
1858 auto *RD = C.buildImplicitRecord("kmp_task_t");
1859 RD->startDefinition();
1860 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1861 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
1862 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1863 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001864 RD->completeDefinition();
1865 return RD;
1866}
1867
1868static RecordDecl *
1869createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
1870 const ArrayRef<PrivateDataTy> Privates) {
1871 auto &C = CGM.getContext();
1872 // Build struct kmp_task_t_with_privates {
1873 // kmp_task_t task_data;
1874 // .kmp_privates_t. privates;
1875 // };
1876 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
1877 RD->startDefinition();
1878 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001879 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
1880 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
1881 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001882 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001883 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001884}
1885
1886/// \brief Emit a proxy function which accepts kmp_task_t as the second
1887/// argument.
1888/// \code
1889/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00001890/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map,
1891/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001892/// return 0;
1893/// }
1894/// \endcode
1895static llvm::Value *
1896emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001897 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
1898 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00001899 QualType SharedsPtrTy, llvm::Value *TaskFunction,
1900 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001901 auto &C = CGM.getContext();
1902 FunctionArgList Args;
1903 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
1904 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001905 /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001906 Args.push_back(&GtidArg);
1907 Args.push_back(&TaskTypeArg);
1908 FunctionType::ExtInfo Info;
1909 auto &TaskEntryFnInfo =
1910 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
1911 /*isVariadic=*/false);
1912 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
1913 auto *TaskEntry =
1914 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
1915 ".omp_task_entry.", &CGM.getModule());
1916 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskEntryFnInfo, TaskEntry);
1917 CodeGenFunction CGF(CGM);
1918 CGF.disableDebugInfo();
1919 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
1920
Alexey Bataev3ae88e22015-05-22 08:56:35 +00001921 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
1922 // tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001923 auto *GtidParam = CGF.EmitLoadOfScalar(
1924 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false,
1925 C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001926 auto *TaskTypeArgAddr = CGF.Builder.CreateAlignedLoad(
1927 CGF.GetAddrOfLocalVar(&TaskTypeArg), CGM.PointerAlignInBytes);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00001928 LValue TDBase =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001929 CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskTWithPrivatesQTy);
1930 auto *KmpTaskTWithPrivatesQTyRD =
1931 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00001932 LValue Base =
1933 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001934 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
1935 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
1936 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
1937 auto *PartidParam = CGF.EmitLoadOfLValue(PartIdLVal, Loc).getScalarVal();
1938
1939 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
1940 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001941 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001942 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001943 CGF.ConvertTypeForMem(SharedsPtrTy));
1944
Alexey Bataev3ae88e22015-05-22 08:56:35 +00001945 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
1946 llvm::Value *PrivatesParam;
1947 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
1948 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
1949 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1950 PrivatesLVal.getAddress(), CGF.VoidPtrTy);
1951 } else {
1952 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
1953 }
1954
1955 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam,
1956 TaskPrivatesMap, SharedsParam};
Alexey Bataev62b63b12015-03-10 07:28:44 +00001957 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
1958 CGF.EmitStoreThroughLValue(
1959 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
1960 CGF.MakeNaturalAlignAddrLValue(CGF.ReturnValue, KmpInt32Ty));
1961 CGF.FinishFunction();
1962 return TaskEntry;
1963}
1964
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001965static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
1966 SourceLocation Loc,
1967 QualType KmpInt32Ty,
1968 QualType KmpTaskTWithPrivatesPtrQTy,
1969 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001970 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001971 FunctionArgList Args;
1972 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
1973 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001974 /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001975 Args.push_back(&GtidArg);
1976 Args.push_back(&TaskTypeArg);
1977 FunctionType::ExtInfo Info;
1978 auto &DestructorFnInfo =
1979 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
1980 /*isVariadic=*/false);
1981 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
1982 auto *DestructorFn =
1983 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
1984 ".omp_task_destructor.", &CGM.getModule());
1985 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, DestructorFnInfo, DestructorFn);
1986 CodeGenFunction CGF(CGM);
1987 CGF.disableDebugInfo();
1988 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
1989 Args);
1990
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001991 auto *TaskTypeArgAddr = CGF.Builder.CreateAlignedLoad(
1992 CGF.GetAddrOfLocalVar(&TaskTypeArg), CGM.PointerAlignInBytes);
1993 LValue Base =
1994 CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskTWithPrivatesQTy);
1995 auto *KmpTaskTWithPrivatesQTyRD =
1996 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
1997 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001998 Base = CGF.EmitLValueForField(Base, *FI);
1999 for (auto *Field :
2000 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
2001 if (auto DtorKind = Field->getType().isDestructedType()) {
2002 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
2003 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
2004 }
2005 }
2006 CGF.FinishFunction();
2007 return DestructorFn;
2008}
2009
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002010/// \brief Emit a privates mapping function for correct handling of private and
2011/// firstprivate variables.
2012/// \code
2013/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
2014/// **noalias priv1,..., <tyn> **noalias privn) {
2015/// *priv1 = &.privates.priv1;
2016/// ...;
2017/// *privn = &.privates.privn;
2018/// }
2019/// \endcode
2020static llvm::Value *
2021emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
2022 const ArrayRef<const Expr *> PrivateVars,
2023 const ArrayRef<const Expr *> FirstprivateVars,
2024 QualType PrivatesQTy,
2025 const ArrayRef<PrivateDataTy> Privates) {
2026 auto &C = CGM.getContext();
2027 FunctionArgList Args;
2028 ImplicitParamDecl TaskPrivatesArg(
2029 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
2030 C.getPointerType(PrivatesQTy).withConst().withRestrict());
2031 Args.push_back(&TaskPrivatesArg);
2032 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
2033 unsigned Counter = 1;
2034 for (auto *E: PrivateVars) {
2035 Args.push_back(ImplicitParamDecl::Create(
2036 C, /*DC=*/nullptr, Loc,
2037 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
2038 .withConst()
2039 .withRestrict()));
2040 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2041 PrivateVarsPos[VD] = Counter;
2042 ++Counter;
2043 }
2044 for (auto *E : FirstprivateVars) {
2045 Args.push_back(ImplicitParamDecl::Create(
2046 C, /*DC=*/nullptr, Loc,
2047 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
2048 .withConst()
2049 .withRestrict()));
2050 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2051 PrivateVarsPos[VD] = Counter;
2052 ++Counter;
2053 }
2054 FunctionType::ExtInfo Info;
2055 auto &TaskPrivatesMapFnInfo =
2056 CGM.getTypes().arrangeFreeFunctionDeclaration(C.VoidTy, Args, Info,
2057 /*isVariadic=*/false);
2058 auto *TaskPrivatesMapTy =
2059 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
2060 auto *TaskPrivatesMap = llvm::Function::Create(
2061 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
2062 ".omp_task_privates_map.", &CGM.getModule());
2063 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskPrivatesMapFnInfo,
2064 TaskPrivatesMap);
2065 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
2066 CodeGenFunction CGF(CGM);
2067 CGF.disableDebugInfo();
2068 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
2069 TaskPrivatesMapFnInfo, Args);
2070
2071 // *privi = &.privates.privi;
2072 auto *TaskPrivatesArgAddr = CGF.Builder.CreateAlignedLoad(
2073 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), CGM.PointerAlignInBytes);
2074 LValue Base =
2075 CGF.MakeNaturalAlignAddrLValue(TaskPrivatesArgAddr, PrivatesQTy);
2076 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
2077 Counter = 0;
2078 for (auto *Field : PrivatesQTyRD->fields()) {
2079 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
2080 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
2081 auto RefLVal = CGF.MakeNaturalAlignAddrLValue(CGF.GetAddrOfLocalVar(VD),
2082 VD->getType());
2083 auto RefLoadRVal = CGF.EmitLoadOfLValue(RefLVal, Loc);
2084 CGF.EmitStoreOfScalar(
2085 FieldLVal.getAddress(),
2086 CGF.MakeNaturalAlignAddrLValue(RefLoadRVal.getScalarVal(),
2087 RefLVal.getType()->getPointeeType()));
2088 ++Counter;
2089 }
2090 CGF.FinishFunction();
2091 return TaskPrivatesMap;
2092}
2093
Benjamin Kramer9b819032015-09-02 15:31:05 +00002094static llvm::Value *getTypeSize(CodeGenFunction &CGF, QualType Ty) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002095 auto &C = CGF.getContext();
2096 llvm::Value *Size;
2097 auto SizeInChars = C.getTypeSizeInChars(Ty);
2098 if (SizeInChars.isZero()) {
2099 // getTypeSizeInChars() returns 0 for a VLA.
2100 Size = nullptr;
2101 while (auto *VAT = C.getAsVariableArrayType(Ty)) {
2102 llvm::Value *ArraySize;
2103 std::tie(ArraySize, Ty) = CGF.getVLASize(VAT);
2104 Size = Size ? CGF.Builder.CreateNUWMul(Size, ArraySize) : ArraySize;
2105 }
2106 SizeInChars = C.getTypeSizeInChars(Ty);
2107 assert(!SizeInChars.isZero());
2108 Size = CGF.Builder.CreateNUWMul(
2109 Size, llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity()));
2110 } else
2111 Size = llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity());
2112 return Size;
2113}
2114
Alexey Bataev9e034042015-05-05 04:05:12 +00002115static int array_pod_sort_comparator(const PrivateDataTy *P1,
2116 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002117 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
2118}
2119
2120void CGOpenMPRuntime::emitTaskCall(
2121 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
2122 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
2123 llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds,
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002124 const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
2125 ArrayRef<const Expr *> PrivateCopies,
2126 ArrayRef<const Expr *> FirstprivateVars,
2127 ArrayRef<const Expr *> FirstprivateCopies,
2128 ArrayRef<const Expr *> FirstprivateInits,
2129 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002130 auto &C = CGM.getContext();
Alexey Bataev9e034042015-05-05 04:05:12 +00002131 llvm::SmallVector<PrivateDataTy, 8> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002132 // Aggregate privates and sort them by the alignment.
Alexey Bataev9e034042015-05-05 04:05:12 +00002133 auto I = PrivateCopies.begin();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002134 for (auto *E : PrivateVars) {
2135 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2136 Privates.push_back(std::make_pair(
2137 C.getTypeAlignInChars(VD->getType()),
Alexey Bataev9e034042015-05-05 04:05:12 +00002138 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
2139 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002140 ++I;
2141 }
Alexey Bataev9e034042015-05-05 04:05:12 +00002142 I = FirstprivateCopies.begin();
2143 auto IElemInitRef = FirstprivateInits.begin();
2144 for (auto *E : FirstprivateVars) {
2145 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2146 Privates.push_back(std::make_pair(
2147 C.getTypeAlignInChars(VD->getType()),
2148 PrivateHelpersTy(
2149 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
2150 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
2151 ++I, ++IElemInitRef;
2152 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002153 llvm::array_pod_sort(Privates.begin(), Privates.end(),
2154 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002155 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2156 // Build type kmp_routine_entry_t (if not built yet).
2157 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002158 // Build type kmp_task_t (if not built yet).
2159 if (KmpTaskTQTy.isNull()) {
2160 KmpTaskTQTy = C.getRecordType(
2161 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
2162 }
2163 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002164 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002165 auto *KmpTaskTWithPrivatesQTyRD =
2166 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
2167 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
2168 QualType KmpTaskTWithPrivatesPtrQTy =
2169 C.getPointerType(KmpTaskTWithPrivatesQTy);
2170 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
2171 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
2172 auto KmpTaskTWithPrivatesTySize =
2173 CGM.getSize(C.getTypeSizeInChars(KmpTaskTWithPrivatesQTy));
Alexey Bataev62b63b12015-03-10 07:28:44 +00002174 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
2175
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002176 // Emit initial values for private copies (if any).
2177 llvm::Value *TaskPrivatesMap = nullptr;
2178 auto *TaskPrivatesMapTy =
2179 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
2180 3)
2181 ->getType();
2182 if (!Privates.empty()) {
2183 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
2184 TaskPrivatesMap = emitTaskPrivateMappingFunction(
2185 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
2186 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2187 TaskPrivatesMap, TaskPrivatesMapTy);
2188 } else {
2189 TaskPrivatesMap = llvm::ConstantPointerNull::get(
2190 cast<llvm::PointerType>(TaskPrivatesMapTy));
2191 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002192 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
2193 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002194 auto *TaskEntry = emitProxyTaskFunction(
2195 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002196 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002197
2198 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
2199 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2200 // kmp_routine_entry_t *task_entry);
2201 // Task flags. Format is taken from
2202 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
2203 // description of kmp_tasking_flags struct.
2204 const unsigned TiedFlag = 0x1;
2205 const unsigned FinalFlag = 0x2;
2206 unsigned Flags = Tied ? TiedFlag : 0;
2207 auto *TaskFlags =
2208 Final.getPointer()
2209 ? CGF.Builder.CreateSelect(Final.getPointer(),
2210 CGF.Builder.getInt32(FinalFlag),
2211 CGF.Builder.getInt32(/*C=*/0))
2212 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
2213 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
2214 auto SharedsSize = C.getTypeSizeInChars(SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002215 llvm::Value *AllocArgs[] = {
2216 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), TaskFlags,
2217 KmpTaskTWithPrivatesTySize, CGM.getSize(SharedsSize),
2218 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskEntry,
2219 KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00002220 auto *NewTask = CGF.EmitRuntimeCall(
2221 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002222 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2223 NewTask, KmpTaskTWithPrivatesPtrTy);
2224 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
2225 KmpTaskTWithPrivatesQTy);
2226 LValue TDBase =
2227 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002228 // Fill the data in the resulting kmp_task_t record.
2229 // Copy shareds if there are any.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002230 llvm::Value *KmpTaskSharedsPtr = nullptr;
2231 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
2232 KmpTaskSharedsPtr = CGF.EmitLoadOfScalar(
2233 CGF.EmitLValueForField(
2234 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
2235 Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002236 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002237 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002238 // Emit initial values for private copies (if any).
2239 bool NeedsCleanup = false;
2240 if (!Privates.empty()) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002241 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
2242 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002243 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002244 LValue SharedsBase;
2245 if (!FirstprivateVars.empty()) {
2246 SharedsBase = CGF.MakeNaturalAlignAddrLValue(
2247 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2248 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
2249 SharedsTy);
2250 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002251 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
2252 cast<CapturedStmt>(*D.getAssociatedStmt()));
2253 for (auto &&Pair : Privates) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002254 auto *VD = Pair.second.PrivateCopy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002255 auto *Init = VD->getAnyInitializer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002256 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002257 if (Init) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002258 if (auto *Elem = Pair.second.PrivateElemInit) {
2259 auto *OriginalVD = Pair.second.Original;
2260 auto *SharedField = CapturesInfo.lookup(OriginalVD);
2261 auto SharedRefLValue =
2262 CGF.EmitLValueForField(SharedsBase, SharedField);
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002263 QualType Type = OriginalVD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002264 if (Type->isArrayType()) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002265 // Initialize firstprivate array.
2266 if (!isa<CXXConstructExpr>(Init) ||
2267 CGF.isTrivialInitializer(Init)) {
2268 // Perform simple memcpy.
2269 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002270 SharedRefLValue.getAddress(), Type);
Alexey Bataev9e034042015-05-05 04:05:12 +00002271 } else {
2272 // Initialize firstprivate array using element-by-element
2273 // intialization.
2274 CGF.EmitOMPAggregateAssign(
2275 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002276 Type, [&CGF, Elem, Init, &CapturesInfo](
2277 llvm::Value *DestElement, llvm::Value *SrcElement) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002278 // Clean up any temporaries needed by the initialization.
2279 CodeGenFunction::OMPPrivateScope InitScope(CGF);
2280 InitScope.addPrivate(Elem, [SrcElement]() -> llvm::Value *{
2281 return SrcElement;
2282 });
2283 (void)InitScope.Privatize();
2284 // Emit initialization for single element.
Alexey Bataevd157d472015-06-24 03:35:38 +00002285 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
2286 CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00002287 CGF.EmitAnyExprToMem(Init, DestElement,
2288 Init->getType().getQualifiers(),
2289 /*IsInitializer=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00002290 });
2291 }
2292 } else {
2293 CodeGenFunction::OMPPrivateScope InitScope(CGF);
2294 InitScope.addPrivate(Elem, [SharedRefLValue]() -> llvm::Value *{
2295 return SharedRefLValue.getAddress();
2296 });
2297 (void)InitScope.Privatize();
Alexey Bataevd157d472015-06-24 03:35:38 +00002298 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00002299 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
2300 /*capturedByInit=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00002301 }
2302 } else {
2303 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
2304 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002305 }
2306 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002307 ++FI;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002308 }
2309 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002310 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002311 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002312 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
2313 KmpTaskTWithPrivatesPtrQTy,
2314 KmpTaskTWithPrivatesQTy)
2315 : llvm::ConstantPointerNull::get(
2316 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
2317 LValue Destructor = CGF.EmitLValueForField(
2318 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
2319 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2320 DestructorFn, KmpRoutineEntryPtrTy),
2321 Destructor);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002322
2323 // Process list of dependences.
2324 llvm::Value *DependInfo = nullptr;
2325 unsigned DependencesNumber = Dependences.size();
2326 if (!Dependences.empty()) {
2327 // Dependence kind for RTL.
2328 enum RTLDependenceKindTy { DepIn = 1, DepOut = 2, DepInOut = 3 };
2329 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
2330 RecordDecl *KmpDependInfoRD;
2331 QualType FlagsTy = C.getIntTypeForBitwidth(
2332 C.toBits(C.getTypeSizeInChars(C.BoolTy)), /*Signed=*/false);
2333 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
2334 if (KmpDependInfoTy.isNull()) {
2335 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
2336 KmpDependInfoRD->startDefinition();
2337 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
2338 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
2339 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
2340 KmpDependInfoRD->completeDefinition();
2341 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
2342 } else {
2343 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
2344 }
2345 // Define type kmp_depend_info[<Dependences.size()>];
2346 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
2347 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, Dependences.size()),
2348 ArrayType::Normal, /*IndexTypeQuals=*/0);
2349 // kmp_depend_info[<Dependences.size()>] deps;
2350 DependInfo = CGF.CreateMemTemp(KmpDependInfoArrayTy);
2351 for (unsigned i = 0; i < DependencesNumber; ++i) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002352 auto *E = Dependences[i].second;
2353 LValue Addr = CGF.EmitLValue(E);
2354 llvm::Value *Size;
2355 QualType Ty = E->getType();
2356 auto *DestAddr = Addr.getAddress();
2357 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
2358 LValue UpAddrLVal =
2359 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
2360 llvm::Value *UpAddr =
2361 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getAddress(), /*Idx0=*/1);
2362 llvm::Value *LowIntPtr =
2363 CGF.Builder.CreatePtrToInt(DestAddr, CGM.SizeTy);
2364 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
2365 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
2366 } else
2367 Size = getTypeSize(CGF, Ty);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002368 auto Base = CGF.MakeNaturalAlignAddrLValue(
2369 CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, i),
2370 KmpDependInfoTy);
2371 // deps[i].base_addr = &<Dependences[i].second>;
2372 auto BaseAddrLVal = CGF.EmitLValueForField(
2373 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002374 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(DestAddr, CGF.IntPtrTy),
2375 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002376 // deps[i].len = sizeof(<Dependences[i].second>);
2377 auto LenLVal = CGF.EmitLValueForField(
2378 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
2379 CGF.EmitStoreOfScalar(Size, LenLVal);
2380 // deps[i].flags = <Dependences[i].first>;
2381 RTLDependenceKindTy DepKind;
2382 switch (Dependences[i].first) {
2383 case OMPC_DEPEND_in:
2384 DepKind = DepIn;
2385 break;
2386 case OMPC_DEPEND_out:
2387 DepKind = DepOut;
2388 break;
2389 case OMPC_DEPEND_inout:
2390 DepKind = DepInOut;
2391 break;
2392 case OMPC_DEPEND_unknown:
2393 llvm_unreachable("Unknown task dependence type");
2394 }
2395 auto FlagsLVal = CGF.EmitLValueForField(
2396 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
2397 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
2398 FlagsLVal);
2399 }
2400 DependInfo = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2401 CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, 0),
2402 CGF.VoidPtrTy);
2403 }
2404
Alexey Bataev62b63b12015-03-10 07:28:44 +00002405 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
2406 // libcall.
2407 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2408 // *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002409 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2410 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2411 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
2412 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00002413 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002414 auto *UpLoc = emitUpdateLocation(CGF, Loc);
2415 llvm::Value *TaskArgs[] = {UpLoc, ThreadID, NewTask};
2416 llvm::Value *DepTaskArgs[] = {
2417 UpLoc,
2418 ThreadID,
2419 NewTask,
2420 DependInfo ? CGF.Builder.getInt32(DependencesNumber) : nullptr,
2421 DependInfo,
2422 DependInfo ? CGF.Builder.getInt32(0) : nullptr,
2423 DependInfo ? llvm::ConstantPointerNull::get(CGF.VoidPtrTy) : nullptr};
2424 auto &&ThenCodeGen = [this, DependInfo, &TaskArgs,
2425 &DepTaskArgs](CodeGenFunction &CGF) {
Alexey Bataev1d677132015-04-22 13:57:31 +00002426 // TODO: add check for untied tasks.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002427 CGF.EmitRuntimeCall(
2428 createRuntimeFunction(DependInfo ? OMPRTL__kmpc_omp_task_with_deps
2429 : OMPRTL__kmpc_omp_task),
2430 DependInfo ? makeArrayRef(DepTaskArgs) : makeArrayRef(TaskArgs));
Alexey Bataev1d677132015-04-22 13:57:31 +00002431 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00002432 typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value>
2433 IfCallEndCleanup;
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002434 llvm::Value *DepWaitTaskArgs[] = {
2435 UpLoc,
2436 ThreadID,
2437 DependInfo ? CGF.Builder.getInt32(DependencesNumber) : nullptr,
2438 DependInfo,
2439 DependInfo ? CGF.Builder.getInt32(0) : nullptr,
2440 DependInfo ? llvm::ConstantPointerNull::get(CGF.VoidPtrTy) : nullptr};
2441 auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
2442 DependInfo, &DepWaitTaskArgs](CodeGenFunction &CGF) {
2443 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
2444 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2445 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
2446 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
2447 // is specified.
2448 if (DependInfo)
2449 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
2450 DepWaitTaskArgs);
2451 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
2452 // kmp_task_t *new_task);
2453 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0),
2454 TaskArgs);
2455 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
2456 // kmp_task_t *new_task);
2457 CGF.EHStack.pushCleanup<IfCallEndCleanup>(
2458 NormalAndEHCleanup,
2459 createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0),
2460 llvm::makeArrayRef(TaskArgs));
Alexey Bataev1d677132015-04-22 13:57:31 +00002461
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002462 // Call proxy_task_entry(gtid, new_task);
2463 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
2464 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
2465 };
Alexey Bataev1d677132015-04-22 13:57:31 +00002466 if (IfCond) {
2467 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
2468 } else {
2469 CodeGenFunction::RunCleanupsScope Scope(CGF);
2470 ThenCodeGen(CGF);
2471 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002472}
2473
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002474static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
2475 llvm::Type *ArgsType,
2476 ArrayRef<const Expr *> LHSExprs,
2477 ArrayRef<const Expr *> RHSExprs,
2478 ArrayRef<const Expr *> ReductionOps) {
2479 auto &C = CGM.getContext();
2480
2481 // void reduction_func(void *LHSArg, void *RHSArg);
2482 FunctionArgList Args;
2483 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2484 C.VoidPtrTy);
2485 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2486 C.VoidPtrTy);
2487 Args.push_back(&LHSArg);
2488 Args.push_back(&RHSArg);
2489 FunctionType::ExtInfo EI;
2490 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
2491 C.VoidTy, Args, EI, /*isVariadic=*/false);
2492 auto *Fn = llvm::Function::Create(
2493 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
2494 ".omp.reduction.reduction_func", &CGM.getModule());
2495 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
2496 CodeGenFunction CGF(CGM);
2497 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
2498
2499 // Dst = (void*[n])(LHSArg);
2500 // Src = (void*[n])(RHSArg);
2501 auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2502 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
2503 CGF.PointerAlignInBytes),
2504 ArgsType);
2505 auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2506 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
2507 CGF.PointerAlignInBytes),
2508 ArgsType);
2509
2510 // ...
2511 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
2512 // ...
2513 CodeGenFunction::OMPPrivateScope Scope(CGF);
2514 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I) {
2515 Scope.addPrivate(
2516 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()),
2517 [&]() -> llvm::Value *{
2518 return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2519 CGF.Builder.CreateAlignedLoad(
2520 CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, RHS, I),
2521 CGM.PointerAlignInBytes),
2522 CGF.ConvertTypeForMem(C.getPointerType(RHSExprs[I]->getType())));
2523 });
2524 Scope.addPrivate(
2525 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()),
2526 [&]() -> llvm::Value *{
2527 return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2528 CGF.Builder.CreateAlignedLoad(
2529 CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, LHS, I),
2530 CGM.PointerAlignInBytes),
2531 CGF.ConvertTypeForMem(C.getPointerType(LHSExprs[I]->getType())));
2532 });
2533 }
2534 Scope.Privatize();
2535 for (auto *E : ReductionOps) {
2536 CGF.EmitIgnoredExpr(E);
2537 }
2538 Scope.ForceCleanup();
2539 CGF.FinishFunction();
2540 return Fn;
2541}
2542
2543void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
2544 ArrayRef<const Expr *> LHSExprs,
2545 ArrayRef<const Expr *> RHSExprs,
2546 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002547 bool WithNowait, bool SimpleReduction) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002548 // Next code should be emitted for reduction:
2549 //
2550 // static kmp_critical_name lock = { 0 };
2551 //
2552 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
2553 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
2554 // ...
2555 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
2556 // *(Type<n>-1*)rhs[<n>-1]);
2557 // }
2558 //
2559 // ...
2560 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
2561 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2562 // RedList, reduce_func, &<lock>)) {
2563 // case 1:
2564 // ...
2565 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2566 // ...
2567 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2568 // break;
2569 // case 2:
2570 // ...
2571 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2572 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00002573 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002574 // break;
2575 // default:;
2576 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002577 //
2578 // if SimpleReduction is true, only the next code is generated:
2579 // ...
2580 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2581 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002582
2583 auto &C = CGM.getContext();
2584
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002585 if (SimpleReduction) {
2586 CodeGenFunction::RunCleanupsScope Scope(CGF);
2587 for (auto *E : ReductionOps) {
2588 CGF.EmitIgnoredExpr(E);
2589 }
2590 return;
2591 }
2592
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002593 // 1. Build a list of reduction variables.
2594 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
2595 llvm::APInt ArraySize(/*unsigned int numBits=*/32, RHSExprs.size());
2596 QualType ReductionArrayTy =
2597 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2598 /*IndexTypeQuals=*/0);
2599 auto *ReductionList =
2600 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
2601 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I) {
2602 auto *Elem = CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, ReductionList, I);
2603 CGF.Builder.CreateAlignedStore(
2604 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2605 CGF.EmitLValue(RHSExprs[I]).getAddress(), CGF.VoidPtrTy),
2606 Elem, CGM.PointerAlignInBytes);
2607 }
2608
2609 // 2. Emit reduce_func().
2610 auto *ReductionFn = emitReductionFunction(
2611 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), LHSExprs,
2612 RHSExprs, ReductionOps);
2613
2614 // 3. Create static kmp_critical_name lock = { 0 };
2615 auto *Lock = getCriticalRegionLock(".reduction");
2616
2617 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2618 // RedList, reduce_func, &<lock>);
2619 auto *IdentTLoc = emitUpdateLocation(
2620 CGF, Loc,
2621 static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE));
2622 auto *ThreadId = getThreadID(CGF, Loc);
2623 auto *ReductionArrayTySize = llvm::ConstantInt::get(
2624 CGM.SizeTy, C.getTypeSizeInChars(ReductionArrayTy).getQuantity());
2625 auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList,
2626 CGF.VoidPtrTy);
2627 llvm::Value *Args[] = {
2628 IdentTLoc, // ident_t *<loc>
2629 ThreadId, // i32 <gtid>
2630 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
2631 ReductionArrayTySize, // size_type sizeof(RedList)
2632 RL, // void *RedList
2633 ReductionFn, // void (*) (void *, void *) <reduce_func>
2634 Lock // kmp_critical_name *&<lock>
2635 };
2636 auto Res = CGF.EmitRuntimeCall(
2637 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
2638 : OMPRTL__kmpc_reduce),
2639 Args);
2640
2641 // 5. Build switch(res)
2642 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
2643 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
2644
2645 // 6. Build case 1:
2646 // ...
2647 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2648 // ...
2649 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2650 // break;
2651 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
2652 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
2653 CGF.EmitBlock(Case1BB);
2654
2655 {
2656 CodeGenFunction::RunCleanupsScope Scope(CGF);
2657 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2658 llvm::Value *EndArgs[] = {
2659 IdentTLoc, // ident_t *<loc>
2660 ThreadId, // i32 <gtid>
2661 Lock // kmp_critical_name *&<lock>
2662 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00002663 CGF.EHStack
2664 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
2665 NormalAndEHCleanup,
2666 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
2667 : OMPRTL__kmpc_end_reduce),
2668 llvm::makeArrayRef(EndArgs));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002669 for (auto *E : ReductionOps) {
2670 CGF.EmitIgnoredExpr(E);
2671 }
2672 }
2673
2674 CGF.EmitBranch(DefaultBB);
2675
2676 // 7. Build case 2:
2677 // ...
2678 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2679 // ...
2680 // break;
2681 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
2682 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
2683 CGF.EmitBlock(Case2BB);
2684
2685 {
2686 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataev69a47792015-05-07 03:54:03 +00002687 if (!WithNowait) {
2688 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
2689 llvm::Value *EndArgs[] = {
2690 IdentTLoc, // ident_t *<loc>
2691 ThreadId, // i32 <gtid>
2692 Lock // kmp_critical_name *&<lock>
2693 };
2694 CGF.EHStack
2695 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
2696 NormalAndEHCleanup,
2697 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
2698 llvm::makeArrayRef(EndArgs));
2699 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002700 auto I = LHSExprs.begin();
2701 for (auto *E : ReductionOps) {
2702 const Expr *XExpr = nullptr;
2703 const Expr *EExpr = nullptr;
2704 const Expr *UpExpr = nullptr;
2705 BinaryOperatorKind BO = BO_Comma;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002706 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
2707 if (BO->getOpcode() == BO_Assign) {
2708 XExpr = BO->getLHS();
2709 UpExpr = BO->getRHS();
2710 }
2711 }
Alexey Bataev69a47792015-05-07 03:54:03 +00002712 // Try to emit update expression as a simple atomic.
2713 auto *RHSExpr = UpExpr;
2714 if (RHSExpr) {
2715 // Analyze RHS part of the whole expression.
2716 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
2717 RHSExpr->IgnoreParenImpCasts())) {
2718 // If this is a conditional operator, analyze its condition for
2719 // min/max reduction operator.
2720 RHSExpr = ACO->getCond();
2721 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002722 if (auto *BORHS =
Alexey Bataev69a47792015-05-07 03:54:03 +00002723 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002724 EExpr = BORHS->getRHS();
2725 BO = BORHS->getOpcode();
2726 }
2727 }
2728 if (XExpr) {
2729 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
2730 LValue X = CGF.EmitLValue(XExpr);
2731 RValue E;
2732 if (EExpr)
2733 E = CGF.EmitAnyExpr(EExpr);
2734 CGF.EmitOMPAtomicSimpleUpdateExpr(
2735 X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
2736 [&CGF, UpExpr, VD](RValue XRValue) {
2737 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
2738 PrivateScope.addPrivate(
2739 VD, [&CGF, VD, XRValue]() -> llvm::Value *{
2740 auto *LHSTemp = CGF.CreateMemTemp(VD->getType());
2741 CGF.EmitStoreThroughLValue(
2742 XRValue,
2743 CGF.MakeNaturalAlignAddrLValue(LHSTemp, VD->getType()));
2744 return LHSTemp;
2745 });
2746 (void)PrivateScope.Privatize();
2747 return CGF.EmitAnyExpr(UpExpr);
2748 });
2749 } else {
2750 // Emit as a critical region.
2751 emitCriticalRegion(CGF, ".atomic_reduction", [E](CodeGenFunction &CGF) {
2752 CGF.EmitIgnoredExpr(E);
2753 }, Loc);
2754 }
2755 ++I;
2756 }
2757 }
2758
2759 CGF.EmitBranch(DefaultBB);
2760 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
2761}
2762
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002763void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
2764 SourceLocation Loc) {
2765 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
2766 // global_tid);
2767 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2768 // Ignore return result until untied tasks are supported.
2769 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
2770}
2771
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002772void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002773 OpenMPDirectiveKind InnerKind,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002774 const RegionCodeGenTy &CodeGen) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002775 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002776 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00002777}
2778
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002779namespace {
2780enum RTCancelKind {
2781 CancelNoreq = 0,
2782 CancelParallel = 1,
2783 CancelLoop = 2,
2784 CancelSections = 3,
2785 CancelTaskgroup = 4
2786};
2787}
2788
2789static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
2790 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00002791 if (CancelRegion == OMPD_parallel)
2792 CancelKind = CancelParallel;
2793 else if (CancelRegion == OMPD_for)
2794 CancelKind = CancelLoop;
2795 else if (CancelRegion == OMPD_sections)
2796 CancelKind = CancelSections;
2797 else {
2798 assert(CancelRegion == OMPD_taskgroup);
2799 CancelKind = CancelTaskgroup;
2800 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002801 return CancelKind;
2802}
2803
2804void CGOpenMPRuntime::emitCancellationPointCall(
2805 CodeGenFunction &CGF, SourceLocation Loc,
2806 OpenMPDirectiveKind CancelRegion) {
2807 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2808 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002809 if (auto *OMPRegionInfo =
2810 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
2811 auto CancelDest =
2812 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
2813 if (CancelDest.isValid()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002814 llvm::Value *Args[] = {
2815 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2816 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002817 // Ignore return result until untied tasks are supported.
2818 auto *Result = CGF.EmitRuntimeCall(
2819 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
2820 // if (__kmpc_cancellationpoint()) {
2821 // __kmpc_cancel_barrier();
2822 // exit from construct;
2823 // }
2824 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
2825 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
2826 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
2827 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2828 CGF.EmitBlock(ExitBB);
2829 // __kmpc_cancel_barrier();
2830 emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false);
2831 // exit from construct;
2832 CGF.EmitBranchThroughCleanup(CancelDest);
2833 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2834 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002835 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002836}
2837
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002838void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
2839 OpenMPDirectiveKind CancelRegion) {
2840 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2841 // kmp_int32 cncl_kind);
2842 if (auto *OMPRegionInfo =
2843 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
2844 auto CancelDest =
2845 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
2846 if (CancelDest.isValid()) {
2847 llvm::Value *Args[] = {
2848 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2849 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
2850 // Ignore return result until untied tasks are supported.
2851 auto *Result =
2852 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
2853 // if (__kmpc_cancel()) {
2854 // __kmpc_cancel_barrier();
2855 // exit from construct;
2856 // }
2857 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
2858 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
2859 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
2860 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2861 CGF.EmitBlock(ExitBB);
2862 // __kmpc_cancel_barrier();
2863 emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false);
2864 // exit from construct;
2865 CGF.EmitBranchThroughCleanup(CancelDest);
2866 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2867 }
2868 }
2869}
2870