blob: 78213f52e2faef875680b7cbb3186f6c5d1ac45e [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 Bataev25e5b442015-09-15 12:52:43 +000048 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
49 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000050 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000051 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000052
53 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000054 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
55 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000056 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000057 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000058
59 /// \brief Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000060 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000061 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000062
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000063 /// \brief Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000064 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000065
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000066 /// \brief Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000067 /// \return LValue for thread id variable. This LValue always has type int32*.
68 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000069
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000070 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000071
Alexey Bataev81c7ea02015-07-03 09:56:58 +000072 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
73
Alexey Bataev25e5b442015-09-15 12:52:43 +000074 bool hasCancel() const { return HasCancel; }
75
Alexey Bataev18095712014-10-10 12:19:54 +000076 static bool classof(const CGCapturedStmtInfo *Info) {
77 return Info->getKind() == CR_OpenMP;
78 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000079
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000080protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000081 CGOpenMPRegionKind RegionKind;
82 const RegionCodeGenTy &CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000083 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +000084 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000085};
Alexey Bataev18095712014-10-10 12:19:54 +000086
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000087/// \brief API for captured statement code generation in OpenMP constructs.
88class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
89public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000090 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +000091 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +000092 OpenMPDirectiveKind Kind, bool HasCancel)
93 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
94 HasCancel),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000095 ThreadIDVar(ThreadIDVar) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000096 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
97 }
98 /// \brief Get a variable or parameter for storing global thread id
99 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000100 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000101
Alexey Bataev18095712014-10-10 12:19:54 +0000102 /// \brief Get the name of the capture helper.
Benjamin Kramerc52193f2014-10-10 13:57:57 +0000103 StringRef getHelperName() const override { return ".omp_outlined."; }
Alexey Bataev18095712014-10-10 12:19:54 +0000104
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000105 static bool classof(const CGCapturedStmtInfo *Info) {
106 return CGOpenMPRegionInfo::classof(Info) &&
107 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
108 ParallelOutlinedRegion;
109 }
110
Alexey Bataev18095712014-10-10 12:19:54 +0000111private:
112 /// \brief A variable or parameter storing global thread id for OpenMP
113 /// constructs.
114 const VarDecl *ThreadIDVar;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000115};
116
Alexey Bataev62b63b12015-03-10 07:28:44 +0000117/// \brief API for captured statement code generation in OpenMP constructs.
118class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo {
119public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000120 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000121 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000122 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000123 OpenMPDirectiveKind Kind, bool HasCancel)
124 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000125 ThreadIDVar(ThreadIDVar) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000126 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
127 }
128 /// \brief Get a variable or parameter for storing global thread id
129 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000130 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000131
132 /// \brief Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000133 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000134
Alexey Bataev62b63b12015-03-10 07:28:44 +0000135 /// \brief Get the name of the capture helper.
136 StringRef getHelperName() const override { return ".omp_outlined."; }
137
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000138 static bool classof(const CGCapturedStmtInfo *Info) {
139 return CGOpenMPRegionInfo::classof(Info) &&
140 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
141 TaskOutlinedRegion;
142 }
143
Alexey Bataev62b63b12015-03-10 07:28:44 +0000144private:
145 /// \brief A variable or parameter storing global thread id for OpenMP
146 /// constructs.
147 const VarDecl *ThreadIDVar;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000148};
149
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000150/// \brief API for inlined captured statement code generation in OpenMP
151/// constructs.
152class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
153public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000154 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000155 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000156 OpenMPDirectiveKind Kind, bool HasCancel)
157 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
158 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000159 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
160 // \brief Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000161 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000162 if (OuterRegionInfo)
163 return OuterRegionInfo->getContextValue();
164 llvm_unreachable("No context value for inlined OpenMP region");
165 }
Hans Wennborg7eb54642015-09-10 17:07:54 +0000166 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000167 if (OuterRegionInfo) {
168 OuterRegionInfo->setContextValue(V);
169 return;
170 }
171 llvm_unreachable("No context value for inlined OpenMP region");
172 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000173 /// \brief Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000174 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000175 if (OuterRegionInfo)
176 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000177 // If there is no outer outlined region,no need to lookup in a list of
178 // captured variables, we can use the original one.
179 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000180 }
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000181 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000182 if (OuterRegionInfo)
183 return OuterRegionInfo->getThisFieldDecl();
184 return nullptr;
185 }
186 /// \brief Get a variable or parameter for storing global thread id
187 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000188 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000189 if (OuterRegionInfo)
190 return OuterRegionInfo->getThreadIDVariable();
191 return nullptr;
192 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000193
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000194 /// \brief Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000195 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000196 if (auto *OuterRegionInfo = getOldCSI())
197 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000198 llvm_unreachable("No helper name for inlined OpenMP construct");
199 }
200
201 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
202
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000203 static bool classof(const CGCapturedStmtInfo *Info) {
204 return CGOpenMPRegionInfo::classof(Info) &&
205 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
206 }
207
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000208private:
209 /// \brief CodeGen info about outer OpenMP region.
210 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
211 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000212};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000213
214/// \brief RAII for emitting code of OpenMP constructs.
215class InlinedOpenMPRegionRAII {
216 CodeGenFunction &CGF;
217
218public:
219 /// \brief Constructs region for combined constructs.
220 /// \param CodeGen Code generation sequence for combined directives. Includes
221 /// a list of functions used for code generation of implicitly inlined
222 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000223 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000224 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000225 : CGF(CGF) {
226 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000227 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
228 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000229 }
230 ~InlinedOpenMPRegionRAII() {
231 // Restore original CapturedStmtInfo only if we're done with code emission.
232 auto *OldCSI =
233 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
234 delete CGF.CapturedStmtInfo;
235 CGF.CapturedStmtInfo = OldCSI;
236 }
237};
238
Hans Wennborg7eb54642015-09-10 17:07:54 +0000239} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000240
Alexey Bataev2377fe92015-09-10 08:12:02 +0000241static LValue emitLoadOfPointerLValue(CodeGenFunction &CGF, Address PtrAddr,
242 QualType Ty) {
243 AlignmentSource Source;
244 CharUnits Align = CGF.getNaturalPointeeTypeAlignment(Ty, &Source);
245 return CGF.MakeAddrLValue(Address(CGF.Builder.CreateLoad(PtrAddr), Align),
246 Ty->getPointeeType(), Source);
247}
248
Alexey Bataev18095712014-10-10 12:19:54 +0000249LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000250 return emitLoadOfPointerLValue(CGF,
251 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
252 getThreadIDVariable()->getType());
Alexey Bataev18095712014-10-10 12:19:54 +0000253}
254
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000255void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
256 // 1.2.2 OpenMP Language Terminology
257 // Structured block - An executable statement with a single entry at the
258 // top and a single exit at the bottom.
259 // The point of exit cannot be a branch out of the structured block.
260 // longjmp() and throw() must not violate the entry/exit criteria.
261 CGF.EHStack.pushTerminate();
262 {
263 CodeGenFunction::RunCleanupsScope Scope(CGF);
264 CodeGen(CGF);
265 }
266 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000267}
268
Alexey Bataev62b63b12015-03-10 07:28:44 +0000269LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
270 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000271 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
272 getThreadIDVariable()->getType(),
273 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000274}
275
Alexey Bataev9959db52014-05-06 10:08:46 +0000276CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
Alexey Bataev62b63b12015-03-10 07:28:44 +0000277 : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000278 IdentTy = llvm::StructType::create(
279 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
280 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000281 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000282 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
Alexey Bataev23b69422014-06-18 07:08:49 +0000283 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
284 llvm::PointerType::getUnqual(CGM.Int32Ty)};
Alexey Bataev9959db52014-05-06 10:08:46 +0000285 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000286 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Alexey Bataev9959db52014-05-06 10:08:46 +0000287}
288
Alexey Bataev91797552015-03-18 04:13:55 +0000289void CGOpenMPRuntime::clear() {
290 InternalVars.clear();
291}
292
John McCall7f416cc2015-09-08 08:05:57 +0000293// Layout information for ident_t.
294static CharUnits getIdentAlign(CodeGenModule &CGM) {
295 return CGM.getPointerAlign();
296}
297static CharUnits getIdentSize(CodeGenModule &CGM) {
298 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign()));
299 return CharUnits::fromQuantity(16) + CGM.getPointerSize();
300}
301static CharUnits getOffsetOfIdentField(CGOpenMPRuntime::IdentFieldIndex Field) {
302 // All the fields except the last are i32, so this works beautifully.
303 return unsigned(Field) * CharUnits::fromQuantity(4);
304}
305static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
306 CGOpenMPRuntime::IdentFieldIndex Field,
307 const llvm::Twine &Name = "") {
308 auto Offset = getOffsetOfIdentField(Field);
309 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
310}
311
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000312llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction(
313 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
314 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000315 assert(ThreadIDVar->getType()->isPointerType() &&
316 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +0000317 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
318 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +0000319 bool HasCancel = false;
320 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
321 HasCancel = OPD->hasCancel();
322 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
323 HasCancel = OPSD->hasCancel();
324 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
325 HasCancel = OPFD->hasCancel();
326 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
327 HasCancel);
Alexey Bataevd157d472015-06-24 03:35:38 +0000328 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000329 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +0000330}
331
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000332llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
333 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
334 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000335 assert(!ThreadIDVar->getType()->isPointerType() &&
336 "thread id variable must be of type kmp_int32 for tasks");
337 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
338 CodeGenFunction CGF(CGM, true);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000339 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000340 InnermostKind,
341 cast<OMPTaskDirective>(D).hasCancel());
Alexey Bataevd157d472015-06-24 03:35:38 +0000342 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000343 return CGF.GenerateCapturedStmtFunction(*CS);
344}
345
John McCall7f416cc2015-09-08 08:05:57 +0000346Address CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
347 CharUnits Align = getIdentAlign(CGM);
Alexey Bataev15007ba2014-05-07 06:18:01 +0000348 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000349 if (!Entry) {
350 if (!DefaultOpenMPPSource) {
351 // Initialize default location for psource field of ident_t structure of
352 // all ident_t objects. Format is ";file;function;line;column;;".
353 // Taken from
354 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
355 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +0000356 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000357 DefaultOpenMPPSource =
358 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
359 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000360 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
361 CGM.getModule(), IdentTy, /*isConstant*/ true,
362 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000363 DefaultOpenMPLocation->setUnnamedAddr(true);
John McCall7f416cc2015-09-08 08:05:57 +0000364 DefaultOpenMPLocation->setAlignment(Align.getQuantity());
Alexey Bataev9959db52014-05-06 10:08:46 +0000365
366 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000367 llvm::Constant *Values[] = {Zero,
368 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
369 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000370 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
371 DefaultOpenMPLocation->setInitializer(Init);
John McCall7f416cc2015-09-08 08:05:57 +0000372 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000373 }
John McCall7f416cc2015-09-08 08:05:57 +0000374 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +0000375}
376
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000377llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
378 SourceLocation Loc,
379 OpenMPLocationFlags Flags) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000380 // If no debug info is generated - return global default location.
381 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
382 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +0000383 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000384
385 assert(CGF.CurFn && "No function in current CodeGenFunction.");
386
John McCall7f416cc2015-09-08 08:05:57 +0000387 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000388 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
389 if (I != OpenMPLocThreadIDMap.end())
John McCall7f416cc2015-09-08 08:05:57 +0000390 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
391
Alexander Musmanc6388682014-12-15 07:07:06 +0000392 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
393 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +0000394 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000395 // Generate "ident_t .kmpc_loc.addr;"
John McCall7f416cc2015-09-08 08:05:57 +0000396 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
397 ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +0000398 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +0000399 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000400 LocValue = AI;
401
402 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
403 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000404 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
John McCall7f416cc2015-09-08 08:05:57 +0000405 CGM.getSize(getIdentSize(CGF.CGM)));
Alexey Bataev9959db52014-05-06 10:08:46 +0000406 }
407
408 // char **psource = &.kmpc_loc_<flags>.addr.psource;
John McCall7f416cc2015-09-08 08:05:57 +0000409 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000410
Alexey Bataevf002aca2014-05-30 05:48:40 +0000411 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
412 if (OMPDebugLoc == nullptr) {
413 SmallString<128> Buffer2;
414 llvm::raw_svector_ostream OS2(Buffer2);
415 // Build debug location
416 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
417 OS2 << ";" << PLoc.getFilename() << ";";
418 if (const FunctionDecl *FD =
419 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
420 OS2 << FD->getQualifiedNameAsString();
421 }
422 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
423 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
424 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000425 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000426 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000427 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
428
John McCall7f416cc2015-09-08 08:05:57 +0000429 // Our callers always pass this to a runtime function, so for
430 // convenience, go ahead and return a naked pointer.
431 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000432}
433
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000434llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
435 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000436 assert(CGF.CurFn && "No function in current CodeGenFunction.");
437
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000438 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000439 // Check whether we've already cached a load of the thread id in this
440 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000441 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000442 if (I != OpenMPLocThreadIDMap.end()) {
443 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000444 if (ThreadID != nullptr)
445 return ThreadID;
446 }
447 if (auto OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000448 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000449 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000450 // Check if this an outlined function with thread id passed as argument.
451 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000452 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
453 // If value loaded in entry block, cache it and use it everywhere in
454 // function.
455 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
456 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
457 Elem.second.ThreadID = ThreadID;
458 }
459 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000460 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000461 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000462
463 // This is not an outlined function region - need to call __kmpc_int32
464 // kmpc_global_thread_num(ident_t *loc).
465 // Generate thread id value and cache this value for use across the
466 // function.
467 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
468 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
469 ThreadID =
470 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
471 emitUpdateLocation(CGF, Loc));
472 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
473 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000474 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000475}
476
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000477void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000478 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000479 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
480 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataev9959db52014-05-06 10:08:46 +0000481}
482
483llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
484 return llvm::PointerType::getUnqual(IdentTy);
485}
486
487llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
488 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
489}
490
491llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000492CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000493 llvm::Constant *RTLFn = nullptr;
494 switch (Function) {
495 case OMPRTL__kmpc_fork_call: {
496 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
497 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +0000498 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
499 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000500 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000501 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +0000502 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
503 break;
504 }
505 case OMPRTL__kmpc_global_thread_num: {
506 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +0000507 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000508 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000509 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +0000510 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
511 break;
512 }
Alexey Bataev97720002014-11-11 04:05:39 +0000513 case OMPRTL__kmpc_threadprivate_cached: {
514 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
515 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
516 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
517 CGM.VoidPtrTy, CGM.SizeTy,
518 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
519 llvm::FunctionType *FnTy =
520 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
521 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
522 break;
523 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000524 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000525 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
526 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000527 llvm::Type *TypeParams[] = {
528 getIdentTyPointerTy(), CGM.Int32Ty,
529 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
530 llvm::FunctionType *FnTy =
531 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
532 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
533 break;
534 }
Alexey Bataev97720002014-11-11 04:05:39 +0000535 case OMPRTL__kmpc_threadprivate_register: {
536 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
537 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
538 // typedef void *(*kmpc_ctor)(void *);
539 auto KmpcCtorTy =
540 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
541 /*isVarArg*/ false)->getPointerTo();
542 // typedef void *(*kmpc_cctor)(void *, void *);
543 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
544 auto KmpcCopyCtorTy =
545 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
546 /*isVarArg*/ false)->getPointerTo();
547 // typedef void (*kmpc_dtor)(void *);
548 auto KmpcDtorTy =
549 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
550 ->getPointerTo();
551 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
552 KmpcCopyCtorTy, KmpcDtorTy};
553 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
554 /*isVarArg*/ false);
555 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
556 break;
557 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000558 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000559 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
560 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000561 llvm::Type *TypeParams[] = {
562 getIdentTyPointerTy(), CGM.Int32Ty,
563 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
564 llvm::FunctionType *FnTy =
565 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
566 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
567 break;
568 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000569 case OMPRTL__kmpc_cancel_barrier: {
570 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
571 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000572 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
573 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000574 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
575 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000576 break;
577 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000578 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +0000579 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000580 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
581 llvm::FunctionType *FnTy =
582 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
583 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
584 break;
585 }
Alexander Musmanc6388682014-12-15 07:07:06 +0000586 case OMPRTL__kmpc_for_static_fini: {
587 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
588 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
589 llvm::FunctionType *FnTy =
590 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
591 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
592 break;
593 }
Alexey Bataevb2059782014-10-13 08:23:51 +0000594 case OMPRTL__kmpc_push_num_threads: {
595 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
596 // kmp_int32 num_threads)
597 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
598 CGM.Int32Ty};
599 llvm::FunctionType *FnTy =
600 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
601 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
602 break;
603 }
Alexey Bataevd74d0602014-10-13 06:02:40 +0000604 case OMPRTL__kmpc_serialized_parallel: {
605 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
606 // global_tid);
607 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
608 llvm::FunctionType *FnTy =
609 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
610 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
611 break;
612 }
613 case OMPRTL__kmpc_end_serialized_parallel: {
614 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
615 // global_tid);
616 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
617 llvm::FunctionType *FnTy =
618 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
619 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
620 break;
621 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000622 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000623 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000624 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
625 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000626 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000627 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
628 break;
629 }
Alexey Bataev8d690652014-12-04 07:23:53 +0000630 case OMPRTL__kmpc_master: {
631 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
632 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
633 llvm::FunctionType *FnTy =
634 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
635 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
636 break;
637 }
638 case OMPRTL__kmpc_end_master: {
639 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
640 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
641 llvm::FunctionType *FnTy =
642 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
643 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
644 break;
645 }
Alexey Bataev9f797f32015-02-05 05:57:51 +0000646 case OMPRTL__kmpc_omp_taskyield: {
647 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
648 // int end_part);
649 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
650 llvm::FunctionType *FnTy =
651 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
652 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
653 break;
654 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +0000655 case OMPRTL__kmpc_single: {
656 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
657 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
658 llvm::FunctionType *FnTy =
659 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
660 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
661 break;
662 }
663 case OMPRTL__kmpc_end_single: {
664 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
665 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
666 llvm::FunctionType *FnTy =
667 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
668 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
669 break;
670 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000671 case OMPRTL__kmpc_omp_task_alloc: {
672 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
673 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
674 // kmp_routine_entry_t *task_entry);
675 assert(KmpRoutineEntryPtrTy != nullptr &&
676 "Type kmp_routine_entry_t must be created.");
677 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
678 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
679 // Return void * and then cast to particular kmp_task_t type.
680 llvm::FunctionType *FnTy =
681 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
682 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
683 break;
684 }
685 case OMPRTL__kmpc_omp_task: {
686 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
687 // *new_task);
688 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
689 CGM.VoidPtrTy};
690 llvm::FunctionType *FnTy =
691 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
692 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
693 break;
694 }
Alexey Bataeva63048e2015-03-23 06:18:07 +0000695 case OMPRTL__kmpc_copyprivate: {
696 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +0000697 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +0000698 // kmp_int32 didit);
699 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
700 auto *CpyFnTy =
701 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +0000702 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +0000703 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
704 CGM.Int32Ty};
705 llvm::FunctionType *FnTy =
706 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
707 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
708 break;
709 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +0000710 case OMPRTL__kmpc_reduce: {
711 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
712 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
713 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
714 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
715 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
716 /*isVarArg=*/false);
717 llvm::Type *TypeParams[] = {
718 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
719 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
720 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
721 llvm::FunctionType *FnTy =
722 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
723 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
724 break;
725 }
726 case OMPRTL__kmpc_reduce_nowait: {
727 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
728 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
729 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
730 // *lck);
731 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
732 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
733 /*isVarArg=*/false);
734 llvm::Type *TypeParams[] = {
735 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
736 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
737 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
738 llvm::FunctionType *FnTy =
739 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
740 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
741 break;
742 }
743 case OMPRTL__kmpc_end_reduce: {
744 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
745 // kmp_critical_name *lck);
746 llvm::Type *TypeParams[] = {
747 getIdentTyPointerTy(), CGM.Int32Ty,
748 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
749 llvm::FunctionType *FnTy =
750 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
751 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
752 break;
753 }
754 case OMPRTL__kmpc_end_reduce_nowait: {
755 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
756 // kmp_critical_name *lck);
757 llvm::Type *TypeParams[] = {
758 getIdentTyPointerTy(), CGM.Int32Ty,
759 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
760 llvm::FunctionType *FnTy =
761 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
762 RTLFn =
763 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
764 break;
765 }
Alexey Bataev1d677132015-04-22 13:57:31 +0000766 case OMPRTL__kmpc_omp_task_begin_if0: {
767 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
768 // *new_task);
769 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
770 CGM.VoidPtrTy};
771 llvm::FunctionType *FnTy =
772 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
773 RTLFn =
774 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
775 break;
776 }
777 case OMPRTL__kmpc_omp_task_complete_if0: {
778 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
779 // *new_task);
780 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
781 CGM.VoidPtrTy};
782 llvm::FunctionType *FnTy =
783 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
784 RTLFn = CGM.CreateRuntimeFunction(FnTy,
785 /*Name=*/"__kmpc_omp_task_complete_if0");
786 break;
787 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000788 case OMPRTL__kmpc_ordered: {
789 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
790 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
791 llvm::FunctionType *FnTy =
792 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
793 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
794 break;
795 }
796 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +0000797 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000798 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
799 llvm::FunctionType *FnTy =
800 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
801 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
802 break;
803 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +0000804 case OMPRTL__kmpc_omp_taskwait: {
805 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
806 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
807 llvm::FunctionType *FnTy =
808 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
809 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
810 break;
811 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +0000812 case OMPRTL__kmpc_taskgroup: {
813 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
814 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
815 llvm::FunctionType *FnTy =
816 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
817 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
818 break;
819 }
820 case OMPRTL__kmpc_end_taskgroup: {
821 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
822 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
823 llvm::FunctionType *FnTy =
824 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
825 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
826 break;
827 }
Alexey Bataev7f210c62015-06-18 13:40:03 +0000828 case OMPRTL__kmpc_push_proc_bind: {
829 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
830 // int proc_bind)
831 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
832 llvm::FunctionType *FnTy =
833 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
834 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
835 break;
836 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +0000837 case OMPRTL__kmpc_omp_task_with_deps: {
838 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
839 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
840 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
841 llvm::Type *TypeParams[] = {
842 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
843 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
844 llvm::FunctionType *FnTy =
845 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
846 RTLFn =
847 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
848 break;
849 }
850 case OMPRTL__kmpc_omp_wait_deps: {
851 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
852 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
853 // kmp_depend_info_t *noalias_dep_list);
854 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
855 CGM.Int32Ty, CGM.VoidPtrTy,
856 CGM.Int32Ty, CGM.VoidPtrTy};
857 llvm::FunctionType *FnTy =
858 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
859 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
860 break;
861 }
Alexey Bataev0f34da12015-07-02 04:17:07 +0000862 case OMPRTL__kmpc_cancellationpoint: {
863 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
864 // global_tid, kmp_int32 cncl_kind)
865 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
866 llvm::FunctionType *FnTy =
867 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
868 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
869 break;
870 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +0000871 case OMPRTL__kmpc_cancel: {
872 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
873 // kmp_int32 cncl_kind)
874 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
875 llvm::FunctionType *FnTy =
876 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
877 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
878 break;
879 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000880 }
881 return RTLFn;
882}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000883
Alexander Musman21212e42015-03-13 10:38:23 +0000884llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
885 bool IVSigned) {
886 assert((IVSize == 32 || IVSize == 64) &&
887 "IV size is not compatible with the omp runtime");
888 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
889 : "__kmpc_for_static_init_4u")
890 : (IVSigned ? "__kmpc_for_static_init_8"
891 : "__kmpc_for_static_init_8u");
892 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
893 auto PtrTy = llvm::PointerType::getUnqual(ITy);
894 llvm::Type *TypeParams[] = {
895 getIdentTyPointerTy(), // loc
896 CGM.Int32Ty, // tid
897 CGM.Int32Ty, // schedtype
898 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
899 PtrTy, // p_lower
900 PtrTy, // p_upper
901 PtrTy, // p_stride
902 ITy, // incr
903 ITy // chunk
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::createDispatchInitFunction(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_init_4" : "__kmpc_dispatch_init_4u")
917 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
918 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
919 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
920 CGM.Int32Ty, // tid
921 CGM.Int32Ty, // schedtype
922 ITy, // lower
923 ITy, // upper
924 ITy, // stride
925 ITy // chunk
926 };
927 llvm::FunctionType *FnTy =
928 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
929 return CGM.CreateRuntimeFunction(FnTy, Name);
930}
931
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000932llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
933 bool IVSigned) {
934 assert((IVSize == 32 || IVSize == 64) &&
935 "IV size is not compatible with the omp runtime");
936 auto Name =
937 IVSize == 32
938 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
939 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
940 llvm::Type *TypeParams[] = {
941 getIdentTyPointerTy(), // loc
942 CGM.Int32Ty, // tid
943 };
944 llvm::FunctionType *FnTy =
945 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
946 return CGM.CreateRuntimeFunction(FnTy, Name);
947}
948
Alexander Musman92bdaab2015-03-12 13:37:50 +0000949llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
950 bool IVSigned) {
951 assert((IVSize == 32 || IVSize == 64) &&
952 "IV size is not compatible with the omp runtime");
953 auto Name =
954 IVSize == 32
955 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
956 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
957 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
958 auto PtrTy = llvm::PointerType::getUnqual(ITy);
959 llvm::Type *TypeParams[] = {
960 getIdentTyPointerTy(), // loc
961 CGM.Int32Ty, // tid
962 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
963 PtrTy, // p_lower
964 PtrTy, // p_upper
965 PtrTy // p_stride
966 };
967 llvm::FunctionType *FnTy =
968 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
969 return CGM.CreateRuntimeFunction(FnTy, Name);
970}
971
Alexey Bataev97720002014-11-11 04:05:39 +0000972llvm::Constant *
973CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +0000974 assert(!CGM.getLangOpts().OpenMPUseTLS ||
975 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +0000976 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000977 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +0000978 Twine(CGM.getMangledName(VD)) + ".cache.");
979}
980
John McCall7f416cc2015-09-08 08:05:57 +0000981Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
982 const VarDecl *VD,
983 Address VDAddr,
984 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +0000985 if (CGM.getLangOpts().OpenMPUseTLS &&
986 CGM.getContext().getTargetInfo().isTLSSupported())
987 return VDAddr;
988
John McCall7f416cc2015-09-08 08:05:57 +0000989 auto VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000990 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +0000991 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
992 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +0000993 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
994 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +0000995 return Address(CGF.EmitRuntimeCall(
996 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
997 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +0000998}
999
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001000void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00001001 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00001002 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1003 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1004 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001005 auto OMPLoc = emitUpdateLocation(CGF, Loc);
1006 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00001007 OMPLoc);
1008 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1009 // to register constructor/destructor for variable.
1010 llvm::Value *Args[] = {OMPLoc,
John McCall7f416cc2015-09-08 08:05:57 +00001011 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1012 CGM.VoidPtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001013 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001014 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001015 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001016}
1017
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001018llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00001019 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00001020 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001021 if (CGM.getLangOpts().OpenMPUseTLS &&
1022 CGM.getContext().getTargetInfo().isTLSSupported())
1023 return nullptr;
1024
Alexey Bataev97720002014-11-11 04:05:39 +00001025 VD = VD->getDefinition(CGM.getContext());
1026 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
1027 ThreadPrivateWithDefinition.insert(VD);
1028 QualType ASTTy = VD->getType();
1029
1030 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1031 auto Init = VD->getAnyInitializer();
1032 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1033 // Generate function that re-emits the declaration's initializer into the
1034 // threadprivate copy of the variable VD
1035 CodeGenFunction CtorCGF(CGM);
1036 FunctionArgList Args;
1037 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1038 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1039 Args.push_back(&Dst);
1040
1041 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1042 CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(),
1043 /*isVariadic=*/false);
1044 auto FTy = CGM.getTypes().GetFunctionType(FI);
1045 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
1046 FTy, ".__kmpc_global_ctor_.", Loc);
1047 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1048 Args, SourceLocation());
1049 auto ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001050 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001051 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00001052 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1053 Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
1054 CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00001055 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1056 /*IsInitializer=*/true);
1057 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001058 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001059 CGM.getContext().VoidPtrTy, Dst.getLocation());
1060 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1061 CtorCGF.FinishFunction();
1062 Ctor = Fn;
1063 }
1064 if (VD->getType().isDestructedType() != QualType::DK_none) {
1065 // Generate function that emits destructor call for the threadprivate copy
1066 // of the variable VD
1067 CodeGenFunction DtorCGF(CGM);
1068 FunctionArgList Args;
1069 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1070 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1071 Args.push_back(&Dst);
1072
1073 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1074 CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(),
1075 /*isVariadic=*/false);
1076 auto FTy = CGM.getTypes().GetFunctionType(FI);
1077 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
1078 FTy, ".__kmpc_global_dtor_.", Loc);
1079 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1080 SourceLocation());
1081 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1082 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00001083 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1084 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001085 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1086 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1087 DtorCGF.FinishFunction();
1088 Dtor = Fn;
1089 }
1090 // Do not emit init function if it is not required.
1091 if (!Ctor && !Dtor)
1092 return nullptr;
1093
1094 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1095 auto CopyCtorTy =
1096 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1097 /*isVarArg=*/false)->getPointerTo();
1098 // Copying constructor for the threadprivate variable.
1099 // Must be NULL - reserved by runtime, but currently it requires that this
1100 // parameter is always NULL. Otherwise it fires assertion.
1101 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1102 if (Ctor == nullptr) {
1103 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1104 /*isVarArg=*/false)->getPointerTo();
1105 Ctor = llvm::Constant::getNullValue(CtorTy);
1106 }
1107 if (Dtor == nullptr) {
1108 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1109 /*isVarArg=*/false)->getPointerTo();
1110 Dtor = llvm::Constant::getNullValue(DtorTy);
1111 }
1112 if (!CGF) {
1113 auto InitFunctionTy =
1114 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1115 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
1116 InitFunctionTy, ".__omp_threadprivate_init_.");
1117 CodeGenFunction InitCGF(CGM);
1118 FunctionArgList ArgList;
1119 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1120 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1121 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001122 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001123 InitCGF.FinishFunction();
1124 return InitFunction;
1125 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001126 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001127 }
1128 return nullptr;
1129}
1130
Alexey Bataev1d677132015-04-22 13:57:31 +00001131/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1132/// function. Here is the logic:
1133/// if (Cond) {
1134/// ThenGen();
1135/// } else {
1136/// ElseGen();
1137/// }
1138static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1139 const RegionCodeGenTy &ThenGen,
1140 const RegionCodeGenTy &ElseGen) {
1141 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1142
1143 // If the condition constant folds and can be elided, try to avoid emitting
1144 // the condition and the dead arm of the if/else.
1145 bool CondConstant;
1146 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
1147 CodeGenFunction::RunCleanupsScope Scope(CGF);
1148 if (CondConstant) {
1149 ThenGen(CGF);
1150 } else {
1151 ElseGen(CGF);
1152 }
1153 return;
1154 }
1155
1156 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1157 // emit the conditional branch.
1158 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1159 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1160 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1161 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1162
1163 // Emit the 'then' code.
1164 CGF.EmitBlock(ThenBlock);
1165 {
1166 CodeGenFunction::RunCleanupsScope ThenScope(CGF);
1167 ThenGen(CGF);
1168 }
1169 CGF.EmitBranch(ContBlock);
1170 // Emit the 'else' code if present.
1171 {
1172 // There is no need to emit line number for unconditional branch.
1173 auto NL = ApplyDebugLocation::CreateEmpty(CGF);
1174 CGF.EmitBlock(ElseBlock);
1175 }
1176 {
1177 CodeGenFunction::RunCleanupsScope ThenScope(CGF);
1178 ElseGen(CGF);
1179 }
1180 {
1181 // There is no need to emit line number for unconditional branch.
1182 auto NL = ApplyDebugLocation::CreateEmpty(CGF);
1183 CGF.EmitBranch(ContBlock);
1184 }
1185 // Emit the continuation block for code after the if.
1186 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001187}
1188
Alexey Bataev1d677132015-04-22 13:57:31 +00001189void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1190 llvm::Value *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001191 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00001192 const Expr *IfCond) {
1193 auto *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001194 auto &&ThenGen = [this, OutlinedFn, CapturedVars,
1195 RTLoc](CodeGenFunction &CGF) {
1196 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
1197 llvm::Value *Args[] = {
1198 RTLoc,
1199 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
1200 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
1201 llvm::SmallVector<llvm::Value *, 16> RealArgs;
1202 RealArgs.append(std::begin(Args), std::end(Args));
1203 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1204
1205 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
1206 CGF.EmitRuntimeCall(RTLFn, RealArgs);
1207 };
1208 auto &&ElseGen = [this, OutlinedFn, CapturedVars, RTLoc,
1209 Loc](CodeGenFunction &CGF) {
Alexey Bataev1d677132015-04-22 13:57:31 +00001210 auto ThreadID = getThreadID(CGF, Loc);
1211 // Build calls:
1212 // __kmpc_serialized_parallel(&Loc, GTid);
1213 llvm::Value *Args[] = {RTLoc, ThreadID};
1214 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel),
1215 Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001216
Alexey Bataev1d677132015-04-22 13:57:31 +00001217 // OutlinedFn(&GTid, &zero, CapturedStruct);
1218 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00001219 Address ZeroAddr =
1220 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
1221 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00001222 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00001223 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
1224 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
1225 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1226 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev1d677132015-04-22 13:57:31 +00001227 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001228
Alexey Bataev1d677132015-04-22 13:57:31 +00001229 // __kmpc_end_serialized_parallel(&Loc, GTid);
1230 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID};
1231 CGF.EmitRuntimeCall(
1232 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs);
1233 };
1234 if (IfCond) {
1235 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
1236 } else {
1237 CodeGenFunction::RunCleanupsScope Scope(CGF);
1238 ThenGen(CGF);
1239 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001240}
1241
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001242// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001243// thread-ID variable (it is passed in a first argument of the outlined function
1244// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1245// regular serial code region, get thread ID by calling kmp_int32
1246// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1247// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00001248Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
1249 SourceLocation Loc) {
Alexey Bataevd74d0602014-10-13 06:02:40 +00001250 if (auto OMPRegionInfo =
1251 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001252 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001253 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001254
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001255 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001256 auto Int32Ty =
1257 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1258 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1259 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00001260 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00001261
1262 return ThreadIDTemp;
1263}
1264
Alexey Bataev97720002014-11-11 04:05:39 +00001265llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001266CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001267 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001268 SmallString<256> Buffer;
1269 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001270 Out << Name;
1271 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001272 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1273 if (Elem.second) {
1274 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001275 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001276 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001277 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001278
David Blaikie13156b62014-11-19 03:06:06 +00001279 return Elem.second = new llvm::GlobalVariable(
1280 CGM.getModule(), Ty, /*IsConstant*/ false,
1281 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1282 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001283}
1284
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001285llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001286 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001287 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001288}
1289
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001290namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00001291template <size_t N> class CallEndCleanup final : public EHScopeStack::Cleanup {
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001292 llvm::Value *Callee;
Alexey Bataeva744ff52015-05-05 09:24:37 +00001293 llvm::Value *Args[N];
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001294
1295public:
Alexey Bataeva744ff52015-05-05 09:24:37 +00001296 CallEndCleanup(llvm::Value *Callee, ArrayRef<llvm::Value *> CleanupArgs)
1297 : Callee(Callee) {
1298 assert(CleanupArgs.size() == N);
1299 std::copy(CleanupArgs.begin(), CleanupArgs.end(), std::begin(Args));
1300 }
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001301 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
1302 CGF.EmitRuntimeCall(Callee, Args);
1303 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001304};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001305} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001306
1307void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1308 StringRef CriticalName,
1309 const RegionCodeGenTy &CriticalOpGen,
1310 SourceLocation Loc) {
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001311 // __kmpc_critical(ident_t *, gtid, Lock);
1312 // CriticalOpGen();
1313 // __kmpc_end_critical(ident_t *, gtid, Lock);
1314 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001315 {
1316 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001317 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1318 getCriticalRegionLock(CriticalName)};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001319 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001320 // Build a call to __kmpc_end_critical
Alexey Bataeva744ff52015-05-05 09:24:37 +00001321 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001322 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
1323 llvm::makeArrayRef(Args));
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001324 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001325 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001326}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001327
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001328static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001329 OpenMPDirectiveKind Kind, SourceLocation Loc,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001330 const RegionCodeGenTy &BodyOpGen) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001331 llvm::Value *CallBool = CGF.EmitScalarConversion(
1332 IfCond,
1333 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001334 CGF.getContext().BoolTy, Loc);
Alexey Bataev8d690652014-12-04 07:23:53 +00001335
1336 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1337 auto *ContBlock = CGF.createBasicBlock("omp_if.end");
1338 // Generate the branch (If-stmt)
1339 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1340 CGF.EmitBlock(ThenBlock);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001341 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen);
Alexey Bataev8d690652014-12-04 07:23:53 +00001342 // Emit the rest of bblocks/branches
1343 CGF.EmitBranch(ContBlock);
1344 CGF.EmitBlock(ContBlock, true);
1345}
1346
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001347void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001348 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001349 SourceLocation Loc) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001350 // if(__kmpc_master(ident_t *, gtid)) {
1351 // MasterOpGen();
1352 // __kmpc_end_master(ident_t *, gtid);
1353 // }
1354 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001355 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001356 auto *IsMaster =
1357 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
Alexey Bataeva744ff52015-05-05 09:24:37 +00001358 typedef CallEndCleanup<std::extent<decltype(Args)>::value>
1359 MasterCallEndCleanup;
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001360 emitIfStmt(
1361 CGF, IsMaster, OMPD_master, Loc, [&](CodeGenFunction &CGF) -> void {
1362 CodeGenFunction::RunCleanupsScope Scope(CGF);
1363 CGF.EHStack.pushCleanup<MasterCallEndCleanup>(
1364 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
1365 llvm::makeArrayRef(Args));
1366 MasterOpGen(CGF);
1367 });
Alexey Bataev8d690652014-12-04 07:23:53 +00001368}
1369
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001370void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
1371 SourceLocation Loc) {
Alexey Bataev9f797f32015-02-05 05:57:51 +00001372 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
1373 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001374 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00001375 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001376 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev9f797f32015-02-05 05:57:51 +00001377}
1378
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001379void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
1380 const RegionCodeGenTy &TaskgroupOpGen,
1381 SourceLocation Loc) {
1382 // __kmpc_taskgroup(ident_t *, gtid);
1383 // TaskgroupOpGen();
1384 // __kmpc_end_taskgroup(ident_t *, gtid);
1385 // Prepare arguments and build a call to __kmpc_taskgroup
1386 {
1387 CodeGenFunction::RunCleanupsScope Scope(CGF);
1388 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1389 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args);
1390 // Build a call to __kmpc_end_taskgroup
1391 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
1392 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
1393 llvm::makeArrayRef(Args));
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001394 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001395 }
1396}
1397
John McCall7f416cc2015-09-08 08:05:57 +00001398/// Given an array of pointers to variables, project the address of a
1399/// given variable.
1400static Address emitAddrOfVarFromArray(CodeGenFunction &CGF,
1401 Address Array, unsigned Index,
1402 const VarDecl *Var) {
1403 // Pull out the pointer to the variable.
1404 Address PtrAddr =
1405 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
1406 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
1407
1408 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
1409 Addr = CGF.Builder.CreateElementBitCast(Addr,
1410 CGF.ConvertTypeForMem(Var->getType()));
1411 return Addr;
1412}
1413
Alexey Bataeva63048e2015-03-23 06:18:07 +00001414static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00001415 CodeGenModule &CGM, llvm::Type *ArgsType,
1416 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
1417 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00001418 auto &C = CGM.getContext();
1419 // void copy_func(void *LHSArg, void *RHSArg);
1420 FunctionArgList Args;
1421 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1422 C.VoidPtrTy);
1423 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1424 C.VoidPtrTy);
1425 Args.push_back(&LHSArg);
1426 Args.push_back(&RHSArg);
1427 FunctionType::ExtInfo EI;
1428 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1429 C.VoidTy, Args, EI, /*isVariadic=*/false);
1430 auto *Fn = llvm::Function::Create(
1431 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
1432 ".omp.copyprivate.copy_func", &CGM.getModule());
1433 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
1434 CodeGenFunction CGF(CGM);
1435 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00001436 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001437 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00001438 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1439 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
1440 ArgsType), CGF.getPointerAlign());
1441 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1442 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
1443 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00001444 // *(Type0*)Dst[0] = *(Type0*)Src[0];
1445 // *(Type1*)Dst[1] = *(Type1*)Src[1];
1446 // ...
1447 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00001448 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00001449 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
1450 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
1451
1452 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
1453 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
1454
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001455 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
1456 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00001457 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001458 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001459 CGF.FinishFunction();
1460 return Fn;
1461}
1462
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001463void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001464 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001465 SourceLocation Loc,
1466 ArrayRef<const Expr *> CopyprivateVars,
1467 ArrayRef<const Expr *> SrcExprs,
1468 ArrayRef<const Expr *> DstExprs,
1469 ArrayRef<const Expr *> AssignmentOps) {
1470 assert(CopyprivateVars.size() == SrcExprs.size() &&
1471 CopyprivateVars.size() == DstExprs.size() &&
1472 CopyprivateVars.size() == AssignmentOps.size());
1473 auto &C = CGM.getContext();
1474 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001475 // if(__kmpc_single(ident_t *, gtid)) {
1476 // SingleOpGen();
1477 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001478 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001479 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001480 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1481 // <copy_func>, did_it);
1482
John McCall7f416cc2015-09-08 08:05:57 +00001483 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00001484 if (!CopyprivateVars.empty()) {
1485 // int32 did_it = 0;
1486 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1487 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00001488 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001489 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001490 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001491 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001492 auto *IsSingle =
1493 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
Alexey Bataeva744ff52015-05-05 09:24:37 +00001494 typedef CallEndCleanup<std::extent<decltype(Args)>::value>
1495 SingleCallEndCleanup;
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001496 emitIfStmt(
1497 CGF, IsSingle, OMPD_single, Loc, [&](CodeGenFunction &CGF) -> void {
1498 CodeGenFunction::RunCleanupsScope Scope(CGF);
1499 CGF.EHStack.pushCleanup<SingleCallEndCleanup>(
1500 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
1501 llvm::makeArrayRef(Args));
1502 SingleOpGen(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00001503 if (DidIt.isValid()) {
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001504 // did_it = 1;
John McCall7f416cc2015-09-08 08:05:57 +00001505 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001506 }
1507 });
Alexey Bataeva63048e2015-03-23 06:18:07 +00001508 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1509 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00001510 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00001511 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
1512 auto CopyprivateArrayTy =
1513 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
1514 /*IndexTypeQuals=*/0);
1515 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00001516 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00001517 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
1518 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00001519 Address Elem = CGF.Builder.CreateConstArrayGEP(
1520 CopyprivateList, I, CGF.getPointerSize());
1521 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00001522 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00001523 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
1524 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001525 }
1526 // Build function that copies private values from single region to all other
1527 // threads in the corresponding parallel region.
1528 auto *CpyFn = emitCopyprivateCopyFunction(
1529 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00001530 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001531 auto *BufSize = llvm::ConstantInt::get(
1532 CGM.SizeTy, C.getTypeSizeInChars(CopyprivateArrayTy).getQuantity());
John McCall7f416cc2015-09-08 08:05:57 +00001533 Address CL =
1534 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
1535 CGF.VoidPtrTy);
1536 auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001537 llvm::Value *Args[] = {
1538 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
1539 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00001540 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00001541 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00001542 CpyFn, // void (*) (void *, void *) <copy_func>
1543 DidItVal // i32 did_it
1544 };
1545 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
1546 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001547}
1548
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001549void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
1550 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00001551 SourceLocation Loc, bool IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001552 // __kmpc_ordered(ident_t *, gtid);
1553 // OrderedOpGen();
1554 // __kmpc_end_ordered(ident_t *, gtid);
1555 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00001556 CodeGenFunction::RunCleanupsScope Scope(CGF);
1557 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001558 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1559 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_ordered), Args);
1560 // Build a call to __kmpc_end_ordered
Alexey Bataeva744ff52015-05-05 09:24:37 +00001561 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001562 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered),
1563 llvm::makeArrayRef(Args));
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001564 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00001565 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001566}
1567
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001568void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev25e5b442015-09-15 12:52:43 +00001569 OpenMPDirectiveKind Kind, bool EmitChecks,
1570 bool ForceSimpleCall) {
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001571 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001572 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataevf2685682015-03-30 04:30:22 +00001573 OpenMPLocationFlags Flags = OMP_IDENT_KMPC;
1574 if (Kind == OMPD_for) {
1575 Flags =
1576 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_FOR);
1577 } else if (Kind == OMPD_sections) {
1578 Flags = static_cast<OpenMPLocationFlags>(Flags |
1579 OMP_IDENT_BARRIER_IMPL_SECTIONS);
1580 } else if (Kind == OMPD_single) {
1581 Flags =
1582 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_SINGLE);
1583 } else if (Kind == OMPD_barrier) {
1584 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_EXPL);
1585 } else {
1586 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL);
1587 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001588 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
1589 // thread_id);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001590 auto *OMPRegionInfo =
1591 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
1592 // Do not emit barrier call in the single directive emitted in some rare cases
1593 // for sections directives.
1594 if (OMPRegionInfo && OMPRegionInfo->getDirectiveKind() == OMPD_single)
1595 return;
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001596 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
1597 getThreadID(CGF, Loc)};
Alexey Bataev25e5b442015-09-15 12:52:43 +00001598 if (OMPRegionInfo) {
1599 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001600 auto *Result = CGF.EmitRuntimeCall(
1601 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001602 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001603 // if (__kmpc_cancel_barrier()) {
1604 // exit from construct;
1605 // }
1606 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
1607 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
1608 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
1609 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
1610 CGF.EmitBlock(ExitBB);
1611 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00001612 auto CancelDestination =
1613 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001614 CGF.EmitBranchThroughCleanup(CancelDestination);
1615 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
1616 }
1617 return;
1618 }
1619 }
1620 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001621}
1622
Alexander Musmanc6388682014-12-15 07:07:06 +00001623/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
1624/// the enum sched_type in kmp.h).
1625enum OpenMPSchedType {
1626 /// \brief Lower bound for default (unordered) versions.
1627 OMP_sch_lower = 32,
1628 OMP_sch_static_chunked = 33,
1629 OMP_sch_static = 34,
1630 OMP_sch_dynamic_chunked = 35,
1631 OMP_sch_guided_chunked = 36,
1632 OMP_sch_runtime = 37,
1633 OMP_sch_auto = 38,
1634 /// \brief Lower bound for 'ordered' versions.
1635 OMP_ord_lower = 64,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001636 OMP_ord_static_chunked = 65,
1637 OMP_ord_static = 66,
1638 OMP_ord_dynamic_chunked = 67,
1639 OMP_ord_guided_chunked = 68,
1640 OMP_ord_runtime = 69,
1641 OMP_ord_auto = 70,
1642 OMP_sch_default = OMP_sch_static,
Alexander Musmanc6388682014-12-15 07:07:06 +00001643};
1644
1645/// \brief Map the OpenMP loop schedule to the runtime enumeration.
1646static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001647 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001648 switch (ScheduleKind) {
1649 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001650 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
1651 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00001652 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001653 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00001654 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001655 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00001656 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001657 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
1658 case OMPC_SCHEDULE_auto:
1659 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00001660 case OMPC_SCHEDULE_unknown:
1661 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001662 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00001663 }
1664 llvm_unreachable("Unexpected runtime schedule");
1665}
1666
1667bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
1668 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001669 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00001670 return Schedule == OMP_sch_static;
1671}
1672
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001673bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001674 auto Schedule =
1675 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001676 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
1677 return Schedule != OMP_sch_static;
1678}
1679
John McCall7f416cc2015-09-08 08:05:57 +00001680void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
1681 SourceLocation Loc,
1682 OpenMPScheduleClauseKind ScheduleKind,
1683 unsigned IVSize, bool IVSigned,
1684 bool Ordered, llvm::Value *UB,
1685 llvm::Value *Chunk) {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001686 OpenMPSchedType Schedule =
1687 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00001688 assert(Ordered ||
1689 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
1690 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
1691 // Call __kmpc_dispatch_init(
1692 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
1693 // kmp_int[32|64] lower, kmp_int[32|64] upper,
1694 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00001695
John McCall7f416cc2015-09-08 08:05:57 +00001696 // If the Chunk was not specified in the clause - use default value 1.
1697 if (Chunk == nullptr)
1698 Chunk = CGF.Builder.getIntN(IVSize, 1);
1699 llvm::Value *Args[] = {
1700 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1701 getThreadID(CGF, Loc),
1702 CGF.Builder.getInt32(Schedule), // Schedule type
1703 CGF.Builder.getIntN(IVSize, 0), // Lower
1704 UB, // Upper
1705 CGF.Builder.getIntN(IVSize, 1), // Stride
1706 Chunk // Chunk
1707 };
1708 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
1709}
1710
1711void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
1712 SourceLocation Loc,
1713 OpenMPScheduleClauseKind ScheduleKind,
1714 unsigned IVSize, bool IVSigned,
1715 bool Ordered, Address IL, Address LB,
1716 Address UB, Address ST,
1717 llvm::Value *Chunk) {
1718 OpenMPSchedType Schedule =
1719 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
1720 assert(!Ordered);
1721 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
1722 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked);
1723
1724 // Call __kmpc_for_static_init(
1725 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
1726 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
1727 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
1728 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
1729 if (Chunk == nullptr) {
1730 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static) &&
1731 "expected static non-chunked schedule");
Alexander Musman92bdaab2015-03-12 13:37:50 +00001732 // If the Chunk was not specified in the clause - use default value 1.
Alexander Musman92bdaab2015-03-12 13:37:50 +00001733 Chunk = CGF.Builder.getIntN(IVSize, 1);
Alexander Musman92bdaab2015-03-12 13:37:50 +00001734 } else {
John McCall7f416cc2015-09-08 08:05:57 +00001735 assert((Schedule == OMP_sch_static_chunked ||
1736 Schedule == OMP_ord_static_chunked) &&
1737 "expected static chunked schedule");
Alexander Musman92bdaab2015-03-12 13:37:50 +00001738 }
John McCall7f416cc2015-09-08 08:05:57 +00001739 llvm::Value *Args[] = {
1740 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1741 getThreadID(CGF, Loc),
1742 CGF.Builder.getInt32(Schedule), // Schedule type
1743 IL.getPointer(), // &isLastIter
1744 LB.getPointer(), // &LB
1745 UB.getPointer(), // &UB
1746 ST.getPointer(), // &Stride
1747 CGF.Builder.getIntN(IVSize, 1), // Incr
1748 Chunk // Chunk
1749 };
1750 CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00001751}
1752
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001753void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
1754 SourceLocation Loc) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001755 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001756 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1757 getThreadID(CGF, Loc)};
1758 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
1759 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00001760}
1761
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001762void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
1763 SourceLocation Loc,
1764 unsigned IVSize,
1765 bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001766 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
1767 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1768 getThreadID(CGF, Loc)};
1769 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
1770}
1771
Alexander Musman92bdaab2015-03-12 13:37:50 +00001772llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
1773 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00001774 bool IVSigned, Address IL,
1775 Address LB, Address UB,
1776 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00001777 // Call __kmpc_dispatch_next(
1778 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
1779 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
1780 // kmp_int[32|64] *p_stride);
1781 llvm::Value *Args[] = {
1782 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001783 IL.getPointer(), // &isLastIter
1784 LB.getPointer(), // &Lower
1785 UB.getPointer(), // &Upper
1786 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00001787 };
1788 llvm::Value *Call =
1789 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
1790 return CGF.EmitScalarConversion(
1791 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001792 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00001793}
1794
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001795void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
1796 llvm::Value *NumThreads,
1797 SourceLocation Loc) {
Alexey Bataevb2059782014-10-13 08:23:51 +00001798 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
1799 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001800 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00001801 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001802 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
1803 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00001804}
1805
Alexey Bataev7f210c62015-06-18 13:40:03 +00001806void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
1807 OpenMPProcBindClauseKind ProcBind,
1808 SourceLocation Loc) {
1809 // Constants for proc bind value accepted by the runtime.
1810 enum ProcBindTy {
1811 ProcBindFalse = 0,
1812 ProcBindTrue,
1813 ProcBindMaster,
1814 ProcBindClose,
1815 ProcBindSpread,
1816 ProcBindIntel,
1817 ProcBindDefault
1818 } RuntimeProcBind;
1819 switch (ProcBind) {
1820 case OMPC_PROC_BIND_master:
1821 RuntimeProcBind = ProcBindMaster;
1822 break;
1823 case OMPC_PROC_BIND_close:
1824 RuntimeProcBind = ProcBindClose;
1825 break;
1826 case OMPC_PROC_BIND_spread:
1827 RuntimeProcBind = ProcBindSpread;
1828 break;
1829 case OMPC_PROC_BIND_unknown:
1830 llvm_unreachable("Unsupported proc_bind value.");
1831 }
1832 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
1833 llvm::Value *Args[] = {
1834 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1835 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
1836 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
1837}
1838
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001839void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
1840 SourceLocation Loc) {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001841 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001842 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
1843 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001844}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001845
Alexey Bataev62b63b12015-03-10 07:28:44 +00001846namespace {
1847/// \brief Indexes of fields for type kmp_task_t.
1848enum KmpTaskTFields {
1849 /// \brief List of shared variables.
1850 KmpTaskTShareds,
1851 /// \brief Task routine.
1852 KmpTaskTRoutine,
1853 /// \brief Partition id for the untied tasks.
1854 KmpTaskTPartId,
1855 /// \brief Function with call of destructors for private variables.
1856 KmpTaskTDestructors,
1857};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001858} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00001859
1860void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
1861 if (!KmpRoutineEntryPtrTy) {
1862 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
1863 auto &C = CGM.getContext();
1864 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
1865 FunctionProtoType::ExtProtoInfo EPI;
1866 KmpRoutineEntryPtrQTy = C.getPointerType(
1867 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
1868 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
1869 }
1870}
1871
Alexey Bataevc71a4092015-09-11 10:29:41 +00001872static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1873 QualType FieldTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001874 auto *Field = FieldDecl::Create(
1875 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1876 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1877 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1878 Field->setAccess(AS_public);
1879 DC->addDecl(Field);
Alexey Bataevc71a4092015-09-11 10:29:41 +00001880 return Field;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001881}
1882
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001883namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00001884struct PrivateHelpersTy {
1885 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
1886 const VarDecl *PrivateElemInit)
1887 : Original(Original), PrivateCopy(PrivateCopy),
1888 PrivateElemInit(PrivateElemInit) {}
1889 const VarDecl *Original;
1890 const VarDecl *PrivateCopy;
1891 const VarDecl *PrivateElemInit;
1892};
1893typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00001894} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001895
Alexey Bataev9e034042015-05-05 04:05:12 +00001896static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00001897createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001898 if (!Privates.empty()) {
1899 auto &C = CGM.getContext();
1900 // Build struct .kmp_privates_t. {
1901 // /* private vars */
1902 // };
1903 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
1904 RD->startDefinition();
1905 for (auto &&Pair : Privates) {
Alexey Bataevc71a4092015-09-11 10:29:41 +00001906 auto *VD = Pair.second.Original;
1907 auto Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001908 Type = Type.getNonReferenceType();
Alexey Bataevc71a4092015-09-11 10:29:41 +00001909 auto *FD = addFieldToRecordDecl(C, RD, Type);
1910 if (VD->hasAttrs()) {
1911 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
1912 E(VD->getAttrs().end());
1913 I != E; ++I)
1914 FD->addAttr(*I);
1915 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001916 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001917 RD->completeDefinition();
1918 return RD;
1919 }
1920 return nullptr;
1921}
1922
Alexey Bataev9e034042015-05-05 04:05:12 +00001923static RecordDecl *
1924createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001925 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001926 auto &C = CGM.getContext();
1927 // Build struct kmp_task_t {
1928 // void * shareds;
1929 // kmp_routine_entry_t routine;
1930 // kmp_int32 part_id;
1931 // kmp_routine_entry_t destructors;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001932 // };
1933 auto *RD = C.buildImplicitRecord("kmp_task_t");
1934 RD->startDefinition();
1935 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1936 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
1937 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1938 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001939 RD->completeDefinition();
1940 return RD;
1941}
1942
1943static RecordDecl *
1944createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00001945 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001946 auto &C = CGM.getContext();
1947 // Build struct kmp_task_t_with_privates {
1948 // kmp_task_t task_data;
1949 // .kmp_privates_t. privates;
1950 // };
1951 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
1952 RD->startDefinition();
1953 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001954 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
1955 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
1956 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001957 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001958 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001959}
1960
1961/// \brief Emit a proxy function which accepts kmp_task_t as the second
1962/// argument.
1963/// \code
1964/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00001965/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map,
1966/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001967/// return 0;
1968/// }
1969/// \endcode
1970static llvm::Value *
1971emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001972 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
1973 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00001974 QualType SharedsPtrTy, llvm::Value *TaskFunction,
1975 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001976 auto &C = CGM.getContext();
1977 FunctionArgList Args;
1978 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
1979 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001980 /*Id=*/nullptr,
1981 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev62b63b12015-03-10 07:28:44 +00001982 Args.push_back(&GtidArg);
1983 Args.push_back(&TaskTypeArg);
1984 FunctionType::ExtInfo Info;
1985 auto &TaskEntryFnInfo =
1986 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
1987 /*isVariadic=*/false);
1988 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
1989 auto *TaskEntry =
1990 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
1991 ".omp_task_entry.", &CGM.getModule());
1992 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskEntryFnInfo, TaskEntry);
1993 CodeGenFunction CGF(CGM);
1994 CGF.disableDebugInfo();
1995 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
1996
Alexey Bataev3ae88e22015-05-22 08:56:35 +00001997 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
1998 // tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001999 auto *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002000 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev2377fe92015-09-10 08:12:02 +00002001 LValue TDBase = emitLoadOfPointerLValue(
2002 CGF, CGF.GetAddrOfLocalVar(&TaskTypeArg), KmpTaskTWithPrivatesPtrQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002003 auto *KmpTaskTWithPrivatesQTyRD =
2004 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002005 LValue Base =
2006 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002007 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
2008 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
2009 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
2010 auto *PartidParam = CGF.EmitLoadOfLValue(PartIdLVal, Loc).getScalarVal();
2011
2012 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
2013 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002014 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002015 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002016 CGF.ConvertTypeForMem(SharedsPtrTy));
2017
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002018 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
2019 llvm::Value *PrivatesParam;
2020 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
2021 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
2022 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002023 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002024 } else {
2025 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2026 }
2027
2028 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam,
2029 TaskPrivatesMap, SharedsParam};
Alexey Bataev62b63b12015-03-10 07:28:44 +00002030 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
2031 CGF.EmitStoreThroughLValue(
2032 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
John McCall7f416cc2015-09-08 08:05:57 +00002033 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00002034 CGF.FinishFunction();
2035 return TaskEntry;
2036}
2037
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002038static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
2039 SourceLocation Loc,
2040 QualType KmpInt32Ty,
2041 QualType KmpTaskTWithPrivatesPtrQTy,
2042 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002043 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002044 FunctionArgList Args;
2045 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
2046 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002047 /*Id=*/nullptr,
2048 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002049 Args.push_back(&GtidArg);
2050 Args.push_back(&TaskTypeArg);
2051 FunctionType::ExtInfo Info;
2052 auto &DestructorFnInfo =
2053 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
2054 /*isVariadic=*/false);
2055 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
2056 auto *DestructorFn =
2057 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
2058 ".omp_task_destructor.", &CGM.getModule());
2059 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, DestructorFnInfo, DestructorFn);
2060 CodeGenFunction CGF(CGM);
2061 CGF.disableDebugInfo();
2062 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
2063 Args);
2064
Alexey Bataev2377fe92015-09-10 08:12:02 +00002065 LValue Base = emitLoadOfPointerLValue(
2066 CGF, CGF.GetAddrOfLocalVar(&TaskTypeArg), KmpTaskTWithPrivatesPtrQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002067 auto *KmpTaskTWithPrivatesQTyRD =
2068 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
2069 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002070 Base = CGF.EmitLValueForField(Base, *FI);
2071 for (auto *Field :
2072 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
2073 if (auto DtorKind = Field->getType().isDestructedType()) {
2074 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
2075 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
2076 }
2077 }
2078 CGF.FinishFunction();
2079 return DestructorFn;
2080}
2081
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002082/// \brief Emit a privates mapping function for correct handling of private and
2083/// firstprivate variables.
2084/// \code
2085/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
2086/// **noalias priv1,..., <tyn> **noalias privn) {
2087/// *priv1 = &.privates.priv1;
2088/// ...;
2089/// *privn = &.privates.privn;
2090/// }
2091/// \endcode
2092static llvm::Value *
2093emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00002094 ArrayRef<const Expr *> PrivateVars,
2095 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002096 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00002097 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002098 auto &C = CGM.getContext();
2099 FunctionArgList Args;
2100 ImplicitParamDecl TaskPrivatesArg(
2101 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
2102 C.getPointerType(PrivatesQTy).withConst().withRestrict());
2103 Args.push_back(&TaskPrivatesArg);
2104 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
2105 unsigned Counter = 1;
2106 for (auto *E: PrivateVars) {
2107 Args.push_back(ImplicitParamDecl::Create(
2108 C, /*DC=*/nullptr, Loc,
2109 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
2110 .withConst()
2111 .withRestrict()));
2112 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2113 PrivateVarsPos[VD] = Counter;
2114 ++Counter;
2115 }
2116 for (auto *E : FirstprivateVars) {
2117 Args.push_back(ImplicitParamDecl::Create(
2118 C, /*DC=*/nullptr, Loc,
2119 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
2120 .withConst()
2121 .withRestrict()));
2122 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2123 PrivateVarsPos[VD] = Counter;
2124 ++Counter;
2125 }
2126 FunctionType::ExtInfo Info;
2127 auto &TaskPrivatesMapFnInfo =
2128 CGM.getTypes().arrangeFreeFunctionDeclaration(C.VoidTy, Args, Info,
2129 /*isVariadic=*/false);
2130 auto *TaskPrivatesMapTy =
2131 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
2132 auto *TaskPrivatesMap = llvm::Function::Create(
2133 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
2134 ".omp_task_privates_map.", &CGM.getModule());
2135 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskPrivatesMapFnInfo,
2136 TaskPrivatesMap);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00002137 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002138 CodeGenFunction CGF(CGM);
2139 CGF.disableDebugInfo();
2140 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
2141 TaskPrivatesMapFnInfo, Args);
2142
2143 // *privi = &.privates.privi;
Alexey Bataev2377fe92015-09-10 08:12:02 +00002144 LValue Base = emitLoadOfPointerLValue(
2145 CGF, CGF.GetAddrOfLocalVar(&TaskPrivatesArg), TaskPrivatesArg.getType());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002146 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
2147 Counter = 0;
2148 for (auto *Field : PrivatesQTyRD->fields()) {
2149 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
2150 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
John McCall7f416cc2015-09-08 08:05:57 +00002151 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
Alexey Bataev2377fe92015-09-10 08:12:02 +00002152 auto RefLoadLVal =
2153 emitLoadOfPointerLValue(CGF, RefLVal.getAddress(), RefLVal.getType());
2154 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002155 ++Counter;
2156 }
2157 CGF.FinishFunction();
2158 return TaskPrivatesMap;
2159}
2160
Benjamin Kramer9b819032015-09-02 15:31:05 +00002161static llvm::Value *getTypeSize(CodeGenFunction &CGF, QualType Ty) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002162 auto &C = CGF.getContext();
2163 llvm::Value *Size;
2164 auto SizeInChars = C.getTypeSizeInChars(Ty);
2165 if (SizeInChars.isZero()) {
2166 // getTypeSizeInChars() returns 0 for a VLA.
2167 Size = nullptr;
2168 while (auto *VAT = C.getAsVariableArrayType(Ty)) {
2169 llvm::Value *ArraySize;
2170 std::tie(ArraySize, Ty) = CGF.getVLASize(VAT);
2171 Size = Size ? CGF.Builder.CreateNUWMul(Size, ArraySize) : ArraySize;
2172 }
2173 SizeInChars = C.getTypeSizeInChars(Ty);
2174 assert(!SizeInChars.isZero());
2175 Size = CGF.Builder.CreateNUWMul(
2176 Size, llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity()));
2177 } else
2178 Size = llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity());
2179 return Size;
2180}
2181
Alexey Bataev9e034042015-05-05 04:05:12 +00002182static int array_pod_sort_comparator(const PrivateDataTy *P1,
2183 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002184 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
2185}
2186
2187void CGOpenMPRuntime::emitTaskCall(
2188 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
2189 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
John McCall7f416cc2015-09-08 08:05:57 +00002190 llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002191 const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
2192 ArrayRef<const Expr *> PrivateCopies,
2193 ArrayRef<const Expr *> FirstprivateVars,
2194 ArrayRef<const Expr *> FirstprivateCopies,
2195 ArrayRef<const Expr *> FirstprivateInits,
2196 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002197 auto &C = CGM.getContext();
Alexey Bataev9e034042015-05-05 04:05:12 +00002198 llvm::SmallVector<PrivateDataTy, 8> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002199 // Aggregate privates and sort them by the alignment.
Alexey Bataev9e034042015-05-05 04:05:12 +00002200 auto I = PrivateCopies.begin();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002201 for (auto *E : PrivateVars) {
2202 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2203 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00002204 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00002205 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
2206 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002207 ++I;
2208 }
Alexey Bataev9e034042015-05-05 04:05:12 +00002209 I = FirstprivateCopies.begin();
2210 auto IElemInitRef = FirstprivateInits.begin();
2211 for (auto *E : FirstprivateVars) {
2212 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2213 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00002214 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00002215 PrivateHelpersTy(
2216 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
2217 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
2218 ++I, ++IElemInitRef;
2219 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002220 llvm::array_pod_sort(Privates.begin(), Privates.end(),
2221 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002222 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2223 // Build type kmp_routine_entry_t (if not built yet).
2224 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002225 // Build type kmp_task_t (if not built yet).
2226 if (KmpTaskTQTy.isNull()) {
2227 KmpTaskTQTy = C.getRecordType(
2228 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
2229 }
2230 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002231 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002232 auto *KmpTaskTWithPrivatesQTyRD =
2233 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
2234 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
2235 QualType KmpTaskTWithPrivatesPtrQTy =
2236 C.getPointerType(KmpTaskTWithPrivatesQTy);
2237 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
2238 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
2239 auto KmpTaskTWithPrivatesTySize =
2240 CGM.getSize(C.getTypeSizeInChars(KmpTaskTWithPrivatesQTy));
Alexey Bataev62b63b12015-03-10 07:28:44 +00002241 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
2242
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002243 // Emit initial values for private copies (if any).
2244 llvm::Value *TaskPrivatesMap = nullptr;
2245 auto *TaskPrivatesMapTy =
2246 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
2247 3)
2248 ->getType();
2249 if (!Privates.empty()) {
2250 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
2251 TaskPrivatesMap = emitTaskPrivateMappingFunction(
2252 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
2253 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2254 TaskPrivatesMap, TaskPrivatesMapTy);
2255 } else {
2256 TaskPrivatesMap = llvm::ConstantPointerNull::get(
2257 cast<llvm::PointerType>(TaskPrivatesMapTy));
2258 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002259 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
2260 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002261 auto *TaskEntry = emitProxyTaskFunction(
2262 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002263 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002264
2265 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
2266 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2267 // kmp_routine_entry_t *task_entry);
2268 // Task flags. Format is taken from
2269 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
2270 // description of kmp_tasking_flags struct.
2271 const unsigned TiedFlag = 0x1;
2272 const unsigned FinalFlag = 0x2;
2273 unsigned Flags = Tied ? TiedFlag : 0;
2274 auto *TaskFlags =
2275 Final.getPointer()
2276 ? CGF.Builder.CreateSelect(Final.getPointer(),
2277 CGF.Builder.getInt32(FinalFlag),
2278 CGF.Builder.getInt32(/*C=*/0))
2279 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
2280 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
2281 auto SharedsSize = C.getTypeSizeInChars(SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002282 llvm::Value *AllocArgs[] = {
2283 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), TaskFlags,
2284 KmpTaskTWithPrivatesTySize, CGM.getSize(SharedsSize),
2285 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskEntry,
2286 KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00002287 auto *NewTask = CGF.EmitRuntimeCall(
2288 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002289 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2290 NewTask, KmpTaskTWithPrivatesPtrTy);
2291 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
2292 KmpTaskTWithPrivatesQTy);
2293 LValue TDBase =
2294 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002295 // Fill the data in the resulting kmp_task_t record.
2296 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00002297 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002298 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00002299 KmpTaskSharedsPtr =
2300 Address(CGF.EmitLoadOfScalar(
2301 CGF.EmitLValueForField(
2302 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
2303 KmpTaskTShareds)),
2304 Loc),
2305 CGF.getNaturalTypeAlignment(SharedsTy));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002306 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002307 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002308 // Emit initial values for private copies (if any).
2309 bool NeedsCleanup = false;
2310 if (!Privates.empty()) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002311 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
2312 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002313 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002314 LValue SharedsBase;
2315 if (!FirstprivateVars.empty()) {
John McCall7f416cc2015-09-08 08:05:57 +00002316 SharedsBase = CGF.MakeAddrLValue(
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002317 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2318 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
2319 SharedsTy);
2320 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002321 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
2322 cast<CapturedStmt>(*D.getAssociatedStmt()));
2323 for (auto &&Pair : Privates) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002324 auto *VD = Pair.second.PrivateCopy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002325 auto *Init = VD->getAnyInitializer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002326 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002327 if (Init) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002328 if (auto *Elem = Pair.second.PrivateElemInit) {
2329 auto *OriginalVD = Pair.second.Original;
2330 auto *SharedField = CapturesInfo.lookup(OriginalVD);
2331 auto SharedRefLValue =
2332 CGF.EmitLValueForField(SharedsBase, SharedField);
Alexey Bataevc71a4092015-09-11 10:29:41 +00002333 SharedRefLValue = CGF.MakeAddrLValue(
2334 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
2335 SharedRefLValue.getType(), AlignmentSource::Decl);
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002336 QualType Type = OriginalVD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002337 if (Type->isArrayType()) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002338 // Initialize firstprivate array.
2339 if (!isa<CXXConstructExpr>(Init) ||
2340 CGF.isTrivialInitializer(Init)) {
2341 // Perform simple memcpy.
2342 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002343 SharedRefLValue.getAddress(), Type);
Alexey Bataev9e034042015-05-05 04:05:12 +00002344 } else {
2345 // Initialize firstprivate array using element-by-element
2346 // intialization.
2347 CGF.EmitOMPAggregateAssign(
2348 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002349 Type, [&CGF, Elem, Init, &CapturesInfo](
John McCall7f416cc2015-09-08 08:05:57 +00002350 Address DestElement, Address SrcElement) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002351 // Clean up any temporaries needed by the initialization.
2352 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00002353 InitScope.addPrivate(Elem, [SrcElement]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00002354 return SrcElement;
2355 });
2356 (void)InitScope.Privatize();
2357 // Emit initialization for single element.
Alexey Bataevd157d472015-06-24 03:35:38 +00002358 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
2359 CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00002360 CGF.EmitAnyExprToMem(Init, DestElement,
2361 Init->getType().getQualifiers(),
2362 /*IsInitializer=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00002363 });
2364 }
2365 } else {
2366 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00002367 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00002368 return SharedRefLValue.getAddress();
2369 });
2370 (void)InitScope.Privatize();
Alexey Bataevd157d472015-06-24 03:35:38 +00002371 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00002372 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
2373 /*capturedByInit=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00002374 }
2375 } else {
2376 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
2377 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002378 }
2379 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002380 ++FI;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002381 }
2382 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002383 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002384 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002385 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
2386 KmpTaskTWithPrivatesPtrQTy,
2387 KmpTaskTWithPrivatesQTy)
2388 : llvm::ConstantPointerNull::get(
2389 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
2390 LValue Destructor = CGF.EmitLValueForField(
2391 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
2392 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2393 DestructorFn, KmpRoutineEntryPtrTy),
2394 Destructor);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002395
2396 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00002397 Address DependenciesArray = Address::invalid();
2398 unsigned NumDependencies = Dependences.size();
2399 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002400 // Dependence kind for RTL.
2401 enum RTLDependenceKindTy { DepIn = 1, DepOut = 2, DepInOut = 3 };
2402 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
2403 RecordDecl *KmpDependInfoRD;
2404 QualType FlagsTy = C.getIntTypeForBitwidth(
2405 C.toBits(C.getTypeSizeInChars(C.BoolTy)), /*Signed=*/false);
2406 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
2407 if (KmpDependInfoTy.isNull()) {
2408 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
2409 KmpDependInfoRD->startDefinition();
2410 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
2411 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
2412 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
2413 KmpDependInfoRD->completeDefinition();
2414 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
2415 } else {
2416 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
2417 }
John McCall7f416cc2015-09-08 08:05:57 +00002418 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002419 // Define type kmp_depend_info[<Dependences.size()>];
2420 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00002421 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002422 ArrayType::Normal, /*IndexTypeQuals=*/0);
2423 // kmp_depend_info[<Dependences.size()>] deps;
John McCall7f416cc2015-09-08 08:05:57 +00002424 DependenciesArray = CGF.CreateMemTemp(KmpDependInfoArrayTy);
2425 for (unsigned i = 0; i < NumDependencies; ++i) {
2426 const Expr *E = Dependences[i].second;
2427 auto Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002428 llvm::Value *Size;
2429 QualType Ty = E->getType();
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002430 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
2431 LValue UpAddrLVal =
2432 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
2433 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00002434 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002435 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00002436 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002437 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
2438 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
John McCall7f416cc2015-09-08 08:05:57 +00002439 } else {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002440 Size = getTypeSize(CGF, Ty);
John McCall7f416cc2015-09-08 08:05:57 +00002441 }
2442 auto Base = CGF.MakeAddrLValue(
2443 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002444 KmpDependInfoTy);
2445 // deps[i].base_addr = &<Dependences[i].second>;
2446 auto BaseAddrLVal = CGF.EmitLValueForField(
2447 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00002448 CGF.EmitStoreOfScalar(
2449 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
2450 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002451 // deps[i].len = sizeof(<Dependences[i].second>);
2452 auto LenLVal = CGF.EmitLValueForField(
2453 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
2454 CGF.EmitStoreOfScalar(Size, LenLVal);
2455 // deps[i].flags = <Dependences[i].first>;
2456 RTLDependenceKindTy DepKind;
2457 switch (Dependences[i].first) {
2458 case OMPC_DEPEND_in:
2459 DepKind = DepIn;
2460 break;
2461 case OMPC_DEPEND_out:
2462 DepKind = DepOut;
2463 break;
2464 case OMPC_DEPEND_inout:
2465 DepKind = DepInOut;
2466 break;
2467 case OMPC_DEPEND_unknown:
2468 llvm_unreachable("Unknown task dependence type");
2469 }
2470 auto FlagsLVal = CGF.EmitLValueForField(
2471 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
2472 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
2473 FlagsLVal);
2474 }
John McCall7f416cc2015-09-08 08:05:57 +00002475 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2476 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002477 CGF.VoidPtrTy);
2478 }
2479
Alexey Bataev62b63b12015-03-10 07:28:44 +00002480 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
2481 // libcall.
2482 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2483 // *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002484 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2485 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2486 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
2487 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00002488 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002489 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00002490 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
2491 llvm::Value *DepTaskArgs[7];
2492 if (NumDependencies) {
2493 DepTaskArgs[0] = UpLoc;
2494 DepTaskArgs[1] = ThreadID;
2495 DepTaskArgs[2] = NewTask;
2496 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
2497 DepTaskArgs[4] = DependenciesArray.getPointer();
2498 DepTaskArgs[5] = CGF.Builder.getInt32(0);
2499 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2500 }
2501 auto &&ThenCodeGen = [this, NumDependencies,
2502 &TaskArgs, &DepTaskArgs](CodeGenFunction &CGF) {
2503 // TODO: add check for untied tasks.
2504 if (NumDependencies) {
2505 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps),
2506 DepTaskArgs);
2507 } else {
2508 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
2509 TaskArgs);
2510 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002511 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00002512 typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value>
2513 IfCallEndCleanup;
John McCall7f416cc2015-09-08 08:05:57 +00002514
2515 llvm::Value *DepWaitTaskArgs[6];
2516 if (NumDependencies) {
2517 DepWaitTaskArgs[0] = UpLoc;
2518 DepWaitTaskArgs[1] = ThreadID;
2519 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
2520 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
2521 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
2522 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2523 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002524 auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
John McCall7f416cc2015-09-08 08:05:57 +00002525 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002526 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
2527 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2528 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
2529 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
2530 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00002531 if (NumDependencies)
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002532 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
2533 DepWaitTaskArgs);
2534 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
2535 // kmp_task_t *new_task);
2536 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0),
2537 TaskArgs);
2538 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
2539 // kmp_task_t *new_task);
2540 CGF.EHStack.pushCleanup<IfCallEndCleanup>(
2541 NormalAndEHCleanup,
2542 createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0),
2543 llvm::makeArrayRef(TaskArgs));
Alexey Bataev1d677132015-04-22 13:57:31 +00002544
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002545 // Call proxy_task_entry(gtid, new_task);
2546 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
2547 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
2548 };
John McCall7f416cc2015-09-08 08:05:57 +00002549
Alexey Bataev1d677132015-04-22 13:57:31 +00002550 if (IfCond) {
2551 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
2552 } else {
2553 CodeGenFunction::RunCleanupsScope Scope(CGF);
2554 ThenCodeGen(CGF);
2555 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002556}
2557
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002558static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
2559 llvm::Type *ArgsType,
2560 ArrayRef<const Expr *> LHSExprs,
2561 ArrayRef<const Expr *> RHSExprs,
2562 ArrayRef<const Expr *> ReductionOps) {
2563 auto &C = CGM.getContext();
2564
2565 // void reduction_func(void *LHSArg, void *RHSArg);
2566 FunctionArgList Args;
2567 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2568 C.VoidPtrTy);
2569 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2570 C.VoidPtrTy);
2571 Args.push_back(&LHSArg);
2572 Args.push_back(&RHSArg);
2573 FunctionType::ExtInfo EI;
2574 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
2575 C.VoidTy, Args, EI, /*isVariadic=*/false);
2576 auto *Fn = llvm::Function::Create(
2577 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
2578 ".omp.reduction.reduction_func", &CGM.getModule());
2579 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
2580 CodeGenFunction CGF(CGM);
2581 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
2582
2583 // Dst = (void*[n])(LHSArg);
2584 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00002585 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2586 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2587 ArgsType), CGF.getPointerAlign());
2588 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2589 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2590 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002591
2592 // ...
2593 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
2594 // ...
2595 CodeGenFunction::OMPPrivateScope Scope(CGF);
2596 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002597 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
2598 Scope.addPrivate(RHSVar, [&]() -> Address {
2599 return emitAddrOfVarFromArray(CGF, RHS, I, RHSVar);
2600 });
2601 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
2602 Scope.addPrivate(LHSVar, [&]() -> Address {
2603 return emitAddrOfVarFromArray(CGF, LHS, I, LHSVar);
2604 });
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002605 }
2606 Scope.Privatize();
2607 for (auto *E : ReductionOps) {
2608 CGF.EmitIgnoredExpr(E);
2609 }
2610 Scope.ForceCleanup();
2611 CGF.FinishFunction();
2612 return Fn;
2613}
2614
2615void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
2616 ArrayRef<const Expr *> LHSExprs,
2617 ArrayRef<const Expr *> RHSExprs,
2618 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002619 bool WithNowait, bool SimpleReduction) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002620 // Next code should be emitted for reduction:
2621 //
2622 // static kmp_critical_name lock = { 0 };
2623 //
2624 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
2625 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
2626 // ...
2627 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
2628 // *(Type<n>-1*)rhs[<n>-1]);
2629 // }
2630 //
2631 // ...
2632 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
2633 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2634 // RedList, reduce_func, &<lock>)) {
2635 // case 1:
2636 // ...
2637 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2638 // ...
2639 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2640 // break;
2641 // case 2:
2642 // ...
2643 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2644 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00002645 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002646 // break;
2647 // default:;
2648 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002649 //
2650 // if SimpleReduction is true, only the next code is generated:
2651 // ...
2652 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2653 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002654
2655 auto &C = CGM.getContext();
2656
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002657 if (SimpleReduction) {
2658 CodeGenFunction::RunCleanupsScope Scope(CGF);
2659 for (auto *E : ReductionOps) {
2660 CGF.EmitIgnoredExpr(E);
2661 }
2662 return;
2663 }
2664
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002665 // 1. Build a list of reduction variables.
2666 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
2667 llvm::APInt ArraySize(/*unsigned int numBits=*/32, RHSExprs.size());
2668 QualType ReductionArrayTy =
2669 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2670 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00002671 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002672 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
2673 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002674 Address Elem =
2675 CGF.Builder.CreateConstArrayGEP(ReductionList, I, CGF.getPointerSize());
2676 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002677 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002678 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
2679 Elem);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002680 }
2681
2682 // 2. Emit reduce_func().
2683 auto *ReductionFn = emitReductionFunction(
2684 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), LHSExprs,
2685 RHSExprs, ReductionOps);
2686
2687 // 3. Create static kmp_critical_name lock = { 0 };
2688 auto *Lock = getCriticalRegionLock(".reduction");
2689
2690 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2691 // RedList, reduce_func, &<lock>);
2692 auto *IdentTLoc = emitUpdateLocation(
2693 CGF, Loc,
2694 static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE));
2695 auto *ThreadId = getThreadID(CGF, Loc);
2696 auto *ReductionArrayTySize = llvm::ConstantInt::get(
2697 CGM.SizeTy, C.getTypeSizeInChars(ReductionArrayTy).getQuantity());
John McCall7f416cc2015-09-08 08:05:57 +00002698 auto *RL =
2699 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
2700 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002701 llvm::Value *Args[] = {
2702 IdentTLoc, // ident_t *<loc>
2703 ThreadId, // i32 <gtid>
2704 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
2705 ReductionArrayTySize, // size_type sizeof(RedList)
2706 RL, // void *RedList
2707 ReductionFn, // void (*) (void *, void *) <reduce_func>
2708 Lock // kmp_critical_name *&<lock>
2709 };
2710 auto Res = CGF.EmitRuntimeCall(
2711 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
2712 : OMPRTL__kmpc_reduce),
2713 Args);
2714
2715 // 5. Build switch(res)
2716 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
2717 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
2718
2719 // 6. Build case 1:
2720 // ...
2721 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2722 // ...
2723 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2724 // break;
2725 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
2726 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
2727 CGF.EmitBlock(Case1BB);
2728
2729 {
2730 CodeGenFunction::RunCleanupsScope Scope(CGF);
2731 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2732 llvm::Value *EndArgs[] = {
2733 IdentTLoc, // ident_t *<loc>
2734 ThreadId, // i32 <gtid>
2735 Lock // kmp_critical_name *&<lock>
2736 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00002737 CGF.EHStack
2738 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
2739 NormalAndEHCleanup,
2740 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
2741 : OMPRTL__kmpc_end_reduce),
2742 llvm::makeArrayRef(EndArgs));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002743 for (auto *E : ReductionOps) {
2744 CGF.EmitIgnoredExpr(E);
2745 }
2746 }
2747
2748 CGF.EmitBranch(DefaultBB);
2749
2750 // 7. Build case 2:
2751 // ...
2752 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2753 // ...
2754 // break;
2755 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
2756 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
2757 CGF.EmitBlock(Case2BB);
2758
2759 {
2760 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataev69a47792015-05-07 03:54:03 +00002761 if (!WithNowait) {
2762 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
2763 llvm::Value *EndArgs[] = {
2764 IdentTLoc, // ident_t *<loc>
2765 ThreadId, // i32 <gtid>
2766 Lock // kmp_critical_name *&<lock>
2767 };
2768 CGF.EHStack
2769 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
2770 NormalAndEHCleanup,
2771 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
2772 llvm::makeArrayRef(EndArgs));
2773 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002774 auto I = LHSExprs.begin();
2775 for (auto *E : ReductionOps) {
2776 const Expr *XExpr = nullptr;
2777 const Expr *EExpr = nullptr;
2778 const Expr *UpExpr = nullptr;
2779 BinaryOperatorKind BO = BO_Comma;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002780 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
2781 if (BO->getOpcode() == BO_Assign) {
2782 XExpr = BO->getLHS();
2783 UpExpr = BO->getRHS();
2784 }
2785 }
Alexey Bataev69a47792015-05-07 03:54:03 +00002786 // Try to emit update expression as a simple atomic.
2787 auto *RHSExpr = UpExpr;
2788 if (RHSExpr) {
2789 // Analyze RHS part of the whole expression.
2790 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
2791 RHSExpr->IgnoreParenImpCasts())) {
2792 // If this is a conditional operator, analyze its condition for
2793 // min/max reduction operator.
2794 RHSExpr = ACO->getCond();
2795 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002796 if (auto *BORHS =
Alexey Bataev69a47792015-05-07 03:54:03 +00002797 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002798 EExpr = BORHS->getRHS();
2799 BO = BORHS->getOpcode();
2800 }
2801 }
2802 if (XExpr) {
2803 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
2804 LValue X = CGF.EmitLValue(XExpr);
2805 RValue E;
2806 if (EExpr)
2807 E = CGF.EmitAnyExpr(EExpr);
2808 CGF.EmitOMPAtomicSimpleUpdateExpr(
2809 X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
2810 [&CGF, UpExpr, VD](RValue XRValue) {
2811 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
2812 PrivateScope.addPrivate(
John McCall7f416cc2015-09-08 08:05:57 +00002813 VD, [&CGF, VD, XRValue]() -> Address {
2814 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002815 CGF.EmitStoreThroughLValue(
2816 XRValue,
John McCall7f416cc2015-09-08 08:05:57 +00002817 CGF.MakeAddrLValue(LHSTemp, VD->getType()));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002818 return LHSTemp;
2819 });
2820 (void)PrivateScope.Privatize();
2821 return CGF.EmitAnyExpr(UpExpr);
2822 });
2823 } else {
2824 // Emit as a critical region.
2825 emitCriticalRegion(CGF, ".atomic_reduction", [E](CodeGenFunction &CGF) {
2826 CGF.EmitIgnoredExpr(E);
2827 }, Loc);
2828 }
2829 ++I;
2830 }
2831 }
2832
2833 CGF.EmitBranch(DefaultBB);
2834 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
2835}
2836
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002837void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
2838 SourceLocation Loc) {
2839 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
2840 // global_tid);
2841 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2842 // Ignore return result until untied tasks are supported.
2843 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
2844}
2845
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002846void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002847 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00002848 const RegionCodeGenTy &CodeGen,
2849 bool HasCancel) {
2850 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002851 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00002852}
2853
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002854namespace {
2855enum RTCancelKind {
2856 CancelNoreq = 0,
2857 CancelParallel = 1,
2858 CancelLoop = 2,
2859 CancelSections = 3,
2860 CancelTaskgroup = 4
2861};
2862}
2863
2864static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
2865 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00002866 if (CancelRegion == OMPD_parallel)
2867 CancelKind = CancelParallel;
2868 else if (CancelRegion == OMPD_for)
2869 CancelKind = CancelLoop;
2870 else if (CancelRegion == OMPD_sections)
2871 CancelKind = CancelSections;
2872 else {
2873 assert(CancelRegion == OMPD_taskgroup);
2874 CancelKind = CancelTaskgroup;
2875 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002876 return CancelKind;
2877}
2878
2879void CGOpenMPRuntime::emitCancellationPointCall(
2880 CodeGenFunction &CGF, SourceLocation Loc,
2881 OpenMPDirectiveKind CancelRegion) {
2882 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2883 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002884 if (auto *OMPRegionInfo =
2885 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00002886 if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
2887 return;
2888 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002889 llvm::Value *Args[] = {
2890 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2891 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002892 // Ignore return result until untied tasks are supported.
2893 auto *Result = CGF.EmitRuntimeCall(
2894 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
2895 // if (__kmpc_cancellationpoint()) {
2896 // __kmpc_cancel_barrier();
2897 // exit from construct;
2898 // }
2899 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
2900 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
2901 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
2902 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2903 CGF.EmitBlock(ExitBB);
2904 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00002905 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002906 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00002907 auto CancelDest =
2908 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002909 CGF.EmitBranchThroughCleanup(CancelDest);
2910 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2911 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002912 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002913}
2914
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002915void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00002916 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002917 OpenMPDirectiveKind CancelRegion) {
2918 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2919 // kmp_int32 cncl_kind);
2920 if (auto *OMPRegionInfo =
2921 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00002922 if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
2923 return;
Alexey Bataev87933c72015-09-18 08:07:34 +00002924 auto &&ThenGen = [this, Loc, CancelRegion,
2925 OMPRegionInfo](CodeGenFunction &CGF) {
2926 llvm::Value *Args[] = {
2927 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2928 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
2929 // Ignore return result until untied tasks are supported.
2930 auto *Result =
2931 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
2932 // if (__kmpc_cancel()) {
2933 // __kmpc_cancel_barrier();
2934 // exit from construct;
2935 // }
2936 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
2937 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
2938 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
2939 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2940 CGF.EmitBlock(ExitBB);
2941 // __kmpc_cancel_barrier();
2942 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
2943 // exit from construct;
2944 auto CancelDest =
2945 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
2946 CGF.EmitBranchThroughCleanup(CancelDest);
2947 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2948 };
2949 if (IfCond)
2950 emitOMPIfClause(CGF, IfCond, ThenGen, [](CodeGenFunction &) {});
2951 else
2952 ThenGen(CGF);
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002953 }
2954}