blob: 33dd853bb6dfda1164f824323c9cce06c2fb0833 [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;
2522 case OMPC_DEPEND_unknown:
2523 llvm_unreachable("Unknown task dependence type");
2524 }
2525 auto FlagsLVal = CGF.EmitLValueForField(
2526 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
2527 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
2528 FlagsLVal);
2529 }
John McCall7f416cc2015-09-08 08:05:57 +00002530 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2531 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002532 CGF.VoidPtrTy);
2533 }
2534
Alexey Bataev62b63b12015-03-10 07:28:44 +00002535 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
2536 // libcall.
2537 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2538 // *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002539 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2540 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2541 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
2542 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00002543 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002544 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00002545 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
2546 llvm::Value *DepTaskArgs[7];
2547 if (NumDependencies) {
2548 DepTaskArgs[0] = UpLoc;
2549 DepTaskArgs[1] = ThreadID;
2550 DepTaskArgs[2] = NewTask;
2551 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
2552 DepTaskArgs[4] = DependenciesArray.getPointer();
2553 DepTaskArgs[5] = CGF.Builder.getInt32(0);
2554 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2555 }
2556 auto &&ThenCodeGen = [this, NumDependencies,
2557 &TaskArgs, &DepTaskArgs](CodeGenFunction &CGF) {
2558 // TODO: add check for untied tasks.
2559 if (NumDependencies) {
2560 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps),
2561 DepTaskArgs);
2562 } else {
2563 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
2564 TaskArgs);
2565 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002566 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00002567 typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value>
2568 IfCallEndCleanup;
John McCall7f416cc2015-09-08 08:05:57 +00002569
2570 llvm::Value *DepWaitTaskArgs[6];
2571 if (NumDependencies) {
2572 DepWaitTaskArgs[0] = UpLoc;
2573 DepWaitTaskArgs[1] = ThreadID;
2574 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
2575 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
2576 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
2577 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2578 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002579 auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
John McCall7f416cc2015-09-08 08:05:57 +00002580 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002581 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
2582 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2583 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
2584 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
2585 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00002586 if (NumDependencies)
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002587 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
2588 DepWaitTaskArgs);
2589 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
2590 // kmp_task_t *new_task);
2591 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0),
2592 TaskArgs);
2593 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
2594 // kmp_task_t *new_task);
2595 CGF.EHStack.pushCleanup<IfCallEndCleanup>(
2596 NormalAndEHCleanup,
2597 createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0),
2598 llvm::makeArrayRef(TaskArgs));
Alexey Bataev1d677132015-04-22 13:57:31 +00002599
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002600 // Call proxy_task_entry(gtid, new_task);
2601 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
2602 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
2603 };
John McCall7f416cc2015-09-08 08:05:57 +00002604
Alexey Bataev1d677132015-04-22 13:57:31 +00002605 if (IfCond) {
2606 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
2607 } else {
2608 CodeGenFunction::RunCleanupsScope Scope(CGF);
2609 ThenCodeGen(CGF);
2610 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002611}
2612
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002613/// \brief Emit reduction operation for each element of array (required for
2614/// array sections) LHS op = RHS.
2615/// \param Type Type of array.
2616/// \param LHSVar Variable on the left side of the reduction operation
2617/// (references element of array in original variable).
2618/// \param RHSVar Variable on the right side of the reduction operation
2619/// (references element of array in original variable).
2620/// \param RedOpGen Generator of reduction operation with use of LHSVar and
2621/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00002622static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002623 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
2624 const VarDecl *RHSVar,
2625 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
2626 const Expr *, const Expr *)> &RedOpGen,
2627 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
2628 const Expr *UpExpr = nullptr) {
2629 // Perform element-by-element initialization.
2630 QualType ElementTy;
2631 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
2632 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
2633
2634 // Drill down to the base element type on both arrays.
2635 auto ArrayTy = Type->getAsArrayTypeUnsafe();
2636 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
2637
2638 auto RHSBegin = RHSAddr.getPointer();
2639 auto LHSBegin = LHSAddr.getPointer();
2640 // Cast from pointer to array type to pointer to single element.
2641 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
2642 // The basic structure here is a while-do loop.
2643 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
2644 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
2645 auto IsEmpty =
2646 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
2647 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
2648
2649 // Enter the loop body, making that address the current address.
2650 auto EntryBB = CGF.Builder.GetInsertBlock();
2651 CGF.EmitBlock(BodyBB);
2652
2653 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
2654
2655 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
2656 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
2657 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
2658 Address RHSElementCurrent =
2659 Address(RHSElementPHI,
2660 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
2661
2662 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
2663 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
2664 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
2665 Address LHSElementCurrent =
2666 Address(LHSElementPHI,
2667 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
2668
2669 // Emit copy.
2670 CodeGenFunction::OMPPrivateScope Scope(CGF);
2671 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
2672 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
2673 Scope.Privatize();
2674 RedOpGen(CGF, XExpr, EExpr, UpExpr);
2675 Scope.ForceCleanup();
2676
2677 // Shift the address forward by one element.
2678 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
2679 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
2680 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
2681 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
2682 // Check whether we've reached the end.
2683 auto Done =
2684 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
2685 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
2686 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
2687 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
2688
2689 // Done.
2690 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
2691}
2692
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002693static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
2694 llvm::Type *ArgsType,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002695 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002696 ArrayRef<const Expr *> LHSExprs,
2697 ArrayRef<const Expr *> RHSExprs,
2698 ArrayRef<const Expr *> ReductionOps) {
2699 auto &C = CGM.getContext();
2700
2701 // void reduction_func(void *LHSArg, void *RHSArg);
2702 FunctionArgList Args;
2703 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2704 C.VoidPtrTy);
2705 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2706 C.VoidPtrTy);
2707 Args.push_back(&LHSArg);
2708 Args.push_back(&RHSArg);
2709 FunctionType::ExtInfo EI;
2710 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
2711 C.VoidTy, Args, EI, /*isVariadic=*/false);
2712 auto *Fn = llvm::Function::Create(
2713 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
2714 ".omp.reduction.reduction_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002715 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002716 CodeGenFunction CGF(CGM);
2717 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
2718
2719 // Dst = (void*[n])(LHSArg);
2720 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00002721 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2722 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2723 ArgsType), CGF.getPointerAlign());
2724 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2725 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2726 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002727
2728 // ...
2729 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
2730 // ...
2731 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002732 auto IPriv = Privates.begin();
2733 unsigned Idx = 0;
2734 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00002735 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
2736 Scope.addPrivate(RHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002737 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00002738 });
2739 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
2740 Scope.addPrivate(LHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002741 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00002742 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002743 QualType PrivTy = (*IPriv)->getType();
2744 if (PrivTy->isArrayType()) {
2745 // Get array size and emit VLA type.
2746 ++Idx;
2747 Address Elem =
2748 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
2749 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
2750 CodeGenFunction::OpaqueValueMapping OpaqueMap(
2751 CGF,
2752 cast<OpaqueValueExpr>(
2753 CGF.getContext().getAsVariableArrayType(PrivTy)->getSizeExpr()),
2754 RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
2755 CGF.EmitVariablyModifiedType(PrivTy);
2756 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002757 }
2758 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002759 IPriv = Privates.begin();
2760 auto ILHS = LHSExprs.begin();
2761 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002762 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002763 if ((*IPriv)->getType()->isArrayType()) {
2764 // Emit reduction for array section.
2765 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
2766 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
2767 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
2768 [=](CodeGenFunction &CGF, const Expr *,
2769 const Expr *,
2770 const Expr *) { CGF.EmitIgnoredExpr(E); });
2771 } else
2772 // Emit reduction for array subscript or single variable.
2773 CGF.EmitIgnoredExpr(E);
2774 ++IPriv, ++ILHS, ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002775 }
2776 Scope.ForceCleanup();
2777 CGF.FinishFunction();
2778 return Fn;
2779}
2780
2781void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002782 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002783 ArrayRef<const Expr *> LHSExprs,
2784 ArrayRef<const Expr *> RHSExprs,
2785 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002786 bool WithNowait, bool SimpleReduction) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002787 // Next code should be emitted for reduction:
2788 //
2789 // static kmp_critical_name lock = { 0 };
2790 //
2791 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
2792 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
2793 // ...
2794 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
2795 // *(Type<n>-1*)rhs[<n>-1]);
2796 // }
2797 //
2798 // ...
2799 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
2800 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2801 // RedList, reduce_func, &<lock>)) {
2802 // case 1:
2803 // ...
2804 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2805 // ...
2806 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2807 // break;
2808 // case 2:
2809 // ...
2810 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2811 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00002812 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002813 // break;
2814 // default:;
2815 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002816 //
2817 // if SimpleReduction is true, only the next code is generated:
2818 // ...
2819 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2820 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002821
2822 auto &C = CGM.getContext();
2823
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002824 if (SimpleReduction) {
2825 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002826 auto IPriv = Privates.begin();
2827 auto ILHS = LHSExprs.begin();
2828 auto IRHS = RHSExprs.begin();
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002829 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002830 if ((*IPriv)->getType()->isArrayType()) {
2831 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
2832 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
2833 EmitOMPAggregateReduction(
2834 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
2835 [=](CodeGenFunction &CGF, const Expr *, const Expr *,
2836 const Expr *) { CGF.EmitIgnoredExpr(E); });
2837 } else
2838 CGF.EmitIgnoredExpr(E);
2839 ++IPriv, ++ILHS, ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002840 }
2841 return;
2842 }
2843
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002844 // 1. Build a list of reduction variables.
2845 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002846 auto Size = RHSExprs.size();
2847 for (auto *E : Privates) {
2848 if (E->getType()->isArrayType())
2849 // Reserve place for array size.
2850 ++Size;
2851 }
2852 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002853 QualType ReductionArrayTy =
2854 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2855 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00002856 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002857 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002858 auto IPriv = Privates.begin();
2859 unsigned Idx = 0;
2860 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00002861 Address Elem =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002862 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00002863 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002864 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002865 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
2866 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002867 if ((*IPriv)->getType()->isArrayType()) {
2868 // Store array size.
2869 ++Idx;
2870 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
2871 CGF.getPointerSize());
2872 CGF.Builder.CreateStore(
2873 CGF.Builder.CreateIntToPtr(
2874 CGF.Builder.CreateIntCast(
2875 CGF.getVLASize(CGF.getContext().getAsVariableArrayType(
2876 (*IPriv)->getType()))
2877 .first,
2878 CGF.SizeTy, /*isSigned=*/false),
2879 CGF.VoidPtrTy),
2880 Elem);
2881 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002882 }
2883
2884 // 2. Emit reduce_func().
2885 auto *ReductionFn = emitReductionFunction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002886 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
2887 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002888
2889 // 3. Create static kmp_critical_name lock = { 0 };
2890 auto *Lock = getCriticalRegionLock(".reduction");
2891
2892 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2893 // RedList, reduce_func, &<lock>);
2894 auto *IdentTLoc = emitUpdateLocation(
2895 CGF, Loc,
2896 static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE));
2897 auto *ThreadId = getThreadID(CGF, Loc);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002898 auto *ReductionArrayTySize = getTypeSize(CGF, ReductionArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00002899 auto *RL =
2900 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
2901 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002902 llvm::Value *Args[] = {
2903 IdentTLoc, // ident_t *<loc>
2904 ThreadId, // i32 <gtid>
2905 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
2906 ReductionArrayTySize, // size_type sizeof(RedList)
2907 RL, // void *RedList
2908 ReductionFn, // void (*) (void *, void *) <reduce_func>
2909 Lock // kmp_critical_name *&<lock>
2910 };
2911 auto Res = CGF.EmitRuntimeCall(
2912 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
2913 : OMPRTL__kmpc_reduce),
2914 Args);
2915
2916 // 5. Build switch(res)
2917 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
2918 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
2919
2920 // 6. Build case 1:
2921 // ...
2922 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2923 // ...
2924 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2925 // break;
2926 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
2927 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
2928 CGF.EmitBlock(Case1BB);
2929
2930 {
2931 CodeGenFunction::RunCleanupsScope Scope(CGF);
2932 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2933 llvm::Value *EndArgs[] = {
2934 IdentTLoc, // ident_t *<loc>
2935 ThreadId, // i32 <gtid>
2936 Lock // kmp_critical_name *&<lock>
2937 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00002938 CGF.EHStack
2939 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
2940 NormalAndEHCleanup,
2941 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
2942 : OMPRTL__kmpc_end_reduce),
2943 llvm::makeArrayRef(EndArgs));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002944 auto IPriv = Privates.begin();
2945 auto ILHS = LHSExprs.begin();
2946 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002947 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002948 if ((*IPriv)->getType()->isArrayType()) {
2949 // Emit reduction for array section.
2950 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
2951 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
2952 EmitOMPAggregateReduction(
2953 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
2954 [=](CodeGenFunction &CGF, const Expr *, const Expr *,
2955 const Expr *) { CGF.EmitIgnoredExpr(E); });
2956 } else
2957 // Emit reduction for array subscript or single variable.
2958 CGF.EmitIgnoredExpr(E);
2959 ++IPriv, ++ILHS, ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002960 }
2961 }
2962
2963 CGF.EmitBranch(DefaultBB);
2964
2965 // 7. Build case 2:
2966 // ...
2967 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2968 // ...
2969 // break;
2970 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
2971 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
2972 CGF.EmitBlock(Case2BB);
2973
2974 {
2975 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataev69a47792015-05-07 03:54:03 +00002976 if (!WithNowait) {
2977 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
2978 llvm::Value *EndArgs[] = {
2979 IdentTLoc, // ident_t *<loc>
2980 ThreadId, // i32 <gtid>
2981 Lock // kmp_critical_name *&<lock>
2982 };
2983 CGF.EHStack
2984 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
2985 NormalAndEHCleanup,
2986 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
2987 llvm::makeArrayRef(EndArgs));
2988 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002989 auto ILHS = LHSExprs.begin();
2990 auto IRHS = RHSExprs.begin();
2991 auto IPriv = Privates.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002992 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002993 const Expr *XExpr = nullptr;
2994 const Expr *EExpr = nullptr;
2995 const Expr *UpExpr = nullptr;
2996 BinaryOperatorKind BO = BO_Comma;
2997 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
2998 if (BO->getOpcode() == BO_Assign) {
2999 XExpr = BO->getLHS();
3000 UpExpr = BO->getRHS();
3001 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003002 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003003 // Try to emit update expression as a simple atomic.
3004 auto *RHSExpr = UpExpr;
3005 if (RHSExpr) {
3006 // Analyze RHS part of the whole expression.
3007 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
3008 RHSExpr->IgnoreParenImpCasts())) {
3009 // If this is a conditional operator, analyze its condition for
3010 // min/max reduction operator.
3011 RHSExpr = ACO->getCond();
3012 }
3013 if (auto *BORHS =
3014 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
3015 EExpr = BORHS->getRHS();
3016 BO = BORHS->getOpcode();
3017 }
Alexey Bataev69a47792015-05-07 03:54:03 +00003018 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003019 if (XExpr) {
3020 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3021 auto &&AtomicRedGen = [this, BO, VD, IPriv,
3022 Loc](CodeGenFunction &CGF, const Expr *XExpr,
3023 const Expr *EExpr, const Expr *UpExpr) {
3024 LValue X = CGF.EmitLValue(XExpr);
3025 RValue E;
3026 if (EExpr)
3027 E = CGF.EmitAnyExpr(EExpr);
3028 CGF.EmitOMPAtomicSimpleUpdateExpr(
3029 X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
3030 [&CGF, UpExpr, VD, IPriv](RValue XRValue) {
3031 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
3032 PrivateScope.addPrivate(VD, [&CGF, VD, XRValue]() -> Address {
John McCall7f416cc2015-09-08 08:05:57 +00003033 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003034 CGF.EmitStoreThroughLValue(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003035 XRValue, CGF.MakeAddrLValue(LHSTemp, VD->getType()));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003036 return LHSTemp;
3037 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003038 (void)PrivateScope.Privatize();
3039 return CGF.EmitAnyExpr(UpExpr);
3040 });
3041 };
3042 if ((*IPriv)->getType()->isArrayType()) {
3043 // Emit atomic reduction for array section.
3044 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3045 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
3046 AtomicRedGen, XExpr, EExpr, UpExpr);
3047 } else
3048 // Emit atomic reduction for array subscript or single variable.
3049 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
3050 } else {
3051 // Emit as a critical region.
3052 auto &&CritRedGen = [this, E, Loc](CodeGenFunction &CGF, const Expr *,
3053 const Expr *, const Expr *) {
3054 emitCriticalRegion(
3055 CGF, ".atomic_reduction",
3056 [E](CodeGenFunction &CGF) { CGF.EmitIgnoredExpr(E); }, Loc);
3057 };
3058 if ((*IPriv)->getType()->isArrayType()) {
3059 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3060 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3061 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3062 CritRedGen);
3063 } else
3064 CritRedGen(CGF, nullptr, nullptr, nullptr);
3065 }
3066 ++ILHS, ++IRHS, ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003067 }
3068 }
3069
3070 CGF.EmitBranch(DefaultBB);
3071 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
3072}
3073
Alexey Bataev8b8e2022015-04-27 05:22:09 +00003074void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
3075 SourceLocation Loc) {
3076 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
3077 // global_tid);
3078 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3079 // Ignore return result until untied tasks are supported.
3080 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
3081}
3082
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003083void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003084 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00003085 const RegionCodeGenTy &CodeGen,
3086 bool HasCancel) {
3087 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003088 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003089}
3090
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003091namespace {
3092enum RTCancelKind {
3093 CancelNoreq = 0,
3094 CancelParallel = 1,
3095 CancelLoop = 2,
3096 CancelSections = 3,
3097 CancelTaskgroup = 4
3098};
3099}
3100
3101static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
3102 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00003103 if (CancelRegion == OMPD_parallel)
3104 CancelKind = CancelParallel;
3105 else if (CancelRegion == OMPD_for)
3106 CancelKind = CancelLoop;
3107 else if (CancelRegion == OMPD_sections)
3108 CancelKind = CancelSections;
3109 else {
3110 assert(CancelRegion == OMPD_taskgroup);
3111 CancelKind = CancelTaskgroup;
3112 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003113 return CancelKind;
3114}
3115
3116void CGOpenMPRuntime::emitCancellationPointCall(
3117 CodeGenFunction &CGF, SourceLocation Loc,
3118 OpenMPDirectiveKind CancelRegion) {
3119 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
3120 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003121 if (auto *OMPRegionInfo =
3122 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003123 if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
3124 return;
3125 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003126 llvm::Value *Args[] = {
3127 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3128 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003129 // Ignore return result until untied tasks are supported.
3130 auto *Result = CGF.EmitRuntimeCall(
3131 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
3132 // if (__kmpc_cancellationpoint()) {
3133 // __kmpc_cancel_barrier();
3134 // exit from construct;
3135 // }
3136 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
3137 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
3138 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
3139 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3140 CGF.EmitBlock(ExitBB);
3141 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00003142 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003143 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00003144 auto CancelDest =
3145 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003146 CGF.EmitBranchThroughCleanup(CancelDest);
3147 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3148 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00003149 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00003150}
3151
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003152void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00003153 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003154 OpenMPDirectiveKind CancelRegion) {
3155 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
3156 // kmp_int32 cncl_kind);
3157 if (auto *OMPRegionInfo =
3158 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003159 if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
3160 return;
Alexey Bataev87933c72015-09-18 08:07:34 +00003161 auto &&ThenGen = [this, Loc, CancelRegion,
3162 OMPRegionInfo](CodeGenFunction &CGF) {
3163 llvm::Value *Args[] = {
3164 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3165 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
3166 // Ignore return result until untied tasks are supported.
3167 auto *Result =
3168 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
3169 // if (__kmpc_cancel()) {
3170 // __kmpc_cancel_barrier();
3171 // exit from construct;
3172 // }
3173 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
3174 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
3175 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
3176 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3177 CGF.EmitBlock(ExitBB);
3178 // __kmpc_cancel_barrier();
3179 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
3180 // exit from construct;
3181 auto CancelDest =
3182 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
3183 CGF.EmitBranchThroughCleanup(CancelDest);
3184 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3185 };
3186 if (IfCond)
3187 emitOMPIfClause(CGF, IfCond, ThenGen, [](CodeGenFunction &) {});
3188 else
3189 ThenGen(CGF);
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003190 }
3191}
Samuel Antaobed3c462015-10-02 16:14:20 +00003192
3193llvm::Value *
3194CGOpenMPRuntime::emitTargetOutlinedFunction(const OMPExecutableDirective &D,
3195 const RegionCodeGenTy &CodeGen) {
3196 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
3197
3198 CodeGenFunction CGF(CGM, true);
3199 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen);
3200 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003201 return CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaobed3c462015-10-02 16:14:20 +00003202}
3203
3204void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
3205 const OMPExecutableDirective &D,
3206 llvm::Value *OutlinedFn,
3207 const Expr *IfCond, const Expr *Device,
3208 ArrayRef<llvm::Value *> CapturedVars) {
3209 /// \brief Values for bit flags used to specify the mapping type for
3210 /// offloading.
3211 enum OpenMPOffloadMappingFlags {
3212 /// \brief Allocate memory on the device and move data from host to device.
3213 OMP_MAP_TO = 0x01,
3214 /// \brief Allocate memory on the device and move data from device to host.
3215 OMP_MAP_FROM = 0x02,
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003216 /// \brief The element passed to the device is a pointer.
3217 OMP_MAP_PTR = 0x20,
3218 /// \brief Pass the element to the device by value.
3219 OMP_MAP_BYCOPY = 0x80,
Samuel Antaobed3c462015-10-02 16:14:20 +00003220 };
3221
3222 enum OpenMPOffloadingReservedDeviceIDs {
3223 /// \brief Device ID if the device was not defined, runtime should get it
3224 /// from environment variables in the spec.
3225 OMP_DEVICEID_UNDEF = -1,
3226 };
3227
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003228 auto &Ctx = CGF.getContext();
3229
Samuel Antaobed3c462015-10-02 16:14:20 +00003230 // Fill up the arrays with the all the captured variables.
3231 SmallVector<llvm::Value *, 16> BasePointers;
3232 SmallVector<llvm::Value *, 16> Pointers;
3233 SmallVector<llvm::Value *, 16> Sizes;
3234 SmallVector<unsigned, 16> MapTypes;
3235
3236 bool hasVLACaptures = false;
3237
3238 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
3239 auto RI = CS.getCapturedRecordDecl()->field_begin();
3240 // auto II = CS.capture_init_begin();
3241 auto CV = CapturedVars.begin();
3242 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
3243 CE = CS.capture_end();
3244 CI != CE; ++CI, ++RI, ++CV) {
3245 StringRef Name;
3246 QualType Ty;
3247 llvm::Value *BasePointer;
3248 llvm::Value *Pointer;
3249 llvm::Value *Size;
3250 unsigned MapType;
3251
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003252 // VLA sizes are passed to the outlined region by copy.
Samuel Antaobed3c462015-10-02 16:14:20 +00003253 if (CI->capturesVariableArrayType()) {
3254 BasePointer = Pointer = *CV;
3255 Size = getTypeSize(CGF, RI->getType());
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003256 // Copy to the device as an argument. No need to retrieve it.
3257 MapType = OMP_MAP_BYCOPY;
Samuel Antaobed3c462015-10-02 16:14:20 +00003258 hasVLACaptures = true;
Samuel Antaobed3c462015-10-02 16:14:20 +00003259 } else if (CI->capturesThis()) {
3260 BasePointer = Pointer = *CV;
3261 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr());
3262 Size = getTypeSize(CGF, PtrTy->getPointeeType());
3263 // Default map type.
3264 MapType = OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003265 } else if (CI->capturesVariableByCopy()) {
3266 MapType = OMP_MAP_BYCOPY;
3267 if (!RI->getType()->isAnyPointerType()) {
3268 // If the field is not a pointer, we need to save the actual value and
3269 // load it as a void pointer.
3270 auto DstAddr = CGF.CreateMemTemp(
3271 Ctx.getUIntPtrType(),
3272 Twine(CI->getCapturedVar()->getName()) + ".casted");
3273 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
3274
3275 auto *SrcAddrVal = CGF.EmitScalarConversion(
3276 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
3277 Ctx.getPointerType(RI->getType()), SourceLocation());
3278 LValue SrcLV =
3279 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType());
3280
3281 // Store the value using the source type pointer.
3282 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV);
3283
3284 // Load the value using the destination type pointer.
3285 BasePointer = Pointer =
3286 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
3287 } else {
3288 MapType |= OMP_MAP_PTR;
3289 BasePointer = Pointer = *CV;
3290 }
3291 Size = getTypeSize(CGF, RI->getType());
Samuel Antaobed3c462015-10-02 16:14:20 +00003292 } else {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003293 assert(CI->capturesVariable() && "Expected captured reference.");
Samuel Antaobed3c462015-10-02 16:14:20 +00003294 BasePointer = Pointer = *CV;
3295
3296 const ReferenceType *PtrTy =
3297 cast<ReferenceType>(RI->getType().getTypePtr());
3298 QualType ElementType = PtrTy->getPointeeType();
3299 Size = getTypeSize(CGF, ElementType);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003300 // The default map type for a scalar/complex type is 'to' because by
3301 // default the value doesn't have to be retrieved. For an aggregate type,
3302 // the default is 'tofrom'.
3303 MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
3304 : OMP_MAP_TO;
3305 if (ElementType->isAnyPointerType())
3306 MapType |= OMP_MAP_PTR;
Samuel Antaobed3c462015-10-02 16:14:20 +00003307 }
3308
3309 BasePointers.push_back(BasePointer);
3310 Pointers.push_back(Pointer);
3311 Sizes.push_back(Size);
3312 MapTypes.push_back(MapType);
3313 }
3314
3315 // Keep track on whether the host function has to be executed.
3316 auto OffloadErrorQType =
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003317 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00003318 auto OffloadError = CGF.MakeAddrLValue(
3319 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
3320 OffloadErrorQType);
3321 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
3322 OffloadError);
3323
3324 // Fill up the pointer arrays and transfer execution to the device.
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003325 auto &&ThenGen = [this, &Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes,
Samuel Antaobed3c462015-10-02 16:14:20 +00003326 hasVLACaptures, Device, OffloadError,
3327 OffloadErrorQType](CodeGenFunction &CGF) {
3328 unsigned PointerNumVal = BasePointers.size();
3329 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal);
3330 llvm::Value *BasePointersArray;
3331 llvm::Value *PointersArray;
3332 llvm::Value *SizesArray;
3333 llvm::Value *MapTypesArray;
3334
3335 if (PointerNumVal) {
3336 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003337 QualType PointerArrayType = Ctx.getConstantArrayType(
3338 Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00003339 /*IndexTypeQuals=*/0);
3340
3341 BasePointersArray =
3342 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
3343 PointersArray =
3344 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
3345
3346 // If we don't have any VLA types, we can use a constant array for the map
3347 // sizes, otherwise we need to fill up the arrays as we do for the
3348 // pointers.
3349 if (hasVLACaptures) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003350 QualType SizeArrayType = Ctx.getConstantArrayType(
3351 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00003352 /*IndexTypeQuals=*/0);
3353 SizesArray =
3354 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
3355 } else {
3356 // We expect all the sizes to be constant, so we collect them to create
3357 // a constant array.
3358 SmallVector<llvm::Constant *, 16> ConstSizes;
3359 for (auto S : Sizes)
3360 ConstSizes.push_back(cast<llvm::Constant>(S));
3361
3362 auto *SizesArrayInit = llvm::ConstantArray::get(
3363 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
3364 auto *SizesArrayGbl = new llvm::GlobalVariable(
3365 CGM.getModule(), SizesArrayInit->getType(),
3366 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
3367 SizesArrayInit, ".offload_sizes");
3368 SizesArrayGbl->setUnnamedAddr(true);
3369 SizesArray = SizesArrayGbl;
3370 }
3371
3372 // The map types are always constant so we don't need to generate code to
3373 // fill arrays. Instead, we create an array constant.
3374 llvm::Constant *MapTypesArrayInit =
3375 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
3376 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
3377 CGM.getModule(), MapTypesArrayInit->getType(),
3378 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
3379 MapTypesArrayInit, ".offload_maptypes");
3380 MapTypesArrayGbl->setUnnamedAddr(true);
3381 MapTypesArray = MapTypesArrayGbl;
3382
3383 for (unsigned i = 0; i < PointerNumVal; ++i) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003384
3385 llvm::Value *BPVal = BasePointers[i];
3386 if (BPVal->getType()->isPointerTy())
3387 BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy);
3388 else {
3389 assert(BPVal->getType()->isIntegerTy() &&
3390 "If not a pointer, the value type must be an integer.");
3391 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy);
3392 }
Samuel Antaobed3c462015-10-02 16:14:20 +00003393 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
3394 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal),
3395 BasePointersArray, 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003396 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
3397 CGF.Builder.CreateStore(BPVal, BPAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00003398
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003399 llvm::Value *PVal = Pointers[i];
3400 if (PVal->getType()->isPointerTy())
3401 PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy);
3402 else {
3403 assert(PVal->getType()->isIntegerTy() &&
3404 "If not a pointer, the value type must be an integer.");
3405 PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy);
3406 }
Samuel Antaobed3c462015-10-02 16:14:20 +00003407 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
3408 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
3409 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003410 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
3411 CGF.Builder.CreateStore(PVal, PAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00003412
3413 if (hasVLACaptures) {
3414 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
3415 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
3416 /*Idx0=*/0,
3417 /*Idx1=*/i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00003418 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
Samuel Antaobed3c462015-10-02 16:14:20 +00003419 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(
3420 Sizes[i], CGM.SizeTy, /*isSigned=*/true),
3421 SAddr);
3422 }
3423 }
3424
3425 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3426 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), BasePointersArray,
3427 /*Idx0=*/0, /*Idx1=*/0);
3428 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3429 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
3430 /*Idx0=*/0,
3431 /*Idx1=*/0);
3432 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3433 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
3434 /*Idx0=*/0, /*Idx1=*/0);
3435 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3436 llvm::ArrayType::get(CGM.Int32Ty, PointerNumVal), MapTypesArray,
3437 /*Idx0=*/0,
3438 /*Idx1=*/0);
3439
3440 } else {
3441 BasePointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
3442 PointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
3443 SizesArray = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
3444 MapTypesArray =
3445 llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo());
3446 }
3447
3448 // On top of the arrays that were filled up, the target offloading call
3449 // takes as arguments the device id as well as the host pointer. The host
3450 // pointer is used by the runtime library to identify the current target
3451 // region, so it only has to be unique and not necessarily point to
3452 // anything. It could be the pointer to the outlined function that
3453 // implements the target region, but we aren't using that so that the
3454 // compiler doesn't need to keep that, and could therefore inline the host
3455 // function if proven worthwhile during optimization.
3456
3457 llvm::Value *HostPtr = new llvm::GlobalVariable(
3458 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
3459 llvm::GlobalValue::PrivateLinkage,
3460 llvm::Constant::getNullValue(CGM.Int8Ty), ".offload_hstptr");
3461
3462 // Emit device ID if any.
3463 llvm::Value *DeviceID;
3464 if (Device)
3465 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
3466 CGM.Int32Ty, /*isSigned=*/true);
3467 else
3468 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
3469
3470 llvm::Value *OffloadingArgs[] = {
3471 DeviceID, HostPtr, PointerNum, BasePointersArray,
3472 PointersArray, SizesArray, MapTypesArray};
3473 auto Return = CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target),
3474 OffloadingArgs);
3475
3476 CGF.EmitStoreOfScalar(Return, OffloadError);
3477 };
3478
3479 if (IfCond) {
3480 // Notify that the host version must be executed.
3481 auto &&ElseGen = [this, OffloadError,
3482 OffloadErrorQType](CodeGenFunction &CGF) {
3483 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/-1u),
3484 OffloadError);
3485 };
3486 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
3487 } else {
3488 CodeGenFunction::RunCleanupsScope Scope(CGF);
3489 ThenGen(CGF);
3490 }
3491
3492 // Check the error code and execute the host version if required.
3493 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
3494 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
3495 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
3496 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
3497 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
3498
3499 CGF.EmitBlock(OffloadFailedBlock);
3500 CGF.Builder.CreateCall(OutlinedFn, BasePointers);
3501 CGF.EmitBranch(OffloadContBlock);
3502
3503 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
3504 return;
3505}