blob: 98a83b661b52f67573c0838e7d0806146ce5cdd7 [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,
Samuel Antaobed3c462015-10-02 16:14:20 +000044 /// \brief Region with outlined function for standalone 'target' directive.
45 TargetRegion,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000046 };
Alexey Bataev18095712014-10-10 12:19:54 +000047
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000048 CGOpenMPRegionInfo(const CapturedStmt &CS,
49 const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000050 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
51 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000052 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000053 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000054
55 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000056 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
57 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000058 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000059 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000060
61 /// \brief Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000062 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000063 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000064
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000065 /// \brief Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000066 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000067
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000068 /// \brief Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000069 /// \return LValue for thread id variable. This LValue always has type int32*.
70 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000071
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000072 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000073
Alexey Bataev81c7ea02015-07-03 09:56:58 +000074 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
75
Alexey Bataev25e5b442015-09-15 12:52:43 +000076 bool hasCancel() const { return HasCancel; }
77
Alexey Bataev18095712014-10-10 12:19:54 +000078 static bool classof(const CGCapturedStmtInfo *Info) {
79 return Info->getKind() == CR_OpenMP;
80 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000081
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000082protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000083 CGOpenMPRegionKind RegionKind;
84 const RegionCodeGenTy &CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000085 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +000086 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000087};
Alexey Bataev18095712014-10-10 12:19:54 +000088
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000089/// \brief API for captured statement code generation in OpenMP constructs.
90class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
91public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000092 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +000093 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +000094 OpenMPDirectiveKind Kind, bool HasCancel)
95 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
96 HasCancel),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000097 ThreadIDVar(ThreadIDVar) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000098 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
99 }
100 /// \brief Get a variable or parameter for storing global thread id
101 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000102 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000103
Alexey Bataev18095712014-10-10 12:19:54 +0000104 /// \brief Get the name of the capture helper.
Benjamin Kramerc52193f2014-10-10 13:57:57 +0000105 StringRef getHelperName() const override { return ".omp_outlined."; }
Alexey Bataev18095712014-10-10 12:19:54 +0000106
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000107 static bool classof(const CGCapturedStmtInfo *Info) {
108 return CGOpenMPRegionInfo::classof(Info) &&
109 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
110 ParallelOutlinedRegion;
111 }
112
Alexey Bataev18095712014-10-10 12:19:54 +0000113private:
114 /// \brief A variable or parameter storing global thread id for OpenMP
115 /// constructs.
116 const VarDecl *ThreadIDVar;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000117};
118
Alexey Bataev62b63b12015-03-10 07:28:44 +0000119/// \brief API for captured statement code generation in OpenMP constructs.
120class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo {
121public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000122 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000123 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000124 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000125 OpenMPDirectiveKind Kind, bool HasCancel)
126 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000127 ThreadIDVar(ThreadIDVar) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000128 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
129 }
130 /// \brief Get a variable or parameter for storing global thread id
131 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000132 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000133
134 /// \brief Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000135 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000136
Alexey Bataev62b63b12015-03-10 07:28:44 +0000137 /// \brief Get the name of the capture helper.
138 StringRef getHelperName() const override { return ".omp_outlined."; }
139
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000140 static bool classof(const CGCapturedStmtInfo *Info) {
141 return CGOpenMPRegionInfo::classof(Info) &&
142 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
143 TaskOutlinedRegion;
144 }
145
Alexey Bataev62b63b12015-03-10 07:28:44 +0000146private:
147 /// \brief A variable or parameter storing global thread id for OpenMP
148 /// constructs.
149 const VarDecl *ThreadIDVar;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000150};
151
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000152/// \brief API for inlined captured statement code generation in OpenMP
153/// constructs.
154class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
155public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000156 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000157 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000158 OpenMPDirectiveKind Kind, bool HasCancel)
159 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
160 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000161 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
162 // \brief Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000163 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000164 if (OuterRegionInfo)
165 return OuterRegionInfo->getContextValue();
166 llvm_unreachable("No context value for inlined OpenMP region");
167 }
Hans Wennborg7eb54642015-09-10 17:07:54 +0000168 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000169 if (OuterRegionInfo) {
170 OuterRegionInfo->setContextValue(V);
171 return;
172 }
173 llvm_unreachable("No context value for inlined OpenMP region");
174 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000175 /// \brief Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000176 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000177 if (OuterRegionInfo)
178 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000179 // If there is no outer outlined region,no need to lookup in a list of
180 // captured variables, we can use the original one.
181 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000182 }
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000183 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000184 if (OuterRegionInfo)
185 return OuterRegionInfo->getThisFieldDecl();
186 return nullptr;
187 }
188 /// \brief Get a variable or parameter for storing global thread id
189 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000190 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000191 if (OuterRegionInfo)
192 return OuterRegionInfo->getThreadIDVariable();
193 return nullptr;
194 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000195
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000196 /// \brief Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000197 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000198 if (auto *OuterRegionInfo = getOldCSI())
199 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000200 llvm_unreachable("No helper name for inlined OpenMP construct");
201 }
202
203 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
204
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000205 static bool classof(const CGCapturedStmtInfo *Info) {
206 return CGOpenMPRegionInfo::classof(Info) &&
207 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
208 }
209
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000210private:
211 /// \brief CodeGen info about outer OpenMP region.
212 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
213 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000214};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000215
Samuel Antaobed3c462015-10-02 16:14:20 +0000216/// \brief API for captured statement code generation in OpenMP target
217/// constructs. For this captures, implicit parameters are used instead of the
218/// captured fields.
219class CGOpenMPTargetRegionInfo : public CGOpenMPRegionInfo {
220public:
221 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
222 const RegionCodeGenTy &CodeGen)
223 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
224 /*HasCancel = */ false) {}
225
226 /// \brief This is unused for target regions because each starts executing
227 /// with a single thread.
228 const VarDecl *getThreadIDVariable() const override { return nullptr; }
229
230 /// \brief Get the name of the capture helper.
231 StringRef getHelperName() const override { return ".omp_offloading."; }
232
233 static bool classof(const CGCapturedStmtInfo *Info) {
234 return CGOpenMPRegionInfo::classof(Info) &&
235 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
236 }
237};
238
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000239/// \brief RAII for emitting code of OpenMP constructs.
240class InlinedOpenMPRegionRAII {
241 CodeGenFunction &CGF;
242
243public:
244 /// \brief Constructs region for combined constructs.
245 /// \param CodeGen Code generation sequence for combined directives. Includes
246 /// a list of functions used for code generation of implicitly inlined
247 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000248 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000249 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000250 : CGF(CGF) {
251 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000252 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
253 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000254 }
255 ~InlinedOpenMPRegionRAII() {
256 // Restore original CapturedStmtInfo only if we're done with code emission.
257 auto *OldCSI =
258 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
259 delete CGF.CapturedStmtInfo;
260 CGF.CapturedStmtInfo = OldCSI;
261 }
262};
263
Hans Wennborg7eb54642015-09-10 17:07:54 +0000264} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000265
Alexey Bataev2377fe92015-09-10 08:12:02 +0000266static LValue emitLoadOfPointerLValue(CodeGenFunction &CGF, Address PtrAddr,
267 QualType Ty) {
268 AlignmentSource Source;
269 CharUnits Align = CGF.getNaturalPointeeTypeAlignment(Ty, &Source);
270 return CGF.MakeAddrLValue(Address(CGF.Builder.CreateLoad(PtrAddr), Align),
271 Ty->getPointeeType(), Source);
272}
273
Alexey Bataev18095712014-10-10 12:19:54 +0000274LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000275 return emitLoadOfPointerLValue(CGF,
276 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
277 getThreadIDVariable()->getType());
Alexey Bataev18095712014-10-10 12:19:54 +0000278}
279
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000280void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
281 // 1.2.2 OpenMP Language Terminology
282 // Structured block - An executable statement with a single entry at the
283 // top and a single exit at the bottom.
284 // The point of exit cannot be a branch out of the structured block.
285 // longjmp() and throw() must not violate the entry/exit criteria.
286 CGF.EHStack.pushTerminate();
287 {
288 CodeGenFunction::RunCleanupsScope Scope(CGF);
289 CodeGen(CGF);
290 }
291 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000292}
293
Alexey Bataev62b63b12015-03-10 07:28:44 +0000294LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
295 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000296 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
297 getThreadIDVariable()->getType(),
298 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000299}
300
Alexey Bataev9959db52014-05-06 10:08:46 +0000301CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
Alexey Bataev62b63b12015-03-10 07:28:44 +0000302 : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000303 IdentTy = llvm::StructType::create(
304 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
305 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000306 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000307 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
Alexey Bataev23b69422014-06-18 07:08:49 +0000308 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
309 llvm::PointerType::getUnqual(CGM.Int32Ty)};
Alexey Bataev9959db52014-05-06 10:08:46 +0000310 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000311 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Alexey Bataev9959db52014-05-06 10:08:46 +0000312}
313
Alexey Bataev91797552015-03-18 04:13:55 +0000314void CGOpenMPRuntime::clear() {
315 InternalVars.clear();
316}
317
John McCall7f416cc2015-09-08 08:05:57 +0000318// Layout information for ident_t.
319static CharUnits getIdentAlign(CodeGenModule &CGM) {
320 return CGM.getPointerAlign();
321}
322static CharUnits getIdentSize(CodeGenModule &CGM) {
323 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign()));
324 return CharUnits::fromQuantity(16) + CGM.getPointerSize();
325}
326static CharUnits getOffsetOfIdentField(CGOpenMPRuntime::IdentFieldIndex Field) {
327 // All the fields except the last are i32, so this works beautifully.
328 return unsigned(Field) * CharUnits::fromQuantity(4);
329}
330static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
331 CGOpenMPRuntime::IdentFieldIndex Field,
332 const llvm::Twine &Name = "") {
333 auto Offset = getOffsetOfIdentField(Field);
334 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
335}
336
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000337llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction(
338 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
339 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000340 assert(ThreadIDVar->getType()->isPointerType() &&
341 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +0000342 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
343 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +0000344 bool HasCancel = false;
345 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
346 HasCancel = OPD->hasCancel();
347 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
348 HasCancel = OPSD->hasCancel();
349 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
350 HasCancel = OPFD->hasCancel();
351 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
352 HasCancel);
Alexey Bataevd157d472015-06-24 03:35:38 +0000353 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000354 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +0000355}
356
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000357llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
358 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
359 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000360 assert(!ThreadIDVar->getType()->isPointerType() &&
361 "thread id variable must be of type kmp_int32 for tasks");
362 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
363 CodeGenFunction CGF(CGM, true);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000364 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000365 InnermostKind,
366 cast<OMPTaskDirective>(D).hasCancel());
Alexey Bataevd157d472015-06-24 03:35:38 +0000367 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000368 return CGF.GenerateCapturedStmtFunction(*CS);
369}
370
John McCall7f416cc2015-09-08 08:05:57 +0000371Address CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
372 CharUnits Align = getIdentAlign(CGM);
Alexey Bataev15007ba2014-05-07 06:18:01 +0000373 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000374 if (!Entry) {
375 if (!DefaultOpenMPPSource) {
376 // Initialize default location for psource field of ident_t structure of
377 // all ident_t objects. Format is ";file;function;line;column;;".
378 // Taken from
379 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
380 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +0000381 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000382 DefaultOpenMPPSource =
383 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
384 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000385 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
386 CGM.getModule(), IdentTy, /*isConstant*/ true,
387 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000388 DefaultOpenMPLocation->setUnnamedAddr(true);
John McCall7f416cc2015-09-08 08:05:57 +0000389 DefaultOpenMPLocation->setAlignment(Align.getQuantity());
Alexey Bataev9959db52014-05-06 10:08:46 +0000390
391 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000392 llvm::Constant *Values[] = {Zero,
393 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
394 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000395 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
396 DefaultOpenMPLocation->setInitializer(Init);
John McCall7f416cc2015-09-08 08:05:57 +0000397 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000398 }
John McCall7f416cc2015-09-08 08:05:57 +0000399 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +0000400}
401
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000402llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
403 SourceLocation Loc,
404 OpenMPLocationFlags Flags) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000405 // If no debug info is generated - return global default location.
406 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
407 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +0000408 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000409
410 assert(CGF.CurFn && "No function in current CodeGenFunction.");
411
John McCall7f416cc2015-09-08 08:05:57 +0000412 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000413 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
414 if (I != OpenMPLocThreadIDMap.end())
John McCall7f416cc2015-09-08 08:05:57 +0000415 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
416
Alexander Musmanc6388682014-12-15 07:07:06 +0000417 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
418 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +0000419 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000420 // Generate "ident_t .kmpc_loc.addr;"
John McCall7f416cc2015-09-08 08:05:57 +0000421 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
422 ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +0000423 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +0000424 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000425 LocValue = AI;
426
427 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
428 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000429 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
John McCall7f416cc2015-09-08 08:05:57 +0000430 CGM.getSize(getIdentSize(CGF.CGM)));
Alexey Bataev9959db52014-05-06 10:08:46 +0000431 }
432
433 // char **psource = &.kmpc_loc_<flags>.addr.psource;
John McCall7f416cc2015-09-08 08:05:57 +0000434 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000435
Alexey Bataevf002aca2014-05-30 05:48:40 +0000436 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
437 if (OMPDebugLoc == nullptr) {
438 SmallString<128> Buffer2;
439 llvm::raw_svector_ostream OS2(Buffer2);
440 // Build debug location
441 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
442 OS2 << ";" << PLoc.getFilename() << ";";
443 if (const FunctionDecl *FD =
444 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
445 OS2 << FD->getQualifiedNameAsString();
446 }
447 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
448 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
449 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000450 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000451 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000452 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
453
John McCall7f416cc2015-09-08 08:05:57 +0000454 // Our callers always pass this to a runtime function, so for
455 // convenience, go ahead and return a naked pointer.
456 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000457}
458
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000459llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
460 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000461 assert(CGF.CurFn && "No function in current CodeGenFunction.");
462
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000463 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000464 // Check whether we've already cached a load of the thread id in this
465 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000466 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000467 if (I != OpenMPLocThreadIDMap.end()) {
468 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000469 if (ThreadID != nullptr)
470 return ThreadID;
471 }
472 if (auto OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000473 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000474 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000475 // Check if this an outlined function with thread id passed as argument.
476 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000477 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
478 // If value loaded in entry block, cache it and use it everywhere in
479 // function.
480 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
481 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
482 Elem.second.ThreadID = ThreadID;
483 }
484 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000485 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000486 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000487
488 // This is not an outlined function region - need to call __kmpc_int32
489 // kmpc_global_thread_num(ident_t *loc).
490 // Generate thread id value and cache this value for use across the
491 // function.
492 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
493 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
494 ThreadID =
495 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
496 emitUpdateLocation(CGF, Loc));
497 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
498 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000499 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000500}
501
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000502void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000503 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000504 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
505 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataev9959db52014-05-06 10:08:46 +0000506}
507
508llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
509 return llvm::PointerType::getUnqual(IdentTy);
510}
511
512llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
513 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
514}
515
516llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000517CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000518 llvm::Constant *RTLFn = nullptr;
519 switch (Function) {
520 case OMPRTL__kmpc_fork_call: {
521 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
522 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +0000523 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
524 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000525 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000526 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +0000527 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
528 break;
529 }
530 case OMPRTL__kmpc_global_thread_num: {
531 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +0000532 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000533 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000534 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +0000535 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
536 break;
537 }
Alexey Bataev97720002014-11-11 04:05:39 +0000538 case OMPRTL__kmpc_threadprivate_cached: {
539 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
540 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
541 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
542 CGM.VoidPtrTy, CGM.SizeTy,
543 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
544 llvm::FunctionType *FnTy =
545 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
546 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
547 break;
548 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000549 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000550 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
551 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000552 llvm::Type *TypeParams[] = {
553 getIdentTyPointerTy(), CGM.Int32Ty,
554 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
555 llvm::FunctionType *FnTy =
556 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
557 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
558 break;
559 }
Alexey Bataevfc57d162015-12-15 10:55:09 +0000560 case OMPRTL__kmpc_critical_with_hint: {
561 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
562 // kmp_critical_name *crit, uintptr_t hint);
563 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
564 llvm::PointerType::getUnqual(KmpCriticalNameTy),
565 CGM.IntPtrTy};
566 llvm::FunctionType *FnTy =
567 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
568 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
569 break;
570 }
Alexey Bataev97720002014-11-11 04:05:39 +0000571 case OMPRTL__kmpc_threadprivate_register: {
572 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
573 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
574 // typedef void *(*kmpc_ctor)(void *);
575 auto KmpcCtorTy =
576 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
577 /*isVarArg*/ false)->getPointerTo();
578 // typedef void *(*kmpc_cctor)(void *, void *);
579 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
580 auto KmpcCopyCtorTy =
581 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
582 /*isVarArg*/ false)->getPointerTo();
583 // typedef void (*kmpc_dtor)(void *);
584 auto KmpcDtorTy =
585 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
586 ->getPointerTo();
587 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
588 KmpcCopyCtorTy, KmpcDtorTy};
589 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
590 /*isVarArg*/ false);
591 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
592 break;
593 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000594 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000595 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
596 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000597 llvm::Type *TypeParams[] = {
598 getIdentTyPointerTy(), CGM.Int32Ty,
599 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
600 llvm::FunctionType *FnTy =
601 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
602 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
603 break;
604 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000605 case OMPRTL__kmpc_cancel_barrier: {
606 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
607 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000608 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
609 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000610 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
611 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000612 break;
613 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000614 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +0000615 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000616 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
617 llvm::FunctionType *FnTy =
618 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
619 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
620 break;
621 }
Alexander Musmanc6388682014-12-15 07:07:06 +0000622 case OMPRTL__kmpc_for_static_fini: {
623 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
624 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
625 llvm::FunctionType *FnTy =
626 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
627 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
628 break;
629 }
Alexey Bataevb2059782014-10-13 08:23:51 +0000630 case OMPRTL__kmpc_push_num_threads: {
631 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
632 // kmp_int32 num_threads)
633 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
634 CGM.Int32Ty};
635 llvm::FunctionType *FnTy =
636 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
637 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
638 break;
639 }
Alexey Bataevd74d0602014-10-13 06:02:40 +0000640 case OMPRTL__kmpc_serialized_parallel: {
641 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
642 // global_tid);
643 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
644 llvm::FunctionType *FnTy =
645 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
646 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
647 break;
648 }
649 case OMPRTL__kmpc_end_serialized_parallel: {
650 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
651 // global_tid);
652 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
653 llvm::FunctionType *FnTy =
654 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
655 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
656 break;
657 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000658 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000659 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000660 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
661 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000662 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000663 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
664 break;
665 }
Alexey Bataev8d690652014-12-04 07:23:53 +0000666 case OMPRTL__kmpc_master: {
667 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
668 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
669 llvm::FunctionType *FnTy =
670 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
671 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
672 break;
673 }
674 case OMPRTL__kmpc_end_master: {
675 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
676 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
677 llvm::FunctionType *FnTy =
678 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
679 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
680 break;
681 }
Alexey Bataev9f797f32015-02-05 05:57:51 +0000682 case OMPRTL__kmpc_omp_taskyield: {
683 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
684 // int end_part);
685 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
686 llvm::FunctionType *FnTy =
687 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
688 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
689 break;
690 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +0000691 case OMPRTL__kmpc_single: {
692 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
693 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
694 llvm::FunctionType *FnTy =
695 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
696 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
697 break;
698 }
699 case OMPRTL__kmpc_end_single: {
700 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
701 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
702 llvm::FunctionType *FnTy =
703 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
704 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
705 break;
706 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000707 case OMPRTL__kmpc_omp_task_alloc: {
708 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
709 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
710 // kmp_routine_entry_t *task_entry);
711 assert(KmpRoutineEntryPtrTy != nullptr &&
712 "Type kmp_routine_entry_t must be created.");
713 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
714 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
715 // Return void * and then cast to particular kmp_task_t type.
716 llvm::FunctionType *FnTy =
717 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
718 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
719 break;
720 }
721 case OMPRTL__kmpc_omp_task: {
722 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
723 // *new_task);
724 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
725 CGM.VoidPtrTy};
726 llvm::FunctionType *FnTy =
727 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
728 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
729 break;
730 }
Alexey Bataeva63048e2015-03-23 06:18:07 +0000731 case OMPRTL__kmpc_copyprivate: {
732 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +0000733 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +0000734 // kmp_int32 didit);
735 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
736 auto *CpyFnTy =
737 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +0000738 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +0000739 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
740 CGM.Int32Ty};
741 llvm::FunctionType *FnTy =
742 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
743 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
744 break;
745 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +0000746 case OMPRTL__kmpc_reduce: {
747 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
748 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
749 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
750 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
751 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
752 /*isVarArg=*/false);
753 llvm::Type *TypeParams[] = {
754 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
755 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
756 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
757 llvm::FunctionType *FnTy =
758 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
759 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
760 break;
761 }
762 case OMPRTL__kmpc_reduce_nowait: {
763 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
764 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
765 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
766 // *lck);
767 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
768 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
769 /*isVarArg=*/false);
770 llvm::Type *TypeParams[] = {
771 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
772 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
773 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
774 llvm::FunctionType *FnTy =
775 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
776 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
777 break;
778 }
779 case OMPRTL__kmpc_end_reduce: {
780 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
781 // kmp_critical_name *lck);
782 llvm::Type *TypeParams[] = {
783 getIdentTyPointerTy(), CGM.Int32Ty,
784 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
785 llvm::FunctionType *FnTy =
786 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
787 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
788 break;
789 }
790 case OMPRTL__kmpc_end_reduce_nowait: {
791 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
792 // kmp_critical_name *lck);
793 llvm::Type *TypeParams[] = {
794 getIdentTyPointerTy(), CGM.Int32Ty,
795 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
796 llvm::FunctionType *FnTy =
797 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
798 RTLFn =
799 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
800 break;
801 }
Alexey Bataev1d677132015-04-22 13:57:31 +0000802 case OMPRTL__kmpc_omp_task_begin_if0: {
803 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
804 // *new_task);
805 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
806 CGM.VoidPtrTy};
807 llvm::FunctionType *FnTy =
808 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
809 RTLFn =
810 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
811 break;
812 }
813 case OMPRTL__kmpc_omp_task_complete_if0: {
814 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
815 // *new_task);
816 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
817 CGM.VoidPtrTy};
818 llvm::FunctionType *FnTy =
819 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
820 RTLFn = CGM.CreateRuntimeFunction(FnTy,
821 /*Name=*/"__kmpc_omp_task_complete_if0");
822 break;
823 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000824 case OMPRTL__kmpc_ordered: {
825 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
826 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
827 llvm::FunctionType *FnTy =
828 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
829 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
830 break;
831 }
832 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +0000833 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000834 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
835 llvm::FunctionType *FnTy =
836 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
837 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
838 break;
839 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +0000840 case OMPRTL__kmpc_omp_taskwait: {
841 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
842 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
843 llvm::FunctionType *FnTy =
844 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
845 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
846 break;
847 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +0000848 case OMPRTL__kmpc_taskgroup: {
849 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
850 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
851 llvm::FunctionType *FnTy =
852 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
853 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
854 break;
855 }
856 case OMPRTL__kmpc_end_taskgroup: {
857 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
858 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
859 llvm::FunctionType *FnTy =
860 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
861 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
862 break;
863 }
Alexey Bataev7f210c62015-06-18 13:40:03 +0000864 case OMPRTL__kmpc_push_proc_bind: {
865 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
866 // int proc_bind)
867 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
868 llvm::FunctionType *FnTy =
869 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
870 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
871 break;
872 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +0000873 case OMPRTL__kmpc_omp_task_with_deps: {
874 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
875 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
876 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
877 llvm::Type *TypeParams[] = {
878 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
879 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
880 llvm::FunctionType *FnTy =
881 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
882 RTLFn =
883 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
884 break;
885 }
886 case OMPRTL__kmpc_omp_wait_deps: {
887 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
888 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
889 // kmp_depend_info_t *noalias_dep_list);
890 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
891 CGM.Int32Ty, CGM.VoidPtrTy,
892 CGM.Int32Ty, CGM.VoidPtrTy};
893 llvm::FunctionType *FnTy =
894 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
895 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
896 break;
897 }
Alexey Bataev0f34da12015-07-02 04:17:07 +0000898 case OMPRTL__kmpc_cancellationpoint: {
899 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
900 // global_tid, kmp_int32 cncl_kind)
901 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
902 llvm::FunctionType *FnTy =
903 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
904 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
905 break;
906 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +0000907 case OMPRTL__kmpc_cancel: {
908 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
909 // kmp_int32 cncl_kind)
910 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
911 llvm::FunctionType *FnTy =
912 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
913 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
914 break;
915 }
Samuel Antaobed3c462015-10-02 16:14:20 +0000916 case OMPRTL__tgt_target: {
917 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
918 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
919 // *arg_types);
920 llvm::Type *TypeParams[] = {CGM.Int32Ty,
921 CGM.VoidPtrTy,
922 CGM.Int32Ty,
923 CGM.VoidPtrPtrTy,
924 CGM.VoidPtrPtrTy,
925 CGM.SizeTy->getPointerTo(),
926 CGM.Int32Ty->getPointerTo()};
927 llvm::FunctionType *FnTy =
928 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
929 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
930 break;
931 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000932 }
933 return RTLFn;
934}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000935
Alexey Bataevf24e7b12015-10-08 09:10:53 +0000936static llvm::Value *getTypeSize(CodeGenFunction &CGF, QualType Ty) {
937 auto &C = CGF.getContext();
938 llvm::Value *Size = nullptr;
939 auto SizeInChars = C.getTypeSizeInChars(Ty);
940 if (SizeInChars.isZero()) {
941 // getTypeSizeInChars() returns 0 for a VLA.
942 while (auto *VAT = C.getAsVariableArrayType(Ty)) {
943 llvm::Value *ArraySize;
944 std::tie(ArraySize, Ty) = CGF.getVLASize(VAT);
945 Size = Size ? CGF.Builder.CreateNUWMul(Size, ArraySize) : ArraySize;
946 }
947 SizeInChars = C.getTypeSizeInChars(Ty);
948 assert(!SizeInChars.isZero());
949 Size = CGF.Builder.CreateNUWMul(
950 Size, llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity()));
951 } else
952 Size = llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity());
953 return Size;
954}
955
Alexander Musman21212e42015-03-13 10:38:23 +0000956llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
957 bool IVSigned) {
958 assert((IVSize == 32 || IVSize == 64) &&
959 "IV size is not compatible with the omp runtime");
960 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
961 : "__kmpc_for_static_init_4u")
962 : (IVSigned ? "__kmpc_for_static_init_8"
963 : "__kmpc_for_static_init_8u");
964 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
965 auto PtrTy = llvm::PointerType::getUnqual(ITy);
966 llvm::Type *TypeParams[] = {
967 getIdentTyPointerTy(), // loc
968 CGM.Int32Ty, // tid
969 CGM.Int32Ty, // schedtype
970 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
971 PtrTy, // p_lower
972 PtrTy, // p_upper
973 PtrTy, // p_stride
974 ITy, // incr
975 ITy // chunk
976 };
977 llvm::FunctionType *FnTy =
978 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
979 return CGM.CreateRuntimeFunction(FnTy, Name);
980}
981
Alexander Musman92bdaab2015-03-12 13:37:50 +0000982llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
983 bool IVSigned) {
984 assert((IVSize == 32 || IVSize == 64) &&
985 "IV size is not compatible with the omp runtime");
986 auto Name =
987 IVSize == 32
988 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
989 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
990 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
991 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
992 CGM.Int32Ty, // tid
993 CGM.Int32Ty, // schedtype
994 ITy, // lower
995 ITy, // upper
996 ITy, // stride
997 ITy // chunk
998 };
999 llvm::FunctionType *FnTy =
1000 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1001 return CGM.CreateRuntimeFunction(FnTy, Name);
1002}
1003
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001004llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
1005 bool IVSigned) {
1006 assert((IVSize == 32 || IVSize == 64) &&
1007 "IV size is not compatible with the omp runtime");
1008 auto Name =
1009 IVSize == 32
1010 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1011 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1012 llvm::Type *TypeParams[] = {
1013 getIdentTyPointerTy(), // loc
1014 CGM.Int32Ty, // tid
1015 };
1016 llvm::FunctionType *FnTy =
1017 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1018 return CGM.CreateRuntimeFunction(FnTy, Name);
1019}
1020
Alexander Musman92bdaab2015-03-12 13:37:50 +00001021llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
1022 bool IVSigned) {
1023 assert((IVSize == 32 || IVSize == 64) &&
1024 "IV size is not compatible with the omp runtime");
1025 auto Name =
1026 IVSize == 32
1027 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1028 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1029 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1030 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1031 llvm::Type *TypeParams[] = {
1032 getIdentTyPointerTy(), // loc
1033 CGM.Int32Ty, // tid
1034 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1035 PtrTy, // p_lower
1036 PtrTy, // p_upper
1037 PtrTy // p_stride
1038 };
1039 llvm::FunctionType *FnTy =
1040 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1041 return CGM.CreateRuntimeFunction(FnTy, Name);
1042}
1043
Alexey Bataev97720002014-11-11 04:05:39 +00001044llvm::Constant *
1045CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001046 assert(!CGM.getLangOpts().OpenMPUseTLS ||
1047 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00001048 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001049 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001050 Twine(CGM.getMangledName(VD)) + ".cache.");
1051}
1052
John McCall7f416cc2015-09-08 08:05:57 +00001053Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1054 const VarDecl *VD,
1055 Address VDAddr,
1056 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001057 if (CGM.getLangOpts().OpenMPUseTLS &&
1058 CGM.getContext().getTargetInfo().isTLSSupported())
1059 return VDAddr;
1060
John McCall7f416cc2015-09-08 08:05:57 +00001061 auto VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001062 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001063 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1064 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001065 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1066 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00001067 return Address(CGF.EmitRuntimeCall(
1068 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
1069 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00001070}
1071
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001072void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00001073 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00001074 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1075 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1076 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001077 auto OMPLoc = emitUpdateLocation(CGF, Loc);
1078 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00001079 OMPLoc);
1080 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1081 // to register constructor/destructor for variable.
1082 llvm::Value *Args[] = {OMPLoc,
John McCall7f416cc2015-09-08 08:05:57 +00001083 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1084 CGM.VoidPtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001085 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001086 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001087 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001088}
1089
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001090llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00001091 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00001092 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001093 if (CGM.getLangOpts().OpenMPUseTLS &&
1094 CGM.getContext().getTargetInfo().isTLSSupported())
1095 return nullptr;
1096
Alexey Bataev97720002014-11-11 04:05:39 +00001097 VD = VD->getDefinition(CGM.getContext());
1098 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
1099 ThreadPrivateWithDefinition.insert(VD);
1100 QualType ASTTy = VD->getType();
1101
1102 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1103 auto Init = VD->getAnyInitializer();
1104 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1105 // Generate function that re-emits the declaration's initializer into the
1106 // threadprivate copy of the variable VD
1107 CodeGenFunction CtorCGF(CGM);
1108 FunctionArgList Args;
1109 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1110 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1111 Args.push_back(&Dst);
1112
1113 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1114 CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(),
1115 /*isVariadic=*/false);
1116 auto FTy = CGM.getTypes().GetFunctionType(FI);
1117 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001118 FTy, ".__kmpc_global_ctor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001119 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1120 Args, SourceLocation());
1121 auto ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001122 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001123 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00001124 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1125 Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
1126 CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00001127 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1128 /*IsInitializer=*/true);
1129 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001130 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001131 CGM.getContext().VoidPtrTy, Dst.getLocation());
1132 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1133 CtorCGF.FinishFunction();
1134 Ctor = Fn;
1135 }
1136 if (VD->getType().isDestructedType() != QualType::DK_none) {
1137 // Generate function that emits destructor call for the threadprivate copy
1138 // of the variable VD
1139 CodeGenFunction DtorCGF(CGM);
1140 FunctionArgList Args;
1141 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1142 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1143 Args.push_back(&Dst);
1144
1145 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1146 CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(),
1147 /*isVariadic=*/false);
1148 auto FTy = CGM.getTypes().GetFunctionType(FI);
1149 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001150 FTy, ".__kmpc_global_dtor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001151 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1152 SourceLocation());
1153 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1154 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00001155 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1156 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001157 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1158 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1159 DtorCGF.FinishFunction();
1160 Dtor = Fn;
1161 }
1162 // Do not emit init function if it is not required.
1163 if (!Ctor && !Dtor)
1164 return nullptr;
1165
1166 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1167 auto CopyCtorTy =
1168 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1169 /*isVarArg=*/false)->getPointerTo();
1170 // Copying constructor for the threadprivate variable.
1171 // Must be NULL - reserved by runtime, but currently it requires that this
1172 // parameter is always NULL. Otherwise it fires assertion.
1173 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1174 if (Ctor == nullptr) {
1175 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1176 /*isVarArg=*/false)->getPointerTo();
1177 Ctor = llvm::Constant::getNullValue(CtorTy);
1178 }
1179 if (Dtor == nullptr) {
1180 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1181 /*isVarArg=*/false)->getPointerTo();
1182 Dtor = llvm::Constant::getNullValue(DtorTy);
1183 }
1184 if (!CGF) {
1185 auto InitFunctionTy =
1186 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1187 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001188 InitFunctionTy, ".__omp_threadprivate_init_.",
1189 CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00001190 CodeGenFunction InitCGF(CGM);
1191 FunctionArgList ArgList;
1192 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1193 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1194 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001195 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001196 InitCGF.FinishFunction();
1197 return InitFunction;
1198 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001199 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001200 }
1201 return nullptr;
1202}
1203
Alexey Bataev1d677132015-04-22 13:57:31 +00001204/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1205/// function. Here is the logic:
1206/// if (Cond) {
1207/// ThenGen();
1208/// } else {
1209/// ElseGen();
1210/// }
1211static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1212 const RegionCodeGenTy &ThenGen,
1213 const RegionCodeGenTy &ElseGen) {
1214 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1215
1216 // If the condition constant folds and can be elided, try to avoid emitting
1217 // the condition and the dead arm of the if/else.
1218 bool CondConstant;
1219 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
1220 CodeGenFunction::RunCleanupsScope Scope(CGF);
1221 if (CondConstant) {
1222 ThenGen(CGF);
1223 } else {
1224 ElseGen(CGF);
1225 }
1226 return;
1227 }
1228
1229 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1230 // emit the conditional branch.
1231 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1232 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1233 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1234 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1235
1236 // Emit the 'then' code.
1237 CGF.EmitBlock(ThenBlock);
1238 {
1239 CodeGenFunction::RunCleanupsScope ThenScope(CGF);
1240 ThenGen(CGF);
1241 }
1242 CGF.EmitBranch(ContBlock);
1243 // Emit the 'else' code if present.
1244 {
1245 // There is no need to emit line number for unconditional branch.
1246 auto NL = ApplyDebugLocation::CreateEmpty(CGF);
1247 CGF.EmitBlock(ElseBlock);
1248 }
1249 {
1250 CodeGenFunction::RunCleanupsScope ThenScope(CGF);
1251 ElseGen(CGF);
1252 }
1253 {
1254 // There is no need to emit line number for unconditional branch.
1255 auto NL = ApplyDebugLocation::CreateEmpty(CGF);
1256 CGF.EmitBranch(ContBlock);
1257 }
1258 // Emit the continuation block for code after the if.
1259 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001260}
1261
Alexey Bataev1d677132015-04-22 13:57:31 +00001262void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1263 llvm::Value *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001264 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00001265 const Expr *IfCond) {
1266 auto *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001267 auto &&ThenGen = [this, OutlinedFn, CapturedVars,
1268 RTLoc](CodeGenFunction &CGF) {
1269 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
1270 llvm::Value *Args[] = {
1271 RTLoc,
1272 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
1273 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
1274 llvm::SmallVector<llvm::Value *, 16> RealArgs;
1275 RealArgs.append(std::begin(Args), std::end(Args));
1276 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1277
1278 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
1279 CGF.EmitRuntimeCall(RTLFn, RealArgs);
1280 };
1281 auto &&ElseGen = [this, OutlinedFn, CapturedVars, RTLoc,
1282 Loc](CodeGenFunction &CGF) {
Alexey Bataev1d677132015-04-22 13:57:31 +00001283 auto ThreadID = getThreadID(CGF, Loc);
1284 // Build calls:
1285 // __kmpc_serialized_parallel(&Loc, GTid);
1286 llvm::Value *Args[] = {RTLoc, ThreadID};
1287 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel),
1288 Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001289
Alexey Bataev1d677132015-04-22 13:57:31 +00001290 // OutlinedFn(&GTid, &zero, CapturedStruct);
1291 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00001292 Address ZeroAddr =
1293 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
1294 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00001295 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00001296 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
1297 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
1298 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1299 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev1d677132015-04-22 13:57:31 +00001300 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001301
Alexey Bataev1d677132015-04-22 13:57:31 +00001302 // __kmpc_end_serialized_parallel(&Loc, GTid);
1303 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID};
1304 CGF.EmitRuntimeCall(
1305 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs);
1306 };
1307 if (IfCond) {
1308 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
1309 } else {
1310 CodeGenFunction::RunCleanupsScope Scope(CGF);
1311 ThenGen(CGF);
1312 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001313}
1314
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001315// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001316// thread-ID variable (it is passed in a first argument of the outlined function
1317// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1318// regular serial code region, get thread ID by calling kmp_int32
1319// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1320// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00001321Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
1322 SourceLocation Loc) {
Alexey Bataevd74d0602014-10-13 06:02:40 +00001323 if (auto OMPRegionInfo =
1324 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001325 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001326 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001327
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001328 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001329 auto Int32Ty =
1330 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1331 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1332 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00001333 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00001334
1335 return ThreadIDTemp;
1336}
1337
Alexey Bataev97720002014-11-11 04:05:39 +00001338llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001339CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001340 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001341 SmallString<256> Buffer;
1342 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001343 Out << Name;
1344 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001345 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1346 if (Elem.second) {
1347 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001348 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001349 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001350 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001351
David Blaikie13156b62014-11-19 03:06:06 +00001352 return Elem.second = new llvm::GlobalVariable(
1353 CGM.getModule(), Ty, /*IsConstant*/ false,
1354 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1355 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001356}
1357
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001358llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001359 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001360 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001361}
1362
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001363namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00001364template <size_t N> class CallEndCleanup final : public EHScopeStack::Cleanup {
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001365 llvm::Value *Callee;
Alexey Bataeva744ff52015-05-05 09:24:37 +00001366 llvm::Value *Args[N];
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001367
1368public:
Alexey Bataeva744ff52015-05-05 09:24:37 +00001369 CallEndCleanup(llvm::Value *Callee, ArrayRef<llvm::Value *> CleanupArgs)
1370 : Callee(Callee) {
1371 assert(CleanupArgs.size() == N);
1372 std::copy(CleanupArgs.begin(), CleanupArgs.end(), std::begin(Args));
1373 }
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001374 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
1375 CGF.EmitRuntimeCall(Callee, Args);
1376 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001377};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001378} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001379
1380void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1381 StringRef CriticalName,
1382 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00001383 SourceLocation Loc, const Expr *Hint) {
1384 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001385 // CriticalOpGen();
1386 // __kmpc_end_critical(ident_t *, gtid, Lock);
1387 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataevfc57d162015-12-15 10:55:09 +00001388 CodeGenFunction::RunCleanupsScope Scope(CGF);
1389 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1390 getCriticalRegionLock(CriticalName)};
1391 if (Hint) {
1392 llvm::SmallVector<llvm::Value *, 8> ArgsWithHint(std::begin(Args),
1393 std::end(Args));
1394 auto *HintVal = CGF.EmitScalarExpr(Hint);
1395 ArgsWithHint.push_back(
1396 CGF.Builder.CreateIntCast(HintVal, CGM.IntPtrTy, /*isSigned=*/false));
1397 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical_with_hint),
1398 ArgsWithHint);
1399 } else
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001400 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
Alexey Bataevfc57d162015-12-15 10:55:09 +00001401 // Build a call to __kmpc_end_critical
1402 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
1403 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
1404 llvm::makeArrayRef(Args));
1405 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001406}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001407
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001408static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001409 OpenMPDirectiveKind Kind, SourceLocation Loc,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001410 const RegionCodeGenTy &BodyOpGen) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001411 llvm::Value *CallBool = CGF.EmitScalarConversion(
1412 IfCond,
1413 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001414 CGF.getContext().BoolTy, Loc);
Alexey Bataev8d690652014-12-04 07:23:53 +00001415
1416 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1417 auto *ContBlock = CGF.createBasicBlock("omp_if.end");
1418 // Generate the branch (If-stmt)
1419 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1420 CGF.EmitBlock(ThenBlock);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001421 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen);
Alexey Bataev8d690652014-12-04 07:23:53 +00001422 // Emit the rest of bblocks/branches
1423 CGF.EmitBranch(ContBlock);
1424 CGF.EmitBlock(ContBlock, true);
1425}
1426
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001427void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001428 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001429 SourceLocation Loc) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001430 // if(__kmpc_master(ident_t *, gtid)) {
1431 // MasterOpGen();
1432 // __kmpc_end_master(ident_t *, gtid);
1433 // }
1434 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001435 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001436 auto *IsMaster =
1437 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
Alexey Bataeva744ff52015-05-05 09:24:37 +00001438 typedef CallEndCleanup<std::extent<decltype(Args)>::value>
1439 MasterCallEndCleanup;
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001440 emitIfStmt(
1441 CGF, IsMaster, OMPD_master, Loc, [&](CodeGenFunction &CGF) -> void {
1442 CodeGenFunction::RunCleanupsScope Scope(CGF);
1443 CGF.EHStack.pushCleanup<MasterCallEndCleanup>(
1444 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
1445 llvm::makeArrayRef(Args));
1446 MasterOpGen(CGF);
1447 });
Alexey Bataev8d690652014-12-04 07:23:53 +00001448}
1449
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001450void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
1451 SourceLocation Loc) {
Alexey Bataev9f797f32015-02-05 05:57:51 +00001452 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
1453 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001454 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00001455 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001456 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev9f797f32015-02-05 05:57:51 +00001457}
1458
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001459void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
1460 const RegionCodeGenTy &TaskgroupOpGen,
1461 SourceLocation Loc) {
1462 // __kmpc_taskgroup(ident_t *, gtid);
1463 // TaskgroupOpGen();
1464 // __kmpc_end_taskgroup(ident_t *, gtid);
1465 // Prepare arguments and build a call to __kmpc_taskgroup
1466 {
1467 CodeGenFunction::RunCleanupsScope Scope(CGF);
1468 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1469 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args);
1470 // Build a call to __kmpc_end_taskgroup
1471 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
1472 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
1473 llvm::makeArrayRef(Args));
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001474 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001475 }
1476}
1477
John McCall7f416cc2015-09-08 08:05:57 +00001478/// Given an array of pointers to variables, project the address of a
1479/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001480static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
1481 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00001482 // Pull out the pointer to the variable.
1483 Address PtrAddr =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001484 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00001485 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
1486
1487 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001488 Addr = CGF.Builder.CreateElementBitCast(
1489 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00001490 return Addr;
1491}
1492
Alexey Bataeva63048e2015-03-23 06:18:07 +00001493static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00001494 CodeGenModule &CGM, llvm::Type *ArgsType,
1495 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
1496 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00001497 auto &C = CGM.getContext();
1498 // void copy_func(void *LHSArg, void *RHSArg);
1499 FunctionArgList Args;
1500 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1501 C.VoidPtrTy);
1502 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1503 C.VoidPtrTy);
1504 Args.push_back(&LHSArg);
1505 Args.push_back(&RHSArg);
1506 FunctionType::ExtInfo EI;
1507 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1508 C.VoidTy, Args, EI, /*isVariadic=*/false);
1509 auto *Fn = llvm::Function::Create(
1510 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
1511 ".omp.copyprivate.copy_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00001512 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001513 CodeGenFunction CGF(CGM);
1514 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00001515 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001516 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00001517 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1518 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
1519 ArgsType), CGF.getPointerAlign());
1520 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1521 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
1522 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00001523 // *(Type0*)Dst[0] = *(Type0*)Src[0];
1524 // *(Type1*)Dst[1] = *(Type1*)Src[1];
1525 // ...
1526 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00001527 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00001528 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
1529 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
1530
1531 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
1532 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
1533
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001534 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
1535 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00001536 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001537 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001538 CGF.FinishFunction();
1539 return Fn;
1540}
1541
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001542void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001543 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001544 SourceLocation Loc,
1545 ArrayRef<const Expr *> CopyprivateVars,
1546 ArrayRef<const Expr *> SrcExprs,
1547 ArrayRef<const Expr *> DstExprs,
1548 ArrayRef<const Expr *> AssignmentOps) {
1549 assert(CopyprivateVars.size() == SrcExprs.size() &&
1550 CopyprivateVars.size() == DstExprs.size() &&
1551 CopyprivateVars.size() == AssignmentOps.size());
1552 auto &C = CGM.getContext();
1553 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001554 // if(__kmpc_single(ident_t *, gtid)) {
1555 // SingleOpGen();
1556 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001557 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001558 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001559 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1560 // <copy_func>, did_it);
1561
John McCall7f416cc2015-09-08 08:05:57 +00001562 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00001563 if (!CopyprivateVars.empty()) {
1564 // int32 did_it = 0;
1565 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1566 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00001567 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001568 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001569 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001570 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001571 auto *IsSingle =
1572 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
Alexey Bataeva744ff52015-05-05 09:24:37 +00001573 typedef CallEndCleanup<std::extent<decltype(Args)>::value>
1574 SingleCallEndCleanup;
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001575 emitIfStmt(
1576 CGF, IsSingle, OMPD_single, Loc, [&](CodeGenFunction &CGF) -> void {
1577 CodeGenFunction::RunCleanupsScope Scope(CGF);
1578 CGF.EHStack.pushCleanup<SingleCallEndCleanup>(
1579 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
1580 llvm::makeArrayRef(Args));
1581 SingleOpGen(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00001582 if (DidIt.isValid()) {
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001583 // did_it = 1;
John McCall7f416cc2015-09-08 08:05:57 +00001584 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001585 }
1586 });
Alexey Bataeva63048e2015-03-23 06:18:07 +00001587 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1588 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00001589 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00001590 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
1591 auto CopyprivateArrayTy =
1592 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
1593 /*IndexTypeQuals=*/0);
1594 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00001595 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00001596 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
1597 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00001598 Address Elem = CGF.Builder.CreateConstArrayGEP(
1599 CopyprivateList, I, CGF.getPointerSize());
1600 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00001601 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00001602 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
1603 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001604 }
1605 // Build function that copies private values from single region to all other
1606 // threads in the corresponding parallel region.
1607 auto *CpyFn = emitCopyprivateCopyFunction(
1608 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00001609 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001610 auto *BufSize = getTypeSize(CGF, CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00001611 Address CL =
1612 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
1613 CGF.VoidPtrTy);
1614 auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001615 llvm::Value *Args[] = {
1616 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
1617 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00001618 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00001619 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00001620 CpyFn, // void (*) (void *, void *) <copy_func>
1621 DidItVal // i32 did_it
1622 };
1623 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
1624 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001625}
1626
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001627void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
1628 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00001629 SourceLocation Loc, bool IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001630 // __kmpc_ordered(ident_t *, gtid);
1631 // OrderedOpGen();
1632 // __kmpc_end_ordered(ident_t *, gtid);
1633 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00001634 CodeGenFunction::RunCleanupsScope Scope(CGF);
1635 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001636 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1637 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_ordered), Args);
1638 // Build a call to __kmpc_end_ordered
Alexey Bataeva744ff52015-05-05 09:24:37 +00001639 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001640 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered),
1641 llvm::makeArrayRef(Args));
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001642 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00001643 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001644}
1645
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001646void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev25e5b442015-09-15 12:52:43 +00001647 OpenMPDirectiveKind Kind, bool EmitChecks,
1648 bool ForceSimpleCall) {
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001649 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001650 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataevf2685682015-03-30 04:30:22 +00001651 OpenMPLocationFlags Flags = OMP_IDENT_KMPC;
1652 if (Kind == OMPD_for) {
1653 Flags =
1654 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_FOR);
1655 } else if (Kind == OMPD_sections) {
1656 Flags = static_cast<OpenMPLocationFlags>(Flags |
1657 OMP_IDENT_BARRIER_IMPL_SECTIONS);
1658 } else if (Kind == OMPD_single) {
1659 Flags =
1660 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_SINGLE);
1661 } else if (Kind == OMPD_barrier) {
1662 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_EXPL);
1663 } else {
1664 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL);
1665 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001666 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
1667 // thread_id);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001668 auto *OMPRegionInfo =
1669 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
1670 // Do not emit barrier call in the single directive emitted in some rare cases
1671 // for sections directives.
1672 if (OMPRegionInfo && OMPRegionInfo->getDirectiveKind() == OMPD_single)
1673 return;
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001674 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
1675 getThreadID(CGF, Loc)};
Alexey Bataev25e5b442015-09-15 12:52:43 +00001676 if (OMPRegionInfo) {
1677 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001678 auto *Result = CGF.EmitRuntimeCall(
1679 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001680 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001681 // if (__kmpc_cancel_barrier()) {
1682 // exit from construct;
1683 // }
1684 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
1685 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
1686 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
1687 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
1688 CGF.EmitBlock(ExitBB);
1689 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00001690 auto CancelDestination =
1691 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001692 CGF.EmitBranchThroughCleanup(CancelDestination);
1693 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
1694 }
1695 return;
1696 }
1697 }
1698 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001699}
1700
Alexander Musmanc6388682014-12-15 07:07:06 +00001701/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
1702/// the enum sched_type in kmp.h).
1703enum OpenMPSchedType {
1704 /// \brief Lower bound for default (unordered) versions.
1705 OMP_sch_lower = 32,
1706 OMP_sch_static_chunked = 33,
1707 OMP_sch_static = 34,
1708 OMP_sch_dynamic_chunked = 35,
1709 OMP_sch_guided_chunked = 36,
1710 OMP_sch_runtime = 37,
1711 OMP_sch_auto = 38,
1712 /// \brief Lower bound for 'ordered' versions.
1713 OMP_ord_lower = 64,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001714 OMP_ord_static_chunked = 65,
1715 OMP_ord_static = 66,
1716 OMP_ord_dynamic_chunked = 67,
1717 OMP_ord_guided_chunked = 68,
1718 OMP_ord_runtime = 69,
1719 OMP_ord_auto = 70,
1720 OMP_sch_default = OMP_sch_static,
Alexander Musmanc6388682014-12-15 07:07:06 +00001721};
1722
1723/// \brief Map the OpenMP loop schedule to the runtime enumeration.
1724static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001725 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001726 switch (ScheduleKind) {
1727 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001728 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
1729 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00001730 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001731 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00001732 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001733 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00001734 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001735 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
1736 case OMPC_SCHEDULE_auto:
1737 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00001738 case OMPC_SCHEDULE_unknown:
1739 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001740 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00001741 }
1742 llvm_unreachable("Unexpected runtime schedule");
1743}
1744
1745bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
1746 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001747 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00001748 return Schedule == OMP_sch_static;
1749}
1750
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001751bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001752 auto Schedule =
1753 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001754 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
1755 return Schedule != OMP_sch_static;
1756}
1757
John McCall7f416cc2015-09-08 08:05:57 +00001758void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
1759 SourceLocation Loc,
1760 OpenMPScheduleClauseKind ScheduleKind,
1761 unsigned IVSize, bool IVSigned,
1762 bool Ordered, llvm::Value *UB,
1763 llvm::Value *Chunk) {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001764 OpenMPSchedType Schedule =
1765 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00001766 assert(Ordered ||
1767 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
1768 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
1769 // Call __kmpc_dispatch_init(
1770 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
1771 // kmp_int[32|64] lower, kmp_int[32|64] upper,
1772 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00001773
John McCall7f416cc2015-09-08 08:05:57 +00001774 // If the Chunk was not specified in the clause - use default value 1.
1775 if (Chunk == nullptr)
1776 Chunk = CGF.Builder.getIntN(IVSize, 1);
1777 llvm::Value *Args[] = {
1778 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1779 getThreadID(CGF, Loc),
1780 CGF.Builder.getInt32(Schedule), // Schedule type
1781 CGF.Builder.getIntN(IVSize, 0), // Lower
1782 UB, // Upper
1783 CGF.Builder.getIntN(IVSize, 1), // Stride
1784 Chunk // Chunk
1785 };
1786 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
1787}
1788
1789void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
1790 SourceLocation Loc,
1791 OpenMPScheduleClauseKind ScheduleKind,
1792 unsigned IVSize, bool IVSigned,
1793 bool Ordered, Address IL, Address LB,
1794 Address UB, Address ST,
1795 llvm::Value *Chunk) {
1796 OpenMPSchedType Schedule =
1797 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
1798 assert(!Ordered);
1799 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
1800 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked);
1801
1802 // Call __kmpc_for_static_init(
1803 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
1804 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
1805 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
1806 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
1807 if (Chunk == nullptr) {
1808 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static) &&
1809 "expected static non-chunked schedule");
Alexander Musman92bdaab2015-03-12 13:37:50 +00001810 // If the Chunk was not specified in the clause - use default value 1.
Alexander Musman92bdaab2015-03-12 13:37:50 +00001811 Chunk = CGF.Builder.getIntN(IVSize, 1);
Alexander Musman92bdaab2015-03-12 13:37:50 +00001812 } else {
John McCall7f416cc2015-09-08 08:05:57 +00001813 assert((Schedule == OMP_sch_static_chunked ||
1814 Schedule == OMP_ord_static_chunked) &&
1815 "expected static chunked schedule");
Alexander Musman92bdaab2015-03-12 13:37:50 +00001816 }
John McCall7f416cc2015-09-08 08:05:57 +00001817 llvm::Value *Args[] = {
1818 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1819 getThreadID(CGF, Loc),
1820 CGF.Builder.getInt32(Schedule), // Schedule type
1821 IL.getPointer(), // &isLastIter
1822 LB.getPointer(), // &LB
1823 UB.getPointer(), // &UB
1824 ST.getPointer(), // &Stride
1825 CGF.Builder.getIntN(IVSize, 1), // Incr
1826 Chunk // Chunk
1827 };
1828 CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00001829}
1830
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001831void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
1832 SourceLocation Loc) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001833 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001834 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1835 getThreadID(CGF, Loc)};
1836 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
1837 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00001838}
1839
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001840void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
1841 SourceLocation Loc,
1842 unsigned IVSize,
1843 bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001844 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
1845 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1846 getThreadID(CGF, Loc)};
1847 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
1848}
1849
Alexander Musman92bdaab2015-03-12 13:37:50 +00001850llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
1851 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00001852 bool IVSigned, Address IL,
1853 Address LB, Address UB,
1854 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00001855 // Call __kmpc_dispatch_next(
1856 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
1857 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
1858 // kmp_int[32|64] *p_stride);
1859 llvm::Value *Args[] = {
1860 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001861 IL.getPointer(), // &isLastIter
1862 LB.getPointer(), // &Lower
1863 UB.getPointer(), // &Upper
1864 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00001865 };
1866 llvm::Value *Call =
1867 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
1868 return CGF.EmitScalarConversion(
1869 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001870 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00001871}
1872
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001873void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
1874 llvm::Value *NumThreads,
1875 SourceLocation Loc) {
Alexey Bataevb2059782014-10-13 08:23:51 +00001876 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
1877 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001878 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00001879 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001880 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
1881 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00001882}
1883
Alexey Bataev7f210c62015-06-18 13:40:03 +00001884void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
1885 OpenMPProcBindClauseKind ProcBind,
1886 SourceLocation Loc) {
1887 // Constants for proc bind value accepted by the runtime.
1888 enum ProcBindTy {
1889 ProcBindFalse = 0,
1890 ProcBindTrue,
1891 ProcBindMaster,
1892 ProcBindClose,
1893 ProcBindSpread,
1894 ProcBindIntel,
1895 ProcBindDefault
1896 } RuntimeProcBind;
1897 switch (ProcBind) {
1898 case OMPC_PROC_BIND_master:
1899 RuntimeProcBind = ProcBindMaster;
1900 break;
1901 case OMPC_PROC_BIND_close:
1902 RuntimeProcBind = ProcBindClose;
1903 break;
1904 case OMPC_PROC_BIND_spread:
1905 RuntimeProcBind = ProcBindSpread;
1906 break;
1907 case OMPC_PROC_BIND_unknown:
1908 llvm_unreachable("Unsupported proc_bind value.");
1909 }
1910 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
1911 llvm::Value *Args[] = {
1912 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1913 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
1914 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
1915}
1916
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001917void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
1918 SourceLocation Loc) {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001919 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001920 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
1921 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001922}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001923
Alexey Bataev62b63b12015-03-10 07:28:44 +00001924namespace {
1925/// \brief Indexes of fields for type kmp_task_t.
1926enum KmpTaskTFields {
1927 /// \brief List of shared variables.
1928 KmpTaskTShareds,
1929 /// \brief Task routine.
1930 KmpTaskTRoutine,
1931 /// \brief Partition id for the untied tasks.
1932 KmpTaskTPartId,
1933 /// \brief Function with call of destructors for private variables.
1934 KmpTaskTDestructors,
1935};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001936} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00001937
1938void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
1939 if (!KmpRoutineEntryPtrTy) {
1940 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
1941 auto &C = CGM.getContext();
1942 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
1943 FunctionProtoType::ExtProtoInfo EPI;
1944 KmpRoutineEntryPtrQTy = C.getPointerType(
1945 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
1946 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
1947 }
1948}
1949
Alexey Bataevc71a4092015-09-11 10:29:41 +00001950static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1951 QualType FieldTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001952 auto *Field = FieldDecl::Create(
1953 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1954 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1955 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1956 Field->setAccess(AS_public);
1957 DC->addDecl(Field);
Alexey Bataevc71a4092015-09-11 10:29:41 +00001958 return Field;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001959}
1960
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001961namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00001962struct PrivateHelpersTy {
1963 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
1964 const VarDecl *PrivateElemInit)
1965 : Original(Original), PrivateCopy(PrivateCopy),
1966 PrivateElemInit(PrivateElemInit) {}
1967 const VarDecl *Original;
1968 const VarDecl *PrivateCopy;
1969 const VarDecl *PrivateElemInit;
1970};
1971typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00001972} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001973
Alexey Bataev9e034042015-05-05 04:05:12 +00001974static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00001975createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001976 if (!Privates.empty()) {
1977 auto &C = CGM.getContext();
1978 // Build struct .kmp_privates_t. {
1979 // /* private vars */
1980 // };
1981 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
1982 RD->startDefinition();
1983 for (auto &&Pair : Privates) {
Alexey Bataevc71a4092015-09-11 10:29:41 +00001984 auto *VD = Pair.second.Original;
1985 auto Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001986 Type = Type.getNonReferenceType();
Alexey Bataevc71a4092015-09-11 10:29:41 +00001987 auto *FD = addFieldToRecordDecl(C, RD, Type);
1988 if (VD->hasAttrs()) {
1989 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
1990 E(VD->getAttrs().end());
1991 I != E; ++I)
1992 FD->addAttr(*I);
1993 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001994 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001995 RD->completeDefinition();
1996 return RD;
1997 }
1998 return nullptr;
1999}
2000
Alexey Bataev9e034042015-05-05 04:05:12 +00002001static RecordDecl *
2002createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002003 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002004 auto &C = CGM.getContext();
2005 // Build struct kmp_task_t {
2006 // void * shareds;
2007 // kmp_routine_entry_t routine;
2008 // kmp_int32 part_id;
2009 // kmp_routine_entry_t destructors;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002010 // };
2011 auto *RD = C.buildImplicitRecord("kmp_task_t");
2012 RD->startDefinition();
2013 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2014 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
2015 addFieldToRecordDecl(C, RD, KmpInt32Ty);
2016 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002017 RD->completeDefinition();
2018 return RD;
2019}
2020
2021static RecordDecl *
2022createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00002023 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002024 auto &C = CGM.getContext();
2025 // Build struct kmp_task_t_with_privates {
2026 // kmp_task_t task_data;
2027 // .kmp_privates_t. privates;
2028 // };
2029 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
2030 RD->startDefinition();
2031 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002032 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
2033 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
2034 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002035 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002036 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002037}
2038
2039/// \brief Emit a proxy function which accepts kmp_task_t as the second
2040/// argument.
2041/// \code
2042/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002043/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map,
2044/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002045/// return 0;
2046/// }
2047/// \endcode
2048static llvm::Value *
2049emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002050 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
2051 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002052 QualType SharedsPtrTy, llvm::Value *TaskFunction,
2053 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002054 auto &C = CGM.getContext();
2055 FunctionArgList Args;
2056 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
2057 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002058 /*Id=*/nullptr,
2059 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002060 Args.push_back(&GtidArg);
2061 Args.push_back(&TaskTypeArg);
2062 FunctionType::ExtInfo Info;
2063 auto &TaskEntryFnInfo =
2064 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
2065 /*isVariadic=*/false);
2066 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
2067 auto *TaskEntry =
2068 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
2069 ".omp_task_entry.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002070 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002071 CodeGenFunction CGF(CGM);
2072 CGF.disableDebugInfo();
2073 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
2074
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002075 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
2076 // tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002077 auto *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002078 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev2377fe92015-09-10 08:12:02 +00002079 LValue TDBase = emitLoadOfPointerLValue(
2080 CGF, CGF.GetAddrOfLocalVar(&TaskTypeArg), KmpTaskTWithPrivatesPtrQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002081 auto *KmpTaskTWithPrivatesQTyRD =
2082 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002083 LValue Base =
2084 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002085 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
2086 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
2087 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
2088 auto *PartidParam = CGF.EmitLoadOfLValue(PartIdLVal, Loc).getScalarVal();
2089
2090 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
2091 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002092 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002093 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002094 CGF.ConvertTypeForMem(SharedsPtrTy));
2095
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002096 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
2097 llvm::Value *PrivatesParam;
2098 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
2099 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
2100 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002101 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002102 } else {
2103 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2104 }
2105
2106 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam,
2107 TaskPrivatesMap, SharedsParam};
Alexey Bataev62b63b12015-03-10 07:28:44 +00002108 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
2109 CGF.EmitStoreThroughLValue(
2110 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
John McCall7f416cc2015-09-08 08:05:57 +00002111 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00002112 CGF.FinishFunction();
2113 return TaskEntry;
2114}
2115
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002116static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
2117 SourceLocation Loc,
2118 QualType KmpInt32Ty,
2119 QualType KmpTaskTWithPrivatesPtrQTy,
2120 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002121 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002122 FunctionArgList Args;
2123 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
2124 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002125 /*Id=*/nullptr,
2126 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002127 Args.push_back(&GtidArg);
2128 Args.push_back(&TaskTypeArg);
2129 FunctionType::ExtInfo Info;
2130 auto &DestructorFnInfo =
2131 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
2132 /*isVariadic=*/false);
2133 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
2134 auto *DestructorFn =
2135 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
2136 ".omp_task_destructor.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002137 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
2138 DestructorFnInfo);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002139 CodeGenFunction CGF(CGM);
2140 CGF.disableDebugInfo();
2141 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
2142 Args);
2143
Alexey Bataev2377fe92015-09-10 08:12:02 +00002144 LValue Base = emitLoadOfPointerLValue(
2145 CGF, CGF.GetAddrOfLocalVar(&TaskTypeArg), KmpTaskTWithPrivatesPtrQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002146 auto *KmpTaskTWithPrivatesQTyRD =
2147 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
2148 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002149 Base = CGF.EmitLValueForField(Base, *FI);
2150 for (auto *Field :
2151 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
2152 if (auto DtorKind = Field->getType().isDestructedType()) {
2153 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
2154 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
2155 }
2156 }
2157 CGF.FinishFunction();
2158 return DestructorFn;
2159}
2160
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002161/// \brief Emit a privates mapping function for correct handling of private and
2162/// firstprivate variables.
2163/// \code
2164/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
2165/// **noalias priv1,..., <tyn> **noalias privn) {
2166/// *priv1 = &.privates.priv1;
2167/// ...;
2168/// *privn = &.privates.privn;
2169/// }
2170/// \endcode
2171static llvm::Value *
2172emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00002173 ArrayRef<const Expr *> PrivateVars,
2174 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002175 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00002176 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002177 auto &C = CGM.getContext();
2178 FunctionArgList Args;
2179 ImplicitParamDecl TaskPrivatesArg(
2180 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
2181 C.getPointerType(PrivatesQTy).withConst().withRestrict());
2182 Args.push_back(&TaskPrivatesArg);
2183 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
2184 unsigned Counter = 1;
2185 for (auto *E: PrivateVars) {
2186 Args.push_back(ImplicitParamDecl::Create(
2187 C, /*DC=*/nullptr, Loc,
2188 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
2189 .withConst()
2190 .withRestrict()));
2191 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2192 PrivateVarsPos[VD] = Counter;
2193 ++Counter;
2194 }
2195 for (auto *E : FirstprivateVars) {
2196 Args.push_back(ImplicitParamDecl::Create(
2197 C, /*DC=*/nullptr, Loc,
2198 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
2199 .withConst()
2200 .withRestrict()));
2201 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2202 PrivateVarsPos[VD] = Counter;
2203 ++Counter;
2204 }
2205 FunctionType::ExtInfo Info;
2206 auto &TaskPrivatesMapFnInfo =
2207 CGM.getTypes().arrangeFreeFunctionDeclaration(C.VoidTy, Args, Info,
2208 /*isVariadic=*/false);
2209 auto *TaskPrivatesMapTy =
2210 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
2211 auto *TaskPrivatesMap = llvm::Function::Create(
2212 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
2213 ".omp_task_privates_map.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002214 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
2215 TaskPrivatesMapFnInfo);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00002216 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002217 CodeGenFunction CGF(CGM);
2218 CGF.disableDebugInfo();
2219 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
2220 TaskPrivatesMapFnInfo, Args);
2221
2222 // *privi = &.privates.privi;
Alexey Bataev2377fe92015-09-10 08:12:02 +00002223 LValue Base = emitLoadOfPointerLValue(
2224 CGF, CGF.GetAddrOfLocalVar(&TaskPrivatesArg), TaskPrivatesArg.getType());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002225 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
2226 Counter = 0;
2227 for (auto *Field : PrivatesQTyRD->fields()) {
2228 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
2229 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
John McCall7f416cc2015-09-08 08:05:57 +00002230 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
Alexey Bataev2377fe92015-09-10 08:12:02 +00002231 auto RefLoadLVal =
2232 emitLoadOfPointerLValue(CGF, RefLVal.getAddress(), RefLVal.getType());
2233 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002234 ++Counter;
2235 }
2236 CGF.FinishFunction();
2237 return TaskPrivatesMap;
2238}
2239
Alexey Bataev9e034042015-05-05 04:05:12 +00002240static int array_pod_sort_comparator(const PrivateDataTy *P1,
2241 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002242 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
2243}
2244
2245void CGOpenMPRuntime::emitTaskCall(
2246 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
2247 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
John McCall7f416cc2015-09-08 08:05:57 +00002248 llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002249 const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
2250 ArrayRef<const Expr *> PrivateCopies,
2251 ArrayRef<const Expr *> FirstprivateVars,
2252 ArrayRef<const Expr *> FirstprivateCopies,
2253 ArrayRef<const Expr *> FirstprivateInits,
2254 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002255 auto &C = CGM.getContext();
Alexey Bataev9e034042015-05-05 04:05:12 +00002256 llvm::SmallVector<PrivateDataTy, 8> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002257 // Aggregate privates and sort them by the alignment.
Alexey Bataev9e034042015-05-05 04:05:12 +00002258 auto I = PrivateCopies.begin();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002259 for (auto *E : PrivateVars) {
2260 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2261 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00002262 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00002263 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
2264 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002265 ++I;
2266 }
Alexey Bataev9e034042015-05-05 04:05:12 +00002267 I = FirstprivateCopies.begin();
2268 auto IElemInitRef = FirstprivateInits.begin();
2269 for (auto *E : FirstprivateVars) {
2270 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2271 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00002272 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00002273 PrivateHelpersTy(
2274 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
2275 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
2276 ++I, ++IElemInitRef;
2277 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002278 llvm::array_pod_sort(Privates.begin(), Privates.end(),
2279 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002280 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2281 // Build type kmp_routine_entry_t (if not built yet).
2282 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002283 // Build type kmp_task_t (if not built yet).
2284 if (KmpTaskTQTy.isNull()) {
2285 KmpTaskTQTy = C.getRecordType(
2286 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
2287 }
2288 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002289 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002290 auto *KmpTaskTWithPrivatesQTyRD =
2291 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
2292 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
2293 QualType KmpTaskTWithPrivatesPtrQTy =
2294 C.getPointerType(KmpTaskTWithPrivatesQTy);
2295 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
2296 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002297 auto *KmpTaskTWithPrivatesTySize = getTypeSize(CGF, KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002298 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
2299
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002300 // Emit initial values for private copies (if any).
2301 llvm::Value *TaskPrivatesMap = nullptr;
2302 auto *TaskPrivatesMapTy =
2303 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
2304 3)
2305 ->getType();
2306 if (!Privates.empty()) {
2307 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
2308 TaskPrivatesMap = emitTaskPrivateMappingFunction(
2309 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
2310 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2311 TaskPrivatesMap, TaskPrivatesMapTy);
2312 } else {
2313 TaskPrivatesMap = llvm::ConstantPointerNull::get(
2314 cast<llvm::PointerType>(TaskPrivatesMapTy));
2315 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002316 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
2317 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002318 auto *TaskEntry = emitProxyTaskFunction(
2319 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002320 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002321
2322 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
2323 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2324 // kmp_routine_entry_t *task_entry);
2325 // Task flags. Format is taken from
2326 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
2327 // description of kmp_tasking_flags struct.
2328 const unsigned TiedFlag = 0x1;
2329 const unsigned FinalFlag = 0x2;
2330 unsigned Flags = Tied ? TiedFlag : 0;
2331 auto *TaskFlags =
2332 Final.getPointer()
2333 ? CGF.Builder.CreateSelect(Final.getPointer(),
2334 CGF.Builder.getInt32(FinalFlag),
2335 CGF.Builder.getInt32(/*C=*/0))
2336 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
2337 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataev40e36f12015-11-24 13:01:44 +00002338 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002339 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
2340 getThreadID(CGF, Loc), TaskFlags,
2341 KmpTaskTWithPrivatesTySize, SharedsSize,
2342 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2343 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00002344 auto *NewTask = CGF.EmitRuntimeCall(
2345 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002346 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2347 NewTask, KmpTaskTWithPrivatesPtrTy);
2348 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
2349 KmpTaskTWithPrivatesQTy);
2350 LValue TDBase =
2351 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002352 // Fill the data in the resulting kmp_task_t record.
2353 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00002354 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002355 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00002356 KmpTaskSharedsPtr =
2357 Address(CGF.EmitLoadOfScalar(
2358 CGF.EmitLValueForField(
2359 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
2360 KmpTaskTShareds)),
2361 Loc),
2362 CGF.getNaturalTypeAlignment(SharedsTy));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002363 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002364 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002365 // Emit initial values for private copies (if any).
2366 bool NeedsCleanup = false;
2367 if (!Privates.empty()) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002368 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
2369 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002370 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002371 LValue SharedsBase;
2372 if (!FirstprivateVars.empty()) {
John McCall7f416cc2015-09-08 08:05:57 +00002373 SharedsBase = CGF.MakeAddrLValue(
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002374 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2375 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
2376 SharedsTy);
2377 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002378 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
2379 cast<CapturedStmt>(*D.getAssociatedStmt()));
2380 for (auto &&Pair : Privates) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002381 auto *VD = Pair.second.PrivateCopy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002382 auto *Init = VD->getAnyInitializer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002383 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002384 if (Init) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002385 if (auto *Elem = Pair.second.PrivateElemInit) {
2386 auto *OriginalVD = Pair.second.Original;
2387 auto *SharedField = CapturesInfo.lookup(OriginalVD);
2388 auto SharedRefLValue =
2389 CGF.EmitLValueForField(SharedsBase, SharedField);
Alexey Bataevc71a4092015-09-11 10:29:41 +00002390 SharedRefLValue = CGF.MakeAddrLValue(
2391 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
2392 SharedRefLValue.getType(), AlignmentSource::Decl);
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002393 QualType Type = OriginalVD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002394 if (Type->isArrayType()) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002395 // Initialize firstprivate array.
2396 if (!isa<CXXConstructExpr>(Init) ||
2397 CGF.isTrivialInitializer(Init)) {
2398 // Perform simple memcpy.
2399 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002400 SharedRefLValue.getAddress(), Type);
Alexey Bataev9e034042015-05-05 04:05:12 +00002401 } else {
2402 // Initialize firstprivate array using element-by-element
2403 // intialization.
2404 CGF.EmitOMPAggregateAssign(
2405 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002406 Type, [&CGF, Elem, Init, &CapturesInfo](
John McCall7f416cc2015-09-08 08:05:57 +00002407 Address DestElement, Address SrcElement) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002408 // Clean up any temporaries needed by the initialization.
2409 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00002410 InitScope.addPrivate(Elem, [SrcElement]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00002411 return SrcElement;
2412 });
2413 (void)InitScope.Privatize();
2414 // Emit initialization for single element.
Alexey Bataevd157d472015-06-24 03:35:38 +00002415 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
2416 CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00002417 CGF.EmitAnyExprToMem(Init, DestElement,
2418 Init->getType().getQualifiers(),
2419 /*IsInitializer=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00002420 });
2421 }
2422 } else {
2423 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00002424 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00002425 return SharedRefLValue.getAddress();
2426 });
2427 (void)InitScope.Privatize();
Alexey Bataevd157d472015-06-24 03:35:38 +00002428 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00002429 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
2430 /*capturedByInit=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00002431 }
2432 } else {
2433 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
2434 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002435 }
2436 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002437 ++FI;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002438 }
2439 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002440 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002441 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002442 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
2443 KmpTaskTWithPrivatesPtrQTy,
2444 KmpTaskTWithPrivatesQTy)
2445 : llvm::ConstantPointerNull::get(
2446 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
2447 LValue Destructor = CGF.EmitLValueForField(
2448 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
2449 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2450 DestructorFn, KmpRoutineEntryPtrTy),
2451 Destructor);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002452
2453 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00002454 Address DependenciesArray = Address::invalid();
2455 unsigned NumDependencies = Dependences.size();
2456 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002457 // Dependence kind for RTL.
Alexey Bataev92e82f92015-11-23 13:33:42 +00002458 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002459 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
2460 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002461 QualType FlagsTy =
2462 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002463 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
2464 if (KmpDependInfoTy.isNull()) {
2465 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
2466 KmpDependInfoRD->startDefinition();
2467 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
2468 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
2469 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
2470 KmpDependInfoRD->completeDefinition();
2471 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
2472 } else {
2473 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
2474 }
John McCall7f416cc2015-09-08 08:05:57 +00002475 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002476 // Define type kmp_depend_info[<Dependences.size()>];
2477 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00002478 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002479 ArrayType::Normal, /*IndexTypeQuals=*/0);
2480 // kmp_depend_info[<Dependences.size()>] deps;
John McCall7f416cc2015-09-08 08:05:57 +00002481 DependenciesArray = CGF.CreateMemTemp(KmpDependInfoArrayTy);
2482 for (unsigned i = 0; i < NumDependencies; ++i) {
2483 const Expr *E = Dependences[i].second;
2484 auto Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002485 llvm::Value *Size;
2486 QualType Ty = E->getType();
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002487 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
2488 LValue UpAddrLVal =
2489 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
2490 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00002491 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002492 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00002493 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002494 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
2495 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002496 } else
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002497 Size = getTypeSize(CGF, Ty);
John McCall7f416cc2015-09-08 08:05:57 +00002498 auto Base = CGF.MakeAddrLValue(
2499 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002500 KmpDependInfoTy);
2501 // deps[i].base_addr = &<Dependences[i].second>;
2502 auto BaseAddrLVal = CGF.EmitLValueForField(
2503 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00002504 CGF.EmitStoreOfScalar(
2505 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
2506 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002507 // deps[i].len = sizeof(<Dependences[i].second>);
2508 auto LenLVal = CGF.EmitLValueForField(
2509 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
2510 CGF.EmitStoreOfScalar(Size, LenLVal);
2511 // deps[i].flags = <Dependences[i].first>;
2512 RTLDependenceKindTy DepKind;
2513 switch (Dependences[i].first) {
2514 case OMPC_DEPEND_in:
2515 DepKind = DepIn;
2516 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00002517 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002518 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002519 case OMPC_DEPEND_inout:
2520 DepKind = DepInOut;
2521 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00002522 case OMPC_DEPEND_source:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002523 case OMPC_DEPEND_unknown:
2524 llvm_unreachable("Unknown task dependence type");
2525 }
2526 auto FlagsLVal = CGF.EmitLValueForField(
2527 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
2528 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
2529 FlagsLVal);
2530 }
John McCall7f416cc2015-09-08 08:05:57 +00002531 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2532 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002533 CGF.VoidPtrTy);
2534 }
2535
Alexey Bataev62b63b12015-03-10 07:28:44 +00002536 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
2537 // libcall.
2538 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2539 // *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002540 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2541 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2542 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
2543 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00002544 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002545 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00002546 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
2547 llvm::Value *DepTaskArgs[7];
2548 if (NumDependencies) {
2549 DepTaskArgs[0] = UpLoc;
2550 DepTaskArgs[1] = ThreadID;
2551 DepTaskArgs[2] = NewTask;
2552 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
2553 DepTaskArgs[4] = DependenciesArray.getPointer();
2554 DepTaskArgs[5] = CGF.Builder.getInt32(0);
2555 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2556 }
2557 auto &&ThenCodeGen = [this, NumDependencies,
2558 &TaskArgs, &DepTaskArgs](CodeGenFunction &CGF) {
2559 // TODO: add check for untied tasks.
2560 if (NumDependencies) {
2561 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps),
2562 DepTaskArgs);
2563 } else {
2564 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
2565 TaskArgs);
2566 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002567 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00002568 typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value>
2569 IfCallEndCleanup;
John McCall7f416cc2015-09-08 08:05:57 +00002570
2571 llvm::Value *DepWaitTaskArgs[6];
2572 if (NumDependencies) {
2573 DepWaitTaskArgs[0] = UpLoc;
2574 DepWaitTaskArgs[1] = ThreadID;
2575 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
2576 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
2577 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
2578 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2579 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002580 auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
John McCall7f416cc2015-09-08 08:05:57 +00002581 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002582 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
2583 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2584 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
2585 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
2586 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00002587 if (NumDependencies)
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002588 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
2589 DepWaitTaskArgs);
2590 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
2591 // kmp_task_t *new_task);
2592 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0),
2593 TaskArgs);
2594 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
2595 // kmp_task_t *new_task);
2596 CGF.EHStack.pushCleanup<IfCallEndCleanup>(
2597 NormalAndEHCleanup,
2598 createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0),
2599 llvm::makeArrayRef(TaskArgs));
Alexey Bataev1d677132015-04-22 13:57:31 +00002600
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002601 // Call proxy_task_entry(gtid, new_task);
2602 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
2603 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
2604 };
John McCall7f416cc2015-09-08 08:05:57 +00002605
Alexey Bataev1d677132015-04-22 13:57:31 +00002606 if (IfCond) {
2607 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
2608 } else {
2609 CodeGenFunction::RunCleanupsScope Scope(CGF);
2610 ThenCodeGen(CGF);
2611 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002612}
2613
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002614/// \brief Emit reduction operation for each element of array (required for
2615/// array sections) LHS op = RHS.
2616/// \param Type Type of array.
2617/// \param LHSVar Variable on the left side of the reduction operation
2618/// (references element of array in original variable).
2619/// \param RHSVar Variable on the right side of the reduction operation
2620/// (references element of array in original variable).
2621/// \param RedOpGen Generator of reduction operation with use of LHSVar and
2622/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00002623static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002624 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
2625 const VarDecl *RHSVar,
2626 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
2627 const Expr *, const Expr *)> &RedOpGen,
2628 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
2629 const Expr *UpExpr = nullptr) {
2630 // Perform element-by-element initialization.
2631 QualType ElementTy;
2632 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
2633 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
2634
2635 // Drill down to the base element type on both arrays.
2636 auto ArrayTy = Type->getAsArrayTypeUnsafe();
2637 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
2638
2639 auto RHSBegin = RHSAddr.getPointer();
2640 auto LHSBegin = LHSAddr.getPointer();
2641 // Cast from pointer to array type to pointer to single element.
2642 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
2643 // The basic structure here is a while-do loop.
2644 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
2645 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
2646 auto IsEmpty =
2647 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
2648 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
2649
2650 // Enter the loop body, making that address the current address.
2651 auto EntryBB = CGF.Builder.GetInsertBlock();
2652 CGF.EmitBlock(BodyBB);
2653
2654 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
2655
2656 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
2657 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
2658 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
2659 Address RHSElementCurrent =
2660 Address(RHSElementPHI,
2661 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
2662
2663 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
2664 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
2665 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
2666 Address LHSElementCurrent =
2667 Address(LHSElementPHI,
2668 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
2669
2670 // Emit copy.
2671 CodeGenFunction::OMPPrivateScope Scope(CGF);
2672 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
2673 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
2674 Scope.Privatize();
2675 RedOpGen(CGF, XExpr, EExpr, UpExpr);
2676 Scope.ForceCleanup();
2677
2678 // Shift the address forward by one element.
2679 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
2680 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
2681 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
2682 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
2683 // Check whether we've reached the end.
2684 auto Done =
2685 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
2686 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
2687 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
2688 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
2689
2690 // Done.
2691 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
2692}
2693
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002694static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
2695 llvm::Type *ArgsType,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002696 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002697 ArrayRef<const Expr *> LHSExprs,
2698 ArrayRef<const Expr *> RHSExprs,
2699 ArrayRef<const Expr *> ReductionOps) {
2700 auto &C = CGM.getContext();
2701
2702 // void reduction_func(void *LHSArg, void *RHSArg);
2703 FunctionArgList Args;
2704 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2705 C.VoidPtrTy);
2706 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2707 C.VoidPtrTy);
2708 Args.push_back(&LHSArg);
2709 Args.push_back(&RHSArg);
2710 FunctionType::ExtInfo EI;
2711 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
2712 C.VoidTy, Args, EI, /*isVariadic=*/false);
2713 auto *Fn = llvm::Function::Create(
2714 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
2715 ".omp.reduction.reduction_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002716 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002717 CodeGenFunction CGF(CGM);
2718 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
2719
2720 // Dst = (void*[n])(LHSArg);
2721 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00002722 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2723 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2724 ArgsType), CGF.getPointerAlign());
2725 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2726 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2727 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002728
2729 // ...
2730 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
2731 // ...
2732 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002733 auto IPriv = Privates.begin();
2734 unsigned Idx = 0;
2735 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00002736 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
2737 Scope.addPrivate(RHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002738 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00002739 });
2740 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
2741 Scope.addPrivate(LHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002742 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00002743 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002744 QualType PrivTy = (*IPriv)->getType();
2745 if (PrivTy->isArrayType()) {
2746 // Get array size and emit VLA type.
2747 ++Idx;
2748 Address Elem =
2749 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
2750 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
2751 CodeGenFunction::OpaqueValueMapping OpaqueMap(
2752 CGF,
2753 cast<OpaqueValueExpr>(
2754 CGF.getContext().getAsVariableArrayType(PrivTy)->getSizeExpr()),
2755 RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
2756 CGF.EmitVariablyModifiedType(PrivTy);
2757 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002758 }
2759 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002760 IPriv = Privates.begin();
2761 auto ILHS = LHSExprs.begin();
2762 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002763 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002764 if ((*IPriv)->getType()->isArrayType()) {
2765 // Emit reduction for array section.
2766 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
2767 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
2768 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
2769 [=](CodeGenFunction &CGF, const Expr *,
2770 const Expr *,
2771 const Expr *) { CGF.EmitIgnoredExpr(E); });
2772 } else
2773 // Emit reduction for array subscript or single variable.
2774 CGF.EmitIgnoredExpr(E);
2775 ++IPriv, ++ILHS, ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002776 }
2777 Scope.ForceCleanup();
2778 CGF.FinishFunction();
2779 return Fn;
2780}
2781
2782void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002783 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002784 ArrayRef<const Expr *> LHSExprs,
2785 ArrayRef<const Expr *> RHSExprs,
2786 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002787 bool WithNowait, bool SimpleReduction) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002788 // Next code should be emitted for reduction:
2789 //
2790 // static kmp_critical_name lock = { 0 };
2791 //
2792 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
2793 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
2794 // ...
2795 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
2796 // *(Type<n>-1*)rhs[<n>-1]);
2797 // }
2798 //
2799 // ...
2800 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
2801 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2802 // RedList, reduce_func, &<lock>)) {
2803 // case 1:
2804 // ...
2805 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2806 // ...
2807 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2808 // break;
2809 // case 2:
2810 // ...
2811 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2812 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00002813 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002814 // break;
2815 // default:;
2816 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002817 //
2818 // if SimpleReduction is true, only the next code is generated:
2819 // ...
2820 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2821 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002822
2823 auto &C = CGM.getContext();
2824
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002825 if (SimpleReduction) {
2826 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002827 auto IPriv = Privates.begin();
2828 auto ILHS = LHSExprs.begin();
2829 auto IRHS = RHSExprs.begin();
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002830 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002831 if ((*IPriv)->getType()->isArrayType()) {
2832 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
2833 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
2834 EmitOMPAggregateReduction(
2835 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
2836 [=](CodeGenFunction &CGF, const Expr *, const Expr *,
2837 const Expr *) { CGF.EmitIgnoredExpr(E); });
2838 } else
2839 CGF.EmitIgnoredExpr(E);
2840 ++IPriv, ++ILHS, ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002841 }
2842 return;
2843 }
2844
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002845 // 1. Build a list of reduction variables.
2846 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002847 auto Size = RHSExprs.size();
2848 for (auto *E : Privates) {
2849 if (E->getType()->isArrayType())
2850 // Reserve place for array size.
2851 ++Size;
2852 }
2853 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002854 QualType ReductionArrayTy =
2855 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2856 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00002857 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002858 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002859 auto IPriv = Privates.begin();
2860 unsigned Idx = 0;
2861 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00002862 Address Elem =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002863 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00002864 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002865 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002866 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
2867 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002868 if ((*IPriv)->getType()->isArrayType()) {
2869 // Store array size.
2870 ++Idx;
2871 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
2872 CGF.getPointerSize());
2873 CGF.Builder.CreateStore(
2874 CGF.Builder.CreateIntToPtr(
2875 CGF.Builder.CreateIntCast(
2876 CGF.getVLASize(CGF.getContext().getAsVariableArrayType(
2877 (*IPriv)->getType()))
2878 .first,
2879 CGF.SizeTy, /*isSigned=*/false),
2880 CGF.VoidPtrTy),
2881 Elem);
2882 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002883 }
2884
2885 // 2. Emit reduce_func().
2886 auto *ReductionFn = emitReductionFunction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002887 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
2888 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002889
2890 // 3. Create static kmp_critical_name lock = { 0 };
2891 auto *Lock = getCriticalRegionLock(".reduction");
2892
2893 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2894 // RedList, reduce_func, &<lock>);
2895 auto *IdentTLoc = emitUpdateLocation(
2896 CGF, Loc,
2897 static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE));
2898 auto *ThreadId = getThreadID(CGF, Loc);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002899 auto *ReductionArrayTySize = getTypeSize(CGF, ReductionArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00002900 auto *RL =
2901 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
2902 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002903 llvm::Value *Args[] = {
2904 IdentTLoc, // ident_t *<loc>
2905 ThreadId, // i32 <gtid>
2906 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
2907 ReductionArrayTySize, // size_type sizeof(RedList)
2908 RL, // void *RedList
2909 ReductionFn, // void (*) (void *, void *) <reduce_func>
2910 Lock // kmp_critical_name *&<lock>
2911 };
2912 auto Res = CGF.EmitRuntimeCall(
2913 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
2914 : OMPRTL__kmpc_reduce),
2915 Args);
2916
2917 // 5. Build switch(res)
2918 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
2919 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
2920
2921 // 6. Build case 1:
2922 // ...
2923 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2924 // ...
2925 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2926 // break;
2927 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
2928 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
2929 CGF.EmitBlock(Case1BB);
2930
2931 {
2932 CodeGenFunction::RunCleanupsScope Scope(CGF);
2933 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2934 llvm::Value *EndArgs[] = {
2935 IdentTLoc, // ident_t *<loc>
2936 ThreadId, // i32 <gtid>
2937 Lock // kmp_critical_name *&<lock>
2938 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00002939 CGF.EHStack
2940 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
2941 NormalAndEHCleanup,
2942 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
2943 : OMPRTL__kmpc_end_reduce),
2944 llvm::makeArrayRef(EndArgs));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002945 auto IPriv = Privates.begin();
2946 auto ILHS = LHSExprs.begin();
2947 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002948 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002949 if ((*IPriv)->getType()->isArrayType()) {
2950 // Emit reduction for array section.
2951 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
2952 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
2953 EmitOMPAggregateReduction(
2954 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
2955 [=](CodeGenFunction &CGF, const Expr *, const Expr *,
2956 const Expr *) { CGF.EmitIgnoredExpr(E); });
2957 } else
2958 // Emit reduction for array subscript or single variable.
2959 CGF.EmitIgnoredExpr(E);
2960 ++IPriv, ++ILHS, ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002961 }
2962 }
2963
2964 CGF.EmitBranch(DefaultBB);
2965
2966 // 7. Build case 2:
2967 // ...
2968 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2969 // ...
2970 // break;
2971 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
2972 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
2973 CGF.EmitBlock(Case2BB);
2974
2975 {
2976 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataev69a47792015-05-07 03:54:03 +00002977 if (!WithNowait) {
2978 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
2979 llvm::Value *EndArgs[] = {
2980 IdentTLoc, // ident_t *<loc>
2981 ThreadId, // i32 <gtid>
2982 Lock // kmp_critical_name *&<lock>
2983 };
2984 CGF.EHStack
2985 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
2986 NormalAndEHCleanup,
2987 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
2988 llvm::makeArrayRef(EndArgs));
2989 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002990 auto ILHS = LHSExprs.begin();
2991 auto IRHS = RHSExprs.begin();
2992 auto IPriv = Privates.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002993 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002994 const Expr *XExpr = nullptr;
2995 const Expr *EExpr = nullptr;
2996 const Expr *UpExpr = nullptr;
2997 BinaryOperatorKind BO = BO_Comma;
2998 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
2999 if (BO->getOpcode() == BO_Assign) {
3000 XExpr = BO->getLHS();
3001 UpExpr = BO->getRHS();
3002 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003003 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003004 // Try to emit update expression as a simple atomic.
3005 auto *RHSExpr = UpExpr;
3006 if (RHSExpr) {
3007 // Analyze RHS part of the whole expression.
3008 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
3009 RHSExpr->IgnoreParenImpCasts())) {
3010 // If this is a conditional operator, analyze its condition for
3011 // min/max reduction operator.
3012 RHSExpr = ACO->getCond();
3013 }
3014 if (auto *BORHS =
3015 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
3016 EExpr = BORHS->getRHS();
3017 BO = BORHS->getOpcode();
3018 }
Alexey Bataev69a47792015-05-07 03:54:03 +00003019 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003020 if (XExpr) {
3021 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3022 auto &&AtomicRedGen = [this, BO, VD, IPriv,
3023 Loc](CodeGenFunction &CGF, const Expr *XExpr,
3024 const Expr *EExpr, const Expr *UpExpr) {
3025 LValue X = CGF.EmitLValue(XExpr);
3026 RValue E;
3027 if (EExpr)
3028 E = CGF.EmitAnyExpr(EExpr);
3029 CGF.EmitOMPAtomicSimpleUpdateExpr(
3030 X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
3031 [&CGF, UpExpr, VD, IPriv](RValue XRValue) {
3032 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
3033 PrivateScope.addPrivate(VD, [&CGF, VD, XRValue]() -> Address {
John McCall7f416cc2015-09-08 08:05:57 +00003034 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003035 CGF.EmitStoreThroughLValue(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003036 XRValue, CGF.MakeAddrLValue(LHSTemp, VD->getType()));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003037 return LHSTemp;
3038 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003039 (void)PrivateScope.Privatize();
3040 return CGF.EmitAnyExpr(UpExpr);
3041 });
3042 };
3043 if ((*IPriv)->getType()->isArrayType()) {
3044 // Emit atomic reduction for array section.
3045 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3046 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
3047 AtomicRedGen, XExpr, EExpr, UpExpr);
3048 } else
3049 // Emit atomic reduction for array subscript or single variable.
3050 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
3051 } else {
3052 // Emit as a critical region.
3053 auto &&CritRedGen = [this, E, Loc](CodeGenFunction &CGF, const Expr *,
3054 const Expr *, const Expr *) {
3055 emitCriticalRegion(
3056 CGF, ".atomic_reduction",
3057 [E](CodeGenFunction &CGF) { CGF.EmitIgnoredExpr(E); }, Loc);
3058 };
3059 if ((*IPriv)->getType()->isArrayType()) {
3060 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3061 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3062 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3063 CritRedGen);
3064 } else
3065 CritRedGen(CGF, nullptr, nullptr, nullptr);
3066 }
3067 ++ILHS, ++IRHS, ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003068 }
3069 }
3070
3071 CGF.EmitBranch(DefaultBB);
3072 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
3073}
3074
Alexey Bataev8b8e2022015-04-27 05:22:09 +00003075void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
3076 SourceLocation Loc) {
3077 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
3078 // global_tid);
3079 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3080 // Ignore return result until untied tasks are supported.
3081 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
3082}
3083
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003084void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003085 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00003086 const RegionCodeGenTy &CodeGen,
3087 bool HasCancel) {
3088 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003089 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003090}
3091
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003092namespace {
3093enum RTCancelKind {
3094 CancelNoreq = 0,
3095 CancelParallel = 1,
3096 CancelLoop = 2,
3097 CancelSections = 3,
3098 CancelTaskgroup = 4
3099};
3100}
3101
3102static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
3103 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00003104 if (CancelRegion == OMPD_parallel)
3105 CancelKind = CancelParallel;
3106 else if (CancelRegion == OMPD_for)
3107 CancelKind = CancelLoop;
3108 else if (CancelRegion == OMPD_sections)
3109 CancelKind = CancelSections;
3110 else {
3111 assert(CancelRegion == OMPD_taskgroup);
3112 CancelKind = CancelTaskgroup;
3113 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003114 return CancelKind;
3115}
3116
3117void CGOpenMPRuntime::emitCancellationPointCall(
3118 CodeGenFunction &CGF, SourceLocation Loc,
3119 OpenMPDirectiveKind CancelRegion) {
3120 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
3121 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003122 if (auto *OMPRegionInfo =
3123 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003124 if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
3125 return;
3126 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003127 llvm::Value *Args[] = {
3128 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3129 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003130 // Ignore return result until untied tasks are supported.
3131 auto *Result = CGF.EmitRuntimeCall(
3132 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
3133 // if (__kmpc_cancellationpoint()) {
3134 // __kmpc_cancel_barrier();
3135 // exit from construct;
3136 // }
3137 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
3138 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
3139 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
3140 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3141 CGF.EmitBlock(ExitBB);
3142 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00003143 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003144 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00003145 auto CancelDest =
3146 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003147 CGF.EmitBranchThroughCleanup(CancelDest);
3148 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3149 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00003150 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00003151}
3152
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003153void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00003154 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003155 OpenMPDirectiveKind CancelRegion) {
3156 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
3157 // kmp_int32 cncl_kind);
3158 if (auto *OMPRegionInfo =
3159 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003160 if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
3161 return;
Alexey Bataev87933c72015-09-18 08:07:34 +00003162 auto &&ThenGen = [this, Loc, CancelRegion,
3163 OMPRegionInfo](CodeGenFunction &CGF) {
3164 llvm::Value *Args[] = {
3165 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3166 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
3167 // Ignore return result until untied tasks are supported.
3168 auto *Result =
3169 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
3170 // if (__kmpc_cancel()) {
3171 // __kmpc_cancel_barrier();
3172 // exit from construct;
3173 // }
3174 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
3175 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
3176 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
3177 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3178 CGF.EmitBlock(ExitBB);
3179 // __kmpc_cancel_barrier();
3180 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
3181 // exit from construct;
3182 auto CancelDest =
3183 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
3184 CGF.EmitBranchThroughCleanup(CancelDest);
3185 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3186 };
3187 if (IfCond)
3188 emitOMPIfClause(CGF, IfCond, ThenGen, [](CodeGenFunction &) {});
3189 else
3190 ThenGen(CGF);
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003191 }
3192}
Samuel Antaobed3c462015-10-02 16:14:20 +00003193
3194llvm::Value *
3195CGOpenMPRuntime::emitTargetOutlinedFunction(const OMPExecutableDirective &D,
3196 const RegionCodeGenTy &CodeGen) {
3197 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
3198
3199 CodeGenFunction CGF(CGM, true);
3200 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen);
3201 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003202 return CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaobed3c462015-10-02 16:14:20 +00003203}
3204
3205void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
3206 const OMPExecutableDirective &D,
3207 llvm::Value *OutlinedFn,
3208 const Expr *IfCond, const Expr *Device,
3209 ArrayRef<llvm::Value *> CapturedVars) {
3210 /// \brief Values for bit flags used to specify the mapping type for
3211 /// offloading.
3212 enum OpenMPOffloadMappingFlags {
3213 /// \brief Allocate memory on the device and move data from host to device.
3214 OMP_MAP_TO = 0x01,
3215 /// \brief Allocate memory on the device and move data from device to host.
3216 OMP_MAP_FROM = 0x02,
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003217 /// \brief The element passed to the device is a pointer.
3218 OMP_MAP_PTR = 0x20,
3219 /// \brief Pass the element to the device by value.
3220 OMP_MAP_BYCOPY = 0x80,
Samuel Antaobed3c462015-10-02 16:14:20 +00003221 };
3222
3223 enum OpenMPOffloadingReservedDeviceIDs {
3224 /// \brief Device ID if the device was not defined, runtime should get it
3225 /// from environment variables in the spec.
3226 OMP_DEVICEID_UNDEF = -1,
3227 };
3228
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003229 auto &Ctx = CGF.getContext();
3230
Samuel Antaobed3c462015-10-02 16:14:20 +00003231 // Fill up the arrays with the all the captured variables.
3232 SmallVector<llvm::Value *, 16> BasePointers;
3233 SmallVector<llvm::Value *, 16> Pointers;
3234 SmallVector<llvm::Value *, 16> Sizes;
3235 SmallVector<unsigned, 16> MapTypes;
3236
3237 bool hasVLACaptures = false;
3238
3239 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
3240 auto RI = CS.getCapturedRecordDecl()->field_begin();
3241 // auto II = CS.capture_init_begin();
3242 auto CV = CapturedVars.begin();
3243 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
3244 CE = CS.capture_end();
3245 CI != CE; ++CI, ++RI, ++CV) {
3246 StringRef Name;
3247 QualType Ty;
3248 llvm::Value *BasePointer;
3249 llvm::Value *Pointer;
3250 llvm::Value *Size;
3251 unsigned MapType;
3252
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003253 // VLA sizes are passed to the outlined region by copy.
Samuel Antaobed3c462015-10-02 16:14:20 +00003254 if (CI->capturesVariableArrayType()) {
3255 BasePointer = Pointer = *CV;
3256 Size = getTypeSize(CGF, RI->getType());
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003257 // Copy to the device as an argument. No need to retrieve it.
3258 MapType = OMP_MAP_BYCOPY;
Samuel Antaobed3c462015-10-02 16:14:20 +00003259 hasVLACaptures = true;
Samuel Antaobed3c462015-10-02 16:14:20 +00003260 } else if (CI->capturesThis()) {
3261 BasePointer = Pointer = *CV;
3262 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr());
3263 Size = getTypeSize(CGF, PtrTy->getPointeeType());
3264 // Default map type.
3265 MapType = OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003266 } else if (CI->capturesVariableByCopy()) {
3267 MapType = OMP_MAP_BYCOPY;
3268 if (!RI->getType()->isAnyPointerType()) {
3269 // If the field is not a pointer, we need to save the actual value and
3270 // load it as a void pointer.
3271 auto DstAddr = CGF.CreateMemTemp(
3272 Ctx.getUIntPtrType(),
3273 Twine(CI->getCapturedVar()->getName()) + ".casted");
3274 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
3275
3276 auto *SrcAddrVal = CGF.EmitScalarConversion(
3277 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
3278 Ctx.getPointerType(RI->getType()), SourceLocation());
3279 LValue SrcLV =
3280 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType());
3281
3282 // Store the value using the source type pointer.
3283 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV);
3284
3285 // Load the value using the destination type pointer.
3286 BasePointer = Pointer =
3287 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
3288 } else {
3289 MapType |= OMP_MAP_PTR;
3290 BasePointer = Pointer = *CV;
3291 }
3292 Size = getTypeSize(CGF, RI->getType());
Samuel Antaobed3c462015-10-02 16:14:20 +00003293 } else {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003294 assert(CI->capturesVariable() && "Expected captured reference.");
Samuel Antaobed3c462015-10-02 16:14:20 +00003295 BasePointer = Pointer = *CV;
3296
3297 const ReferenceType *PtrTy =
3298 cast<ReferenceType>(RI->getType().getTypePtr());
3299 QualType ElementType = PtrTy->getPointeeType();
3300 Size = getTypeSize(CGF, ElementType);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003301 // The default map type for a scalar/complex type is 'to' because by
3302 // default the value doesn't have to be retrieved. For an aggregate type,
3303 // the default is 'tofrom'.
3304 MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
3305 : OMP_MAP_TO;
3306 if (ElementType->isAnyPointerType())
3307 MapType |= OMP_MAP_PTR;
Samuel Antaobed3c462015-10-02 16:14:20 +00003308 }
3309
3310 BasePointers.push_back(BasePointer);
3311 Pointers.push_back(Pointer);
3312 Sizes.push_back(Size);
3313 MapTypes.push_back(MapType);
3314 }
3315
3316 // Keep track on whether the host function has to be executed.
3317 auto OffloadErrorQType =
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003318 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00003319 auto OffloadError = CGF.MakeAddrLValue(
3320 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
3321 OffloadErrorQType);
3322 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
3323 OffloadError);
3324
3325 // Fill up the pointer arrays and transfer execution to the device.
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003326 auto &&ThenGen = [this, &Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes,
Samuel Antaobed3c462015-10-02 16:14:20 +00003327 hasVLACaptures, Device, OffloadError,
3328 OffloadErrorQType](CodeGenFunction &CGF) {
3329 unsigned PointerNumVal = BasePointers.size();
3330 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal);
3331 llvm::Value *BasePointersArray;
3332 llvm::Value *PointersArray;
3333 llvm::Value *SizesArray;
3334 llvm::Value *MapTypesArray;
3335
3336 if (PointerNumVal) {
3337 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003338 QualType PointerArrayType = Ctx.getConstantArrayType(
3339 Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00003340 /*IndexTypeQuals=*/0);
3341
3342 BasePointersArray =
3343 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
3344 PointersArray =
3345 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
3346
3347 // If we don't have any VLA types, we can use a constant array for the map
3348 // sizes, otherwise we need to fill up the arrays as we do for the
3349 // pointers.
3350 if (hasVLACaptures) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003351 QualType SizeArrayType = Ctx.getConstantArrayType(
3352 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00003353 /*IndexTypeQuals=*/0);
3354 SizesArray =
3355 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
3356 } else {
3357 // We expect all the sizes to be constant, so we collect them to create
3358 // a constant array.
3359 SmallVector<llvm::Constant *, 16> ConstSizes;
3360 for (auto S : Sizes)
3361 ConstSizes.push_back(cast<llvm::Constant>(S));
3362
3363 auto *SizesArrayInit = llvm::ConstantArray::get(
3364 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
3365 auto *SizesArrayGbl = new llvm::GlobalVariable(
3366 CGM.getModule(), SizesArrayInit->getType(),
3367 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
3368 SizesArrayInit, ".offload_sizes");
3369 SizesArrayGbl->setUnnamedAddr(true);
3370 SizesArray = SizesArrayGbl;
3371 }
3372
3373 // The map types are always constant so we don't need to generate code to
3374 // fill arrays. Instead, we create an array constant.
3375 llvm::Constant *MapTypesArrayInit =
3376 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
3377 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
3378 CGM.getModule(), MapTypesArrayInit->getType(),
3379 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
3380 MapTypesArrayInit, ".offload_maptypes");
3381 MapTypesArrayGbl->setUnnamedAddr(true);
3382 MapTypesArray = MapTypesArrayGbl;
3383
3384 for (unsigned i = 0; i < PointerNumVal; ++i) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003385
3386 llvm::Value *BPVal = BasePointers[i];
3387 if (BPVal->getType()->isPointerTy())
3388 BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy);
3389 else {
3390 assert(BPVal->getType()->isIntegerTy() &&
3391 "If not a pointer, the value type must be an integer.");
3392 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy);
3393 }
Samuel Antaobed3c462015-10-02 16:14:20 +00003394 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
3395 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal),
3396 BasePointersArray, 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003397 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
3398 CGF.Builder.CreateStore(BPVal, BPAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00003399
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003400 llvm::Value *PVal = Pointers[i];
3401 if (PVal->getType()->isPointerTy())
3402 PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy);
3403 else {
3404 assert(PVal->getType()->isIntegerTy() &&
3405 "If not a pointer, the value type must be an integer.");
3406 PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy);
3407 }
Samuel Antaobed3c462015-10-02 16:14:20 +00003408 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
3409 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
3410 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003411 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
3412 CGF.Builder.CreateStore(PVal, PAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00003413
3414 if (hasVLACaptures) {
3415 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
3416 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
3417 /*Idx0=*/0,
3418 /*Idx1=*/i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003419 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
Samuel Antaobed3c462015-10-02 16:14:20 +00003420 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(
3421 Sizes[i], CGM.SizeTy, /*isSigned=*/true),
3422 SAddr);
3423 }
3424 }
3425
3426 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3427 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), BasePointersArray,
3428 /*Idx0=*/0, /*Idx1=*/0);
3429 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3430 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
3431 /*Idx0=*/0,
3432 /*Idx1=*/0);
3433 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3434 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
3435 /*Idx0=*/0, /*Idx1=*/0);
3436 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3437 llvm::ArrayType::get(CGM.Int32Ty, PointerNumVal), MapTypesArray,
3438 /*Idx0=*/0,
3439 /*Idx1=*/0);
3440
3441 } else {
3442 BasePointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
3443 PointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
3444 SizesArray = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
3445 MapTypesArray =
3446 llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo());
3447 }
3448
3449 // On top of the arrays that were filled up, the target offloading call
3450 // takes as arguments the device id as well as the host pointer. The host
3451 // pointer is used by the runtime library to identify the current target
3452 // region, so it only has to be unique and not necessarily point to
3453 // anything. It could be the pointer to the outlined function that
3454 // implements the target region, but we aren't using that so that the
3455 // compiler doesn't need to keep that, and could therefore inline the host
3456 // function if proven worthwhile during optimization.
3457
3458 llvm::Value *HostPtr = new llvm::GlobalVariable(
3459 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
3460 llvm::GlobalValue::PrivateLinkage,
3461 llvm::Constant::getNullValue(CGM.Int8Ty), ".offload_hstptr");
3462
3463 // Emit device ID if any.
3464 llvm::Value *DeviceID;
3465 if (Device)
3466 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
3467 CGM.Int32Ty, /*isSigned=*/true);
3468 else
3469 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
3470
3471 llvm::Value *OffloadingArgs[] = {
3472 DeviceID, HostPtr, PointerNum, BasePointersArray,
3473 PointersArray, SizesArray, MapTypesArray};
3474 auto Return = CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target),
3475 OffloadingArgs);
3476
3477 CGF.EmitStoreOfScalar(Return, OffloadError);
3478 };
3479
3480 if (IfCond) {
3481 // Notify that the host version must be executed.
3482 auto &&ElseGen = [this, OffloadError,
3483 OffloadErrorQType](CodeGenFunction &CGF) {
3484 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/-1u),
3485 OffloadError);
3486 };
3487 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
3488 } else {
3489 CodeGenFunction::RunCleanupsScope Scope(CGF);
3490 ThenGen(CGF);
3491 }
3492
3493 // Check the error code and execute the host version if required.
3494 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
3495 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
3496 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
3497 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
3498 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
3499
3500 CGF.EmitBlock(OffloadFailedBlock);
3501 CGF.Builder.CreateCall(OutlinedFn, BasePointers);
3502 CGF.EmitBranch(OffloadContBlock);
3503
3504 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
3505 return;
3506}