blob: 9c484de2847c09cf1a8ab4d887a01238a00d6ca5 [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 Bataev97720002014-11-11 04:05:39 +0000560 case OMPRTL__kmpc_threadprivate_register: {
561 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
562 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
563 // typedef void *(*kmpc_ctor)(void *);
564 auto KmpcCtorTy =
565 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
566 /*isVarArg*/ false)->getPointerTo();
567 // typedef void *(*kmpc_cctor)(void *, void *);
568 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
569 auto KmpcCopyCtorTy =
570 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
571 /*isVarArg*/ false)->getPointerTo();
572 // typedef void (*kmpc_dtor)(void *);
573 auto KmpcDtorTy =
574 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
575 ->getPointerTo();
576 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
577 KmpcCopyCtorTy, KmpcDtorTy};
578 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
579 /*isVarArg*/ false);
580 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
581 break;
582 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000583 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000584 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
585 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000586 llvm::Type *TypeParams[] = {
587 getIdentTyPointerTy(), CGM.Int32Ty,
588 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
589 llvm::FunctionType *FnTy =
590 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
591 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
592 break;
593 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000594 case OMPRTL__kmpc_cancel_barrier: {
595 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
596 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000597 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
598 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000599 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
600 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000601 break;
602 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000603 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +0000604 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000605 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
606 llvm::FunctionType *FnTy =
607 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
608 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
609 break;
610 }
Alexander Musmanc6388682014-12-15 07:07:06 +0000611 case OMPRTL__kmpc_for_static_fini: {
612 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
613 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
614 llvm::FunctionType *FnTy =
615 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
616 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
617 break;
618 }
Alexey Bataevb2059782014-10-13 08:23:51 +0000619 case OMPRTL__kmpc_push_num_threads: {
620 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
621 // kmp_int32 num_threads)
622 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
623 CGM.Int32Ty};
624 llvm::FunctionType *FnTy =
625 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
626 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
627 break;
628 }
Alexey Bataevd74d0602014-10-13 06:02:40 +0000629 case OMPRTL__kmpc_serialized_parallel: {
630 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
631 // global_tid);
632 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
633 llvm::FunctionType *FnTy =
634 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
635 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
636 break;
637 }
638 case OMPRTL__kmpc_end_serialized_parallel: {
639 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
640 // global_tid);
641 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
642 llvm::FunctionType *FnTy =
643 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
644 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
645 break;
646 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000647 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000648 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000649 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
650 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000651 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000652 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
653 break;
654 }
Alexey Bataev8d690652014-12-04 07:23:53 +0000655 case OMPRTL__kmpc_master: {
656 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
657 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
658 llvm::FunctionType *FnTy =
659 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
660 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
661 break;
662 }
663 case OMPRTL__kmpc_end_master: {
664 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
665 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
666 llvm::FunctionType *FnTy =
667 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
668 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
669 break;
670 }
Alexey Bataev9f797f32015-02-05 05:57:51 +0000671 case OMPRTL__kmpc_omp_taskyield: {
672 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
673 // int end_part);
674 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
675 llvm::FunctionType *FnTy =
676 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
677 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
678 break;
679 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +0000680 case OMPRTL__kmpc_single: {
681 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
682 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
683 llvm::FunctionType *FnTy =
684 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
685 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
686 break;
687 }
688 case OMPRTL__kmpc_end_single: {
689 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
690 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
691 llvm::FunctionType *FnTy =
692 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
693 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
694 break;
695 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000696 case OMPRTL__kmpc_omp_task_alloc: {
697 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
698 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
699 // kmp_routine_entry_t *task_entry);
700 assert(KmpRoutineEntryPtrTy != nullptr &&
701 "Type kmp_routine_entry_t must be created.");
702 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
703 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
704 // Return void * and then cast to particular kmp_task_t type.
705 llvm::FunctionType *FnTy =
706 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
707 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
708 break;
709 }
710 case OMPRTL__kmpc_omp_task: {
711 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
712 // *new_task);
713 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
714 CGM.VoidPtrTy};
715 llvm::FunctionType *FnTy =
716 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
717 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
718 break;
719 }
Alexey Bataeva63048e2015-03-23 06:18:07 +0000720 case OMPRTL__kmpc_copyprivate: {
721 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +0000722 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +0000723 // kmp_int32 didit);
724 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
725 auto *CpyFnTy =
726 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +0000727 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +0000728 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
729 CGM.Int32Ty};
730 llvm::FunctionType *FnTy =
731 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
732 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
733 break;
734 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +0000735 case OMPRTL__kmpc_reduce: {
736 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
737 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
738 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
739 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
740 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
741 /*isVarArg=*/false);
742 llvm::Type *TypeParams[] = {
743 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
744 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
745 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
746 llvm::FunctionType *FnTy =
747 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
748 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
749 break;
750 }
751 case OMPRTL__kmpc_reduce_nowait: {
752 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
753 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
754 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
755 // *lck);
756 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
757 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
758 /*isVarArg=*/false);
759 llvm::Type *TypeParams[] = {
760 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
761 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
762 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
763 llvm::FunctionType *FnTy =
764 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
765 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
766 break;
767 }
768 case OMPRTL__kmpc_end_reduce: {
769 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
770 // kmp_critical_name *lck);
771 llvm::Type *TypeParams[] = {
772 getIdentTyPointerTy(), CGM.Int32Ty,
773 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
774 llvm::FunctionType *FnTy =
775 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
776 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
777 break;
778 }
779 case OMPRTL__kmpc_end_reduce_nowait: {
780 // Build __kmpc_end_reduce_nowait(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 =
788 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
789 break;
790 }
Alexey Bataev1d677132015-04-22 13:57:31 +0000791 case OMPRTL__kmpc_omp_task_begin_if0: {
792 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
793 // *new_task);
794 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
795 CGM.VoidPtrTy};
796 llvm::FunctionType *FnTy =
797 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
798 RTLFn =
799 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
800 break;
801 }
802 case OMPRTL__kmpc_omp_task_complete_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 = CGM.CreateRuntimeFunction(FnTy,
810 /*Name=*/"__kmpc_omp_task_complete_if0");
811 break;
812 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000813 case OMPRTL__kmpc_ordered: {
814 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
815 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
816 llvm::FunctionType *FnTy =
817 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
818 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
819 break;
820 }
821 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +0000822 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000823 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
824 llvm::FunctionType *FnTy =
825 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
826 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
827 break;
828 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +0000829 case OMPRTL__kmpc_omp_taskwait: {
830 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
831 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
832 llvm::FunctionType *FnTy =
833 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
834 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
835 break;
836 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +0000837 case OMPRTL__kmpc_taskgroup: {
838 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
839 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
840 llvm::FunctionType *FnTy =
841 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
842 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
843 break;
844 }
845 case OMPRTL__kmpc_end_taskgroup: {
846 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
847 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
848 llvm::FunctionType *FnTy =
849 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
850 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
851 break;
852 }
Alexey Bataev7f210c62015-06-18 13:40:03 +0000853 case OMPRTL__kmpc_push_proc_bind: {
854 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
855 // int proc_bind)
856 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
857 llvm::FunctionType *FnTy =
858 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
859 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
860 break;
861 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +0000862 case OMPRTL__kmpc_omp_task_with_deps: {
863 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
864 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
865 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
866 llvm::Type *TypeParams[] = {
867 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
868 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
869 llvm::FunctionType *FnTy =
870 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
871 RTLFn =
872 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
873 break;
874 }
875 case OMPRTL__kmpc_omp_wait_deps: {
876 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
877 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
878 // kmp_depend_info_t *noalias_dep_list);
879 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
880 CGM.Int32Ty, CGM.VoidPtrTy,
881 CGM.Int32Ty, CGM.VoidPtrTy};
882 llvm::FunctionType *FnTy =
883 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
884 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
885 break;
886 }
Alexey Bataev0f34da12015-07-02 04:17:07 +0000887 case OMPRTL__kmpc_cancellationpoint: {
888 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
889 // global_tid, kmp_int32 cncl_kind)
890 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
891 llvm::FunctionType *FnTy =
892 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
893 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
894 break;
895 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +0000896 case OMPRTL__kmpc_cancel: {
897 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
898 // kmp_int32 cncl_kind)
899 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
900 llvm::FunctionType *FnTy =
901 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
902 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
903 break;
904 }
Samuel Antaobed3c462015-10-02 16:14:20 +0000905 case OMPRTL__tgt_target: {
906 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
907 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
908 // *arg_types);
909 llvm::Type *TypeParams[] = {CGM.Int32Ty,
910 CGM.VoidPtrTy,
911 CGM.Int32Ty,
912 CGM.VoidPtrPtrTy,
913 CGM.VoidPtrPtrTy,
914 CGM.SizeTy->getPointerTo(),
915 CGM.Int32Ty->getPointerTo()};
916 llvm::FunctionType *FnTy =
917 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
918 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
919 break;
920 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000921 }
922 return RTLFn;
923}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000924
Alexey Bataevf24e7b12015-10-08 09:10:53 +0000925static llvm::Value *getTypeSize(CodeGenFunction &CGF, QualType Ty) {
926 auto &C = CGF.getContext();
927 llvm::Value *Size = nullptr;
928 auto SizeInChars = C.getTypeSizeInChars(Ty);
929 if (SizeInChars.isZero()) {
930 // getTypeSizeInChars() returns 0 for a VLA.
931 while (auto *VAT = C.getAsVariableArrayType(Ty)) {
932 llvm::Value *ArraySize;
933 std::tie(ArraySize, Ty) = CGF.getVLASize(VAT);
934 Size = Size ? CGF.Builder.CreateNUWMul(Size, ArraySize) : ArraySize;
935 }
936 SizeInChars = C.getTypeSizeInChars(Ty);
937 assert(!SizeInChars.isZero());
938 Size = CGF.Builder.CreateNUWMul(
939 Size, llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity()));
940 } else
941 Size = llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity());
942 return Size;
943}
944
Alexander Musman21212e42015-03-13 10:38:23 +0000945llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
946 bool IVSigned) {
947 assert((IVSize == 32 || IVSize == 64) &&
948 "IV size is not compatible with the omp runtime");
949 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
950 : "__kmpc_for_static_init_4u")
951 : (IVSigned ? "__kmpc_for_static_init_8"
952 : "__kmpc_for_static_init_8u");
953 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
954 auto PtrTy = llvm::PointerType::getUnqual(ITy);
955 llvm::Type *TypeParams[] = {
956 getIdentTyPointerTy(), // loc
957 CGM.Int32Ty, // tid
958 CGM.Int32Ty, // schedtype
959 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
960 PtrTy, // p_lower
961 PtrTy, // p_upper
962 PtrTy, // p_stride
963 ITy, // incr
964 ITy // chunk
965 };
966 llvm::FunctionType *FnTy =
967 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
968 return CGM.CreateRuntimeFunction(FnTy, Name);
969}
970
Alexander Musman92bdaab2015-03-12 13:37:50 +0000971llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
972 bool IVSigned) {
973 assert((IVSize == 32 || IVSize == 64) &&
974 "IV size is not compatible with the omp runtime");
975 auto Name =
976 IVSize == 32
977 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
978 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
979 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
980 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
981 CGM.Int32Ty, // tid
982 CGM.Int32Ty, // schedtype
983 ITy, // lower
984 ITy, // upper
985 ITy, // stride
986 ITy // chunk
987 };
988 llvm::FunctionType *FnTy =
989 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
990 return CGM.CreateRuntimeFunction(FnTy, Name);
991}
992
Alexey Bataev98eb6e32015-04-22 11:15:40 +0000993llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
994 bool IVSigned) {
995 assert((IVSize == 32 || IVSize == 64) &&
996 "IV size is not compatible with the omp runtime");
997 auto Name =
998 IVSize == 32
999 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1000 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1001 llvm::Type *TypeParams[] = {
1002 getIdentTyPointerTy(), // loc
1003 CGM.Int32Ty, // tid
1004 };
1005 llvm::FunctionType *FnTy =
1006 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1007 return CGM.CreateRuntimeFunction(FnTy, Name);
1008}
1009
Alexander Musman92bdaab2015-03-12 13:37:50 +00001010llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
1011 bool IVSigned) {
1012 assert((IVSize == 32 || IVSize == 64) &&
1013 "IV size is not compatible with the omp runtime");
1014 auto Name =
1015 IVSize == 32
1016 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1017 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1018 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1019 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1020 llvm::Type *TypeParams[] = {
1021 getIdentTyPointerTy(), // loc
1022 CGM.Int32Ty, // tid
1023 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1024 PtrTy, // p_lower
1025 PtrTy, // p_upper
1026 PtrTy // p_stride
1027 };
1028 llvm::FunctionType *FnTy =
1029 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1030 return CGM.CreateRuntimeFunction(FnTy, Name);
1031}
1032
Alexey Bataev97720002014-11-11 04:05:39 +00001033llvm::Constant *
1034CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001035 assert(!CGM.getLangOpts().OpenMPUseTLS ||
1036 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00001037 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001038 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001039 Twine(CGM.getMangledName(VD)) + ".cache.");
1040}
1041
John McCall7f416cc2015-09-08 08:05:57 +00001042Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1043 const VarDecl *VD,
1044 Address VDAddr,
1045 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001046 if (CGM.getLangOpts().OpenMPUseTLS &&
1047 CGM.getContext().getTargetInfo().isTLSSupported())
1048 return VDAddr;
1049
John McCall7f416cc2015-09-08 08:05:57 +00001050 auto VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001051 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001052 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1053 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001054 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1055 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00001056 return Address(CGF.EmitRuntimeCall(
1057 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
1058 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00001059}
1060
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001061void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00001062 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00001063 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1064 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1065 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001066 auto OMPLoc = emitUpdateLocation(CGF, Loc);
1067 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00001068 OMPLoc);
1069 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1070 // to register constructor/destructor for variable.
1071 llvm::Value *Args[] = {OMPLoc,
John McCall7f416cc2015-09-08 08:05:57 +00001072 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1073 CGM.VoidPtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001074 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001075 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001076 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001077}
1078
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001079llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00001080 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00001081 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001082 if (CGM.getLangOpts().OpenMPUseTLS &&
1083 CGM.getContext().getTargetInfo().isTLSSupported())
1084 return nullptr;
1085
Alexey Bataev97720002014-11-11 04:05:39 +00001086 VD = VD->getDefinition(CGM.getContext());
1087 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
1088 ThreadPrivateWithDefinition.insert(VD);
1089 QualType ASTTy = VD->getType();
1090
1091 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1092 auto Init = VD->getAnyInitializer();
1093 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1094 // Generate function that re-emits the declaration's initializer into the
1095 // threadprivate copy of the variable VD
1096 CodeGenFunction CtorCGF(CGM);
1097 FunctionArgList Args;
1098 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1099 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1100 Args.push_back(&Dst);
1101
1102 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1103 CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(),
1104 /*isVariadic=*/false);
1105 auto FTy = CGM.getTypes().GetFunctionType(FI);
1106 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001107 FTy, ".__kmpc_global_ctor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001108 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1109 Args, SourceLocation());
1110 auto ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001111 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001112 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00001113 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1114 Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
1115 CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00001116 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1117 /*IsInitializer=*/true);
1118 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001119 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001120 CGM.getContext().VoidPtrTy, Dst.getLocation());
1121 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1122 CtorCGF.FinishFunction();
1123 Ctor = Fn;
1124 }
1125 if (VD->getType().isDestructedType() != QualType::DK_none) {
1126 // Generate function that emits destructor call for the threadprivate copy
1127 // of the variable VD
1128 CodeGenFunction DtorCGF(CGM);
1129 FunctionArgList Args;
1130 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1131 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1132 Args.push_back(&Dst);
1133
1134 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1135 CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(),
1136 /*isVariadic=*/false);
1137 auto FTy = CGM.getTypes().GetFunctionType(FI);
1138 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001139 FTy, ".__kmpc_global_dtor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001140 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1141 SourceLocation());
1142 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1143 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00001144 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1145 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001146 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1147 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1148 DtorCGF.FinishFunction();
1149 Dtor = Fn;
1150 }
1151 // Do not emit init function if it is not required.
1152 if (!Ctor && !Dtor)
1153 return nullptr;
1154
1155 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1156 auto CopyCtorTy =
1157 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1158 /*isVarArg=*/false)->getPointerTo();
1159 // Copying constructor for the threadprivate variable.
1160 // Must be NULL - reserved by runtime, but currently it requires that this
1161 // parameter is always NULL. Otherwise it fires assertion.
1162 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1163 if (Ctor == nullptr) {
1164 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1165 /*isVarArg=*/false)->getPointerTo();
1166 Ctor = llvm::Constant::getNullValue(CtorTy);
1167 }
1168 if (Dtor == nullptr) {
1169 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1170 /*isVarArg=*/false)->getPointerTo();
1171 Dtor = llvm::Constant::getNullValue(DtorTy);
1172 }
1173 if (!CGF) {
1174 auto InitFunctionTy =
1175 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1176 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001177 InitFunctionTy, ".__omp_threadprivate_init_.",
1178 CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00001179 CodeGenFunction InitCGF(CGM);
1180 FunctionArgList ArgList;
1181 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1182 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1183 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001184 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001185 InitCGF.FinishFunction();
1186 return InitFunction;
1187 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001188 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001189 }
1190 return nullptr;
1191}
1192
Alexey Bataev1d677132015-04-22 13:57:31 +00001193/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1194/// function. Here is the logic:
1195/// if (Cond) {
1196/// ThenGen();
1197/// } else {
1198/// ElseGen();
1199/// }
1200static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1201 const RegionCodeGenTy &ThenGen,
1202 const RegionCodeGenTy &ElseGen) {
1203 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1204
1205 // If the condition constant folds and can be elided, try to avoid emitting
1206 // the condition and the dead arm of the if/else.
1207 bool CondConstant;
1208 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
1209 CodeGenFunction::RunCleanupsScope Scope(CGF);
1210 if (CondConstant) {
1211 ThenGen(CGF);
1212 } else {
1213 ElseGen(CGF);
1214 }
1215 return;
1216 }
1217
1218 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1219 // emit the conditional branch.
1220 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1221 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1222 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1223 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1224
1225 // Emit the 'then' code.
1226 CGF.EmitBlock(ThenBlock);
1227 {
1228 CodeGenFunction::RunCleanupsScope ThenScope(CGF);
1229 ThenGen(CGF);
1230 }
1231 CGF.EmitBranch(ContBlock);
1232 // Emit the 'else' code if present.
1233 {
1234 // There is no need to emit line number for unconditional branch.
1235 auto NL = ApplyDebugLocation::CreateEmpty(CGF);
1236 CGF.EmitBlock(ElseBlock);
1237 }
1238 {
1239 CodeGenFunction::RunCleanupsScope ThenScope(CGF);
1240 ElseGen(CGF);
1241 }
1242 {
1243 // There is no need to emit line number for unconditional branch.
1244 auto NL = ApplyDebugLocation::CreateEmpty(CGF);
1245 CGF.EmitBranch(ContBlock);
1246 }
1247 // Emit the continuation block for code after the if.
1248 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001249}
1250
Alexey Bataev1d677132015-04-22 13:57:31 +00001251void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1252 llvm::Value *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001253 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00001254 const Expr *IfCond) {
1255 auto *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001256 auto &&ThenGen = [this, OutlinedFn, CapturedVars,
1257 RTLoc](CodeGenFunction &CGF) {
1258 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
1259 llvm::Value *Args[] = {
1260 RTLoc,
1261 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
1262 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
1263 llvm::SmallVector<llvm::Value *, 16> RealArgs;
1264 RealArgs.append(std::begin(Args), std::end(Args));
1265 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1266
1267 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
1268 CGF.EmitRuntimeCall(RTLFn, RealArgs);
1269 };
1270 auto &&ElseGen = [this, OutlinedFn, CapturedVars, RTLoc,
1271 Loc](CodeGenFunction &CGF) {
Alexey Bataev1d677132015-04-22 13:57:31 +00001272 auto ThreadID = getThreadID(CGF, Loc);
1273 // Build calls:
1274 // __kmpc_serialized_parallel(&Loc, GTid);
1275 llvm::Value *Args[] = {RTLoc, ThreadID};
1276 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel),
1277 Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001278
Alexey Bataev1d677132015-04-22 13:57:31 +00001279 // OutlinedFn(&GTid, &zero, CapturedStruct);
1280 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00001281 Address ZeroAddr =
1282 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
1283 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00001284 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00001285 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
1286 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
1287 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1288 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev1d677132015-04-22 13:57:31 +00001289 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001290
Alexey Bataev1d677132015-04-22 13:57:31 +00001291 // __kmpc_end_serialized_parallel(&Loc, GTid);
1292 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID};
1293 CGF.EmitRuntimeCall(
1294 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs);
1295 };
1296 if (IfCond) {
1297 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
1298 } else {
1299 CodeGenFunction::RunCleanupsScope Scope(CGF);
1300 ThenGen(CGF);
1301 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001302}
1303
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001304// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001305// thread-ID variable (it is passed in a first argument of the outlined function
1306// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1307// regular serial code region, get thread ID by calling kmp_int32
1308// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1309// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00001310Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
1311 SourceLocation Loc) {
Alexey Bataevd74d0602014-10-13 06:02:40 +00001312 if (auto OMPRegionInfo =
1313 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001314 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001315 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001316
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001317 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001318 auto Int32Ty =
1319 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1320 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1321 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00001322 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00001323
1324 return ThreadIDTemp;
1325}
1326
Alexey Bataev97720002014-11-11 04:05:39 +00001327llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001328CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001329 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001330 SmallString<256> Buffer;
1331 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001332 Out << Name;
1333 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001334 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1335 if (Elem.second) {
1336 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001337 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001338 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001339 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001340
David Blaikie13156b62014-11-19 03:06:06 +00001341 return Elem.second = new llvm::GlobalVariable(
1342 CGM.getModule(), Ty, /*IsConstant*/ false,
1343 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1344 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001345}
1346
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001347llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001348 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001349 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001350}
1351
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001352namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00001353template <size_t N> class CallEndCleanup final : public EHScopeStack::Cleanup {
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001354 llvm::Value *Callee;
Alexey Bataeva744ff52015-05-05 09:24:37 +00001355 llvm::Value *Args[N];
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001356
1357public:
Alexey Bataeva744ff52015-05-05 09:24:37 +00001358 CallEndCleanup(llvm::Value *Callee, ArrayRef<llvm::Value *> CleanupArgs)
1359 : Callee(Callee) {
1360 assert(CleanupArgs.size() == N);
1361 std::copy(CleanupArgs.begin(), CleanupArgs.end(), std::begin(Args));
1362 }
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001363 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
1364 CGF.EmitRuntimeCall(Callee, Args);
1365 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001366};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001367} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001368
1369void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1370 StringRef CriticalName,
1371 const RegionCodeGenTy &CriticalOpGen,
1372 SourceLocation Loc) {
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001373 // __kmpc_critical(ident_t *, gtid, Lock);
1374 // CriticalOpGen();
1375 // __kmpc_end_critical(ident_t *, gtid, Lock);
1376 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001377 {
1378 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001379 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1380 getCriticalRegionLock(CriticalName)};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001381 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001382 // Build a call to __kmpc_end_critical
Alexey Bataeva744ff52015-05-05 09:24:37 +00001383 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001384 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
1385 llvm::makeArrayRef(Args));
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001386 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001387 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001388}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001389
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001390static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001391 OpenMPDirectiveKind Kind, SourceLocation Loc,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001392 const RegionCodeGenTy &BodyOpGen) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001393 llvm::Value *CallBool = CGF.EmitScalarConversion(
1394 IfCond,
1395 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001396 CGF.getContext().BoolTy, Loc);
Alexey Bataev8d690652014-12-04 07:23:53 +00001397
1398 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1399 auto *ContBlock = CGF.createBasicBlock("omp_if.end");
1400 // Generate the branch (If-stmt)
1401 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1402 CGF.EmitBlock(ThenBlock);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001403 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen);
Alexey Bataev8d690652014-12-04 07:23:53 +00001404 // Emit the rest of bblocks/branches
1405 CGF.EmitBranch(ContBlock);
1406 CGF.EmitBlock(ContBlock, true);
1407}
1408
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001409void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001410 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001411 SourceLocation Loc) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001412 // if(__kmpc_master(ident_t *, gtid)) {
1413 // MasterOpGen();
1414 // __kmpc_end_master(ident_t *, gtid);
1415 // }
1416 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001417 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001418 auto *IsMaster =
1419 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
Alexey Bataeva744ff52015-05-05 09:24:37 +00001420 typedef CallEndCleanup<std::extent<decltype(Args)>::value>
1421 MasterCallEndCleanup;
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001422 emitIfStmt(
1423 CGF, IsMaster, OMPD_master, Loc, [&](CodeGenFunction &CGF) -> void {
1424 CodeGenFunction::RunCleanupsScope Scope(CGF);
1425 CGF.EHStack.pushCleanup<MasterCallEndCleanup>(
1426 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
1427 llvm::makeArrayRef(Args));
1428 MasterOpGen(CGF);
1429 });
Alexey Bataev8d690652014-12-04 07:23:53 +00001430}
1431
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001432void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
1433 SourceLocation Loc) {
Alexey Bataev9f797f32015-02-05 05:57:51 +00001434 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
1435 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001436 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00001437 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001438 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev9f797f32015-02-05 05:57:51 +00001439}
1440
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001441void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
1442 const RegionCodeGenTy &TaskgroupOpGen,
1443 SourceLocation Loc) {
1444 // __kmpc_taskgroup(ident_t *, gtid);
1445 // TaskgroupOpGen();
1446 // __kmpc_end_taskgroup(ident_t *, gtid);
1447 // Prepare arguments and build a call to __kmpc_taskgroup
1448 {
1449 CodeGenFunction::RunCleanupsScope Scope(CGF);
1450 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1451 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args);
1452 // Build a call to __kmpc_end_taskgroup
1453 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
1454 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
1455 llvm::makeArrayRef(Args));
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001456 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001457 }
1458}
1459
John McCall7f416cc2015-09-08 08:05:57 +00001460/// Given an array of pointers to variables, project the address of a
1461/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001462static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
1463 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00001464 // Pull out the pointer to the variable.
1465 Address PtrAddr =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001466 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00001467 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
1468
1469 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001470 Addr = CGF.Builder.CreateElementBitCast(
1471 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00001472 return Addr;
1473}
1474
Alexey Bataeva63048e2015-03-23 06:18:07 +00001475static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00001476 CodeGenModule &CGM, llvm::Type *ArgsType,
1477 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
1478 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00001479 auto &C = CGM.getContext();
1480 // void copy_func(void *LHSArg, void *RHSArg);
1481 FunctionArgList Args;
1482 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1483 C.VoidPtrTy);
1484 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1485 C.VoidPtrTy);
1486 Args.push_back(&LHSArg);
1487 Args.push_back(&RHSArg);
1488 FunctionType::ExtInfo EI;
1489 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1490 C.VoidTy, Args, EI, /*isVariadic=*/false);
1491 auto *Fn = llvm::Function::Create(
1492 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
1493 ".omp.copyprivate.copy_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00001494 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001495 CodeGenFunction CGF(CGM);
1496 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00001497 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001498 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00001499 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1500 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
1501 ArgsType), CGF.getPointerAlign());
1502 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1503 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
1504 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00001505 // *(Type0*)Dst[0] = *(Type0*)Src[0];
1506 // *(Type1*)Dst[1] = *(Type1*)Src[1];
1507 // ...
1508 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00001509 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00001510 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
1511 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
1512
1513 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
1514 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
1515
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001516 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
1517 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00001518 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001519 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001520 CGF.FinishFunction();
1521 return Fn;
1522}
1523
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001524void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001525 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001526 SourceLocation Loc,
1527 ArrayRef<const Expr *> CopyprivateVars,
1528 ArrayRef<const Expr *> SrcExprs,
1529 ArrayRef<const Expr *> DstExprs,
1530 ArrayRef<const Expr *> AssignmentOps) {
1531 assert(CopyprivateVars.size() == SrcExprs.size() &&
1532 CopyprivateVars.size() == DstExprs.size() &&
1533 CopyprivateVars.size() == AssignmentOps.size());
1534 auto &C = CGM.getContext();
1535 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001536 // if(__kmpc_single(ident_t *, gtid)) {
1537 // SingleOpGen();
1538 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001539 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001540 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001541 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1542 // <copy_func>, did_it);
1543
John McCall7f416cc2015-09-08 08:05:57 +00001544 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00001545 if (!CopyprivateVars.empty()) {
1546 // int32 did_it = 0;
1547 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1548 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00001549 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001550 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001551 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001552 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001553 auto *IsSingle =
1554 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
Alexey Bataeva744ff52015-05-05 09:24:37 +00001555 typedef CallEndCleanup<std::extent<decltype(Args)>::value>
1556 SingleCallEndCleanup;
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001557 emitIfStmt(
1558 CGF, IsSingle, OMPD_single, Loc, [&](CodeGenFunction &CGF) -> void {
1559 CodeGenFunction::RunCleanupsScope Scope(CGF);
1560 CGF.EHStack.pushCleanup<SingleCallEndCleanup>(
1561 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
1562 llvm::makeArrayRef(Args));
1563 SingleOpGen(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00001564 if (DidIt.isValid()) {
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001565 // did_it = 1;
John McCall7f416cc2015-09-08 08:05:57 +00001566 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001567 }
1568 });
Alexey Bataeva63048e2015-03-23 06:18:07 +00001569 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1570 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00001571 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00001572 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
1573 auto CopyprivateArrayTy =
1574 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
1575 /*IndexTypeQuals=*/0);
1576 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00001577 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00001578 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
1579 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00001580 Address Elem = CGF.Builder.CreateConstArrayGEP(
1581 CopyprivateList, I, CGF.getPointerSize());
1582 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00001583 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00001584 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
1585 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001586 }
1587 // Build function that copies private values from single region to all other
1588 // threads in the corresponding parallel region.
1589 auto *CpyFn = emitCopyprivateCopyFunction(
1590 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00001591 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001592 auto *BufSize = getTypeSize(CGF, CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00001593 Address CL =
1594 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
1595 CGF.VoidPtrTy);
1596 auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001597 llvm::Value *Args[] = {
1598 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
1599 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00001600 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00001601 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00001602 CpyFn, // void (*) (void *, void *) <copy_func>
1603 DidItVal // i32 did_it
1604 };
1605 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
1606 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001607}
1608
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001609void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
1610 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00001611 SourceLocation Loc, bool IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001612 // __kmpc_ordered(ident_t *, gtid);
1613 // OrderedOpGen();
1614 // __kmpc_end_ordered(ident_t *, gtid);
1615 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00001616 CodeGenFunction::RunCleanupsScope Scope(CGF);
1617 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001618 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1619 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_ordered), Args);
1620 // Build a call to __kmpc_end_ordered
Alexey Bataeva744ff52015-05-05 09:24:37 +00001621 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001622 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered),
1623 llvm::makeArrayRef(Args));
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001624 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00001625 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001626}
1627
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001628void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev25e5b442015-09-15 12:52:43 +00001629 OpenMPDirectiveKind Kind, bool EmitChecks,
1630 bool ForceSimpleCall) {
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001631 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001632 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataevf2685682015-03-30 04:30:22 +00001633 OpenMPLocationFlags Flags = OMP_IDENT_KMPC;
1634 if (Kind == OMPD_for) {
1635 Flags =
1636 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_FOR);
1637 } else if (Kind == OMPD_sections) {
1638 Flags = static_cast<OpenMPLocationFlags>(Flags |
1639 OMP_IDENT_BARRIER_IMPL_SECTIONS);
1640 } else if (Kind == OMPD_single) {
1641 Flags =
1642 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_SINGLE);
1643 } else if (Kind == OMPD_barrier) {
1644 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_EXPL);
1645 } else {
1646 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL);
1647 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001648 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
1649 // thread_id);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001650 auto *OMPRegionInfo =
1651 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
1652 // Do not emit barrier call in the single directive emitted in some rare cases
1653 // for sections directives.
1654 if (OMPRegionInfo && OMPRegionInfo->getDirectiveKind() == OMPD_single)
1655 return;
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001656 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
1657 getThreadID(CGF, Loc)};
Alexey Bataev25e5b442015-09-15 12:52:43 +00001658 if (OMPRegionInfo) {
1659 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001660 auto *Result = CGF.EmitRuntimeCall(
1661 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001662 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001663 // if (__kmpc_cancel_barrier()) {
1664 // exit from construct;
1665 // }
1666 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
1667 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
1668 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
1669 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
1670 CGF.EmitBlock(ExitBB);
1671 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00001672 auto CancelDestination =
1673 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001674 CGF.EmitBranchThroughCleanup(CancelDestination);
1675 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
1676 }
1677 return;
1678 }
1679 }
1680 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001681}
1682
Alexander Musmanc6388682014-12-15 07:07:06 +00001683/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
1684/// the enum sched_type in kmp.h).
1685enum OpenMPSchedType {
1686 /// \brief Lower bound for default (unordered) versions.
1687 OMP_sch_lower = 32,
1688 OMP_sch_static_chunked = 33,
1689 OMP_sch_static = 34,
1690 OMP_sch_dynamic_chunked = 35,
1691 OMP_sch_guided_chunked = 36,
1692 OMP_sch_runtime = 37,
1693 OMP_sch_auto = 38,
1694 /// \brief Lower bound for 'ordered' versions.
1695 OMP_ord_lower = 64,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001696 OMP_ord_static_chunked = 65,
1697 OMP_ord_static = 66,
1698 OMP_ord_dynamic_chunked = 67,
1699 OMP_ord_guided_chunked = 68,
1700 OMP_ord_runtime = 69,
1701 OMP_ord_auto = 70,
1702 OMP_sch_default = OMP_sch_static,
Alexander Musmanc6388682014-12-15 07:07:06 +00001703};
1704
1705/// \brief Map the OpenMP loop schedule to the runtime enumeration.
1706static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001707 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001708 switch (ScheduleKind) {
1709 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001710 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
1711 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00001712 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001713 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00001714 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001715 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00001716 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001717 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
1718 case OMPC_SCHEDULE_auto:
1719 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00001720 case OMPC_SCHEDULE_unknown:
1721 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001722 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00001723 }
1724 llvm_unreachable("Unexpected runtime schedule");
1725}
1726
1727bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
1728 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001729 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00001730 return Schedule == OMP_sch_static;
1731}
1732
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001733bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001734 auto Schedule =
1735 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001736 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
1737 return Schedule != OMP_sch_static;
1738}
1739
John McCall7f416cc2015-09-08 08:05:57 +00001740void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
1741 SourceLocation Loc,
1742 OpenMPScheduleClauseKind ScheduleKind,
1743 unsigned IVSize, bool IVSigned,
1744 bool Ordered, llvm::Value *UB,
1745 llvm::Value *Chunk) {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001746 OpenMPSchedType Schedule =
1747 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00001748 assert(Ordered ||
1749 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
1750 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
1751 // Call __kmpc_dispatch_init(
1752 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
1753 // kmp_int[32|64] lower, kmp_int[32|64] upper,
1754 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00001755
John McCall7f416cc2015-09-08 08:05:57 +00001756 // If the Chunk was not specified in the clause - use default value 1.
1757 if (Chunk == nullptr)
1758 Chunk = CGF.Builder.getIntN(IVSize, 1);
1759 llvm::Value *Args[] = {
1760 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1761 getThreadID(CGF, Loc),
1762 CGF.Builder.getInt32(Schedule), // Schedule type
1763 CGF.Builder.getIntN(IVSize, 0), // Lower
1764 UB, // Upper
1765 CGF.Builder.getIntN(IVSize, 1), // Stride
1766 Chunk // Chunk
1767 };
1768 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
1769}
1770
1771void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
1772 SourceLocation Loc,
1773 OpenMPScheduleClauseKind ScheduleKind,
1774 unsigned IVSize, bool IVSigned,
1775 bool Ordered, Address IL, Address LB,
1776 Address UB, Address ST,
1777 llvm::Value *Chunk) {
1778 OpenMPSchedType Schedule =
1779 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
1780 assert(!Ordered);
1781 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
1782 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked);
1783
1784 // Call __kmpc_for_static_init(
1785 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
1786 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
1787 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
1788 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
1789 if (Chunk == nullptr) {
1790 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static) &&
1791 "expected static non-chunked schedule");
Alexander Musman92bdaab2015-03-12 13:37:50 +00001792 // If the Chunk was not specified in the clause - use default value 1.
Alexander Musman92bdaab2015-03-12 13:37:50 +00001793 Chunk = CGF.Builder.getIntN(IVSize, 1);
Alexander Musman92bdaab2015-03-12 13:37:50 +00001794 } else {
John McCall7f416cc2015-09-08 08:05:57 +00001795 assert((Schedule == OMP_sch_static_chunked ||
1796 Schedule == OMP_ord_static_chunked) &&
1797 "expected static chunked schedule");
Alexander Musman92bdaab2015-03-12 13:37:50 +00001798 }
John McCall7f416cc2015-09-08 08:05:57 +00001799 llvm::Value *Args[] = {
1800 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1801 getThreadID(CGF, Loc),
1802 CGF.Builder.getInt32(Schedule), // Schedule type
1803 IL.getPointer(), // &isLastIter
1804 LB.getPointer(), // &LB
1805 UB.getPointer(), // &UB
1806 ST.getPointer(), // &Stride
1807 CGF.Builder.getIntN(IVSize, 1), // Incr
1808 Chunk // Chunk
1809 };
1810 CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00001811}
1812
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001813void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
1814 SourceLocation Loc) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001815 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001816 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1817 getThreadID(CGF, Loc)};
1818 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
1819 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00001820}
1821
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00001822void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
1823 SourceLocation Loc,
1824 unsigned IVSize,
1825 bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001826 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
1827 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1828 getThreadID(CGF, Loc)};
1829 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
1830}
1831
Alexander Musman92bdaab2015-03-12 13:37:50 +00001832llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
1833 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00001834 bool IVSigned, Address IL,
1835 Address LB, Address UB,
1836 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00001837 // Call __kmpc_dispatch_next(
1838 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
1839 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
1840 // kmp_int[32|64] *p_stride);
1841 llvm::Value *Args[] = {
1842 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001843 IL.getPointer(), // &isLastIter
1844 LB.getPointer(), // &Lower
1845 UB.getPointer(), // &Upper
1846 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00001847 };
1848 llvm::Value *Call =
1849 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
1850 return CGF.EmitScalarConversion(
1851 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00001852 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00001853}
1854
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001855void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
1856 llvm::Value *NumThreads,
1857 SourceLocation Loc) {
Alexey Bataevb2059782014-10-13 08:23:51 +00001858 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
1859 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001860 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00001861 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001862 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
1863 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00001864}
1865
Alexey Bataev7f210c62015-06-18 13:40:03 +00001866void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
1867 OpenMPProcBindClauseKind ProcBind,
1868 SourceLocation Loc) {
1869 // Constants for proc bind value accepted by the runtime.
1870 enum ProcBindTy {
1871 ProcBindFalse = 0,
1872 ProcBindTrue,
1873 ProcBindMaster,
1874 ProcBindClose,
1875 ProcBindSpread,
1876 ProcBindIntel,
1877 ProcBindDefault
1878 } RuntimeProcBind;
1879 switch (ProcBind) {
1880 case OMPC_PROC_BIND_master:
1881 RuntimeProcBind = ProcBindMaster;
1882 break;
1883 case OMPC_PROC_BIND_close:
1884 RuntimeProcBind = ProcBindClose;
1885 break;
1886 case OMPC_PROC_BIND_spread:
1887 RuntimeProcBind = ProcBindSpread;
1888 break;
1889 case OMPC_PROC_BIND_unknown:
1890 llvm_unreachable("Unsupported proc_bind value.");
1891 }
1892 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
1893 llvm::Value *Args[] = {
1894 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1895 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
1896 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
1897}
1898
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001899void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
1900 SourceLocation Loc) {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001901 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001902 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
1903 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001904}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001905
Alexey Bataev62b63b12015-03-10 07:28:44 +00001906namespace {
1907/// \brief Indexes of fields for type kmp_task_t.
1908enum KmpTaskTFields {
1909 /// \brief List of shared variables.
1910 KmpTaskTShareds,
1911 /// \brief Task routine.
1912 KmpTaskTRoutine,
1913 /// \brief Partition id for the untied tasks.
1914 KmpTaskTPartId,
1915 /// \brief Function with call of destructors for private variables.
1916 KmpTaskTDestructors,
1917};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001918} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00001919
1920void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
1921 if (!KmpRoutineEntryPtrTy) {
1922 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
1923 auto &C = CGM.getContext();
1924 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
1925 FunctionProtoType::ExtProtoInfo EPI;
1926 KmpRoutineEntryPtrQTy = C.getPointerType(
1927 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
1928 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
1929 }
1930}
1931
Alexey Bataevc71a4092015-09-11 10:29:41 +00001932static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1933 QualType FieldTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001934 auto *Field = FieldDecl::Create(
1935 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1936 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1937 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1938 Field->setAccess(AS_public);
1939 DC->addDecl(Field);
Alexey Bataevc71a4092015-09-11 10:29:41 +00001940 return Field;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001941}
1942
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001943namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00001944struct PrivateHelpersTy {
1945 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
1946 const VarDecl *PrivateElemInit)
1947 : Original(Original), PrivateCopy(PrivateCopy),
1948 PrivateElemInit(PrivateElemInit) {}
1949 const VarDecl *Original;
1950 const VarDecl *PrivateCopy;
1951 const VarDecl *PrivateElemInit;
1952};
1953typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00001954} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001955
Alexey Bataev9e034042015-05-05 04:05:12 +00001956static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00001957createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001958 if (!Privates.empty()) {
1959 auto &C = CGM.getContext();
1960 // Build struct .kmp_privates_t. {
1961 // /* private vars */
1962 // };
1963 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
1964 RD->startDefinition();
1965 for (auto &&Pair : Privates) {
Alexey Bataevc71a4092015-09-11 10:29:41 +00001966 auto *VD = Pair.second.Original;
1967 auto Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00001968 Type = Type.getNonReferenceType();
Alexey Bataevc71a4092015-09-11 10:29:41 +00001969 auto *FD = addFieldToRecordDecl(C, RD, Type);
1970 if (VD->hasAttrs()) {
1971 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
1972 E(VD->getAttrs().end());
1973 I != E; ++I)
1974 FD->addAttr(*I);
1975 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001976 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00001977 RD->completeDefinition();
1978 return RD;
1979 }
1980 return nullptr;
1981}
1982
Alexey Bataev9e034042015-05-05 04:05:12 +00001983static RecordDecl *
1984createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001985 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001986 auto &C = CGM.getContext();
1987 // Build struct kmp_task_t {
1988 // void * shareds;
1989 // kmp_routine_entry_t routine;
1990 // kmp_int32 part_id;
1991 // kmp_routine_entry_t destructors;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001992 // };
1993 auto *RD = C.buildImplicitRecord("kmp_task_t");
1994 RD->startDefinition();
1995 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1996 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
1997 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1998 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00001999 RD->completeDefinition();
2000 return RD;
2001}
2002
2003static RecordDecl *
2004createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00002005 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002006 auto &C = CGM.getContext();
2007 // Build struct kmp_task_t_with_privates {
2008 // kmp_task_t task_data;
2009 // .kmp_privates_t. privates;
2010 // };
2011 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
2012 RD->startDefinition();
2013 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002014 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
2015 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
2016 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002017 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002018 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002019}
2020
2021/// \brief Emit a proxy function which accepts kmp_task_t as the second
2022/// argument.
2023/// \code
2024/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002025/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map,
2026/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002027/// return 0;
2028/// }
2029/// \endcode
2030static llvm::Value *
2031emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002032 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
2033 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002034 QualType SharedsPtrTy, llvm::Value *TaskFunction,
2035 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002036 auto &C = CGM.getContext();
2037 FunctionArgList Args;
2038 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
2039 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002040 /*Id=*/nullptr,
2041 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002042 Args.push_back(&GtidArg);
2043 Args.push_back(&TaskTypeArg);
2044 FunctionType::ExtInfo Info;
2045 auto &TaskEntryFnInfo =
2046 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
2047 /*isVariadic=*/false);
2048 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
2049 auto *TaskEntry =
2050 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
2051 ".omp_task_entry.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002052 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002053 CodeGenFunction CGF(CGM);
2054 CGF.disableDebugInfo();
2055 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
2056
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002057 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
2058 // tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002059 auto *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002060 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev2377fe92015-09-10 08:12:02 +00002061 LValue TDBase = emitLoadOfPointerLValue(
2062 CGF, CGF.GetAddrOfLocalVar(&TaskTypeArg), KmpTaskTWithPrivatesPtrQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002063 auto *KmpTaskTWithPrivatesQTyRD =
2064 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002065 LValue Base =
2066 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002067 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
2068 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
2069 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
2070 auto *PartidParam = CGF.EmitLoadOfLValue(PartIdLVal, Loc).getScalarVal();
2071
2072 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
2073 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002074 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002075 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002076 CGF.ConvertTypeForMem(SharedsPtrTy));
2077
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002078 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
2079 llvm::Value *PrivatesParam;
2080 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
2081 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
2082 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002083 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002084 } else {
2085 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2086 }
2087
2088 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam,
2089 TaskPrivatesMap, SharedsParam};
Alexey Bataev62b63b12015-03-10 07:28:44 +00002090 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
2091 CGF.EmitStoreThroughLValue(
2092 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
John McCall7f416cc2015-09-08 08:05:57 +00002093 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00002094 CGF.FinishFunction();
2095 return TaskEntry;
2096}
2097
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002098static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
2099 SourceLocation Loc,
2100 QualType KmpInt32Ty,
2101 QualType KmpTaskTWithPrivatesPtrQTy,
2102 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002103 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002104 FunctionArgList Args;
2105 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
2106 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002107 /*Id=*/nullptr,
2108 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002109 Args.push_back(&GtidArg);
2110 Args.push_back(&TaskTypeArg);
2111 FunctionType::ExtInfo Info;
2112 auto &DestructorFnInfo =
2113 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
2114 /*isVariadic=*/false);
2115 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
2116 auto *DestructorFn =
2117 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
2118 ".omp_task_destructor.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002119 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
2120 DestructorFnInfo);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002121 CodeGenFunction CGF(CGM);
2122 CGF.disableDebugInfo();
2123 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
2124 Args);
2125
Alexey Bataev2377fe92015-09-10 08:12:02 +00002126 LValue Base = emitLoadOfPointerLValue(
2127 CGF, CGF.GetAddrOfLocalVar(&TaskTypeArg), KmpTaskTWithPrivatesPtrQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002128 auto *KmpTaskTWithPrivatesQTyRD =
2129 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
2130 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002131 Base = CGF.EmitLValueForField(Base, *FI);
2132 for (auto *Field :
2133 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
2134 if (auto DtorKind = Field->getType().isDestructedType()) {
2135 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
2136 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
2137 }
2138 }
2139 CGF.FinishFunction();
2140 return DestructorFn;
2141}
2142
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002143/// \brief Emit a privates mapping function for correct handling of private and
2144/// firstprivate variables.
2145/// \code
2146/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
2147/// **noalias priv1,..., <tyn> **noalias privn) {
2148/// *priv1 = &.privates.priv1;
2149/// ...;
2150/// *privn = &.privates.privn;
2151/// }
2152/// \endcode
2153static llvm::Value *
2154emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00002155 ArrayRef<const Expr *> PrivateVars,
2156 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002157 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00002158 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002159 auto &C = CGM.getContext();
2160 FunctionArgList Args;
2161 ImplicitParamDecl TaskPrivatesArg(
2162 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
2163 C.getPointerType(PrivatesQTy).withConst().withRestrict());
2164 Args.push_back(&TaskPrivatesArg);
2165 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
2166 unsigned Counter = 1;
2167 for (auto *E: PrivateVars) {
2168 Args.push_back(ImplicitParamDecl::Create(
2169 C, /*DC=*/nullptr, Loc,
2170 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
2171 .withConst()
2172 .withRestrict()));
2173 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2174 PrivateVarsPos[VD] = Counter;
2175 ++Counter;
2176 }
2177 for (auto *E : FirstprivateVars) {
2178 Args.push_back(ImplicitParamDecl::Create(
2179 C, /*DC=*/nullptr, Loc,
2180 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
2181 .withConst()
2182 .withRestrict()));
2183 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2184 PrivateVarsPos[VD] = Counter;
2185 ++Counter;
2186 }
2187 FunctionType::ExtInfo Info;
2188 auto &TaskPrivatesMapFnInfo =
2189 CGM.getTypes().arrangeFreeFunctionDeclaration(C.VoidTy, Args, Info,
2190 /*isVariadic=*/false);
2191 auto *TaskPrivatesMapTy =
2192 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
2193 auto *TaskPrivatesMap = llvm::Function::Create(
2194 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
2195 ".omp_task_privates_map.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002196 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
2197 TaskPrivatesMapFnInfo);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00002198 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002199 CodeGenFunction CGF(CGM);
2200 CGF.disableDebugInfo();
2201 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
2202 TaskPrivatesMapFnInfo, Args);
2203
2204 // *privi = &.privates.privi;
Alexey Bataev2377fe92015-09-10 08:12:02 +00002205 LValue Base = emitLoadOfPointerLValue(
2206 CGF, CGF.GetAddrOfLocalVar(&TaskPrivatesArg), TaskPrivatesArg.getType());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002207 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
2208 Counter = 0;
2209 for (auto *Field : PrivatesQTyRD->fields()) {
2210 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
2211 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
John McCall7f416cc2015-09-08 08:05:57 +00002212 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
Alexey Bataev2377fe92015-09-10 08:12:02 +00002213 auto RefLoadLVal =
2214 emitLoadOfPointerLValue(CGF, RefLVal.getAddress(), RefLVal.getType());
2215 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002216 ++Counter;
2217 }
2218 CGF.FinishFunction();
2219 return TaskPrivatesMap;
2220}
2221
Alexey Bataev9e034042015-05-05 04:05:12 +00002222static int array_pod_sort_comparator(const PrivateDataTy *P1,
2223 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002224 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
2225}
2226
2227void CGOpenMPRuntime::emitTaskCall(
2228 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
2229 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
John McCall7f416cc2015-09-08 08:05:57 +00002230 llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002231 const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
2232 ArrayRef<const Expr *> PrivateCopies,
2233 ArrayRef<const Expr *> FirstprivateVars,
2234 ArrayRef<const Expr *> FirstprivateCopies,
2235 ArrayRef<const Expr *> FirstprivateInits,
2236 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002237 auto &C = CGM.getContext();
Alexey Bataev9e034042015-05-05 04:05:12 +00002238 llvm::SmallVector<PrivateDataTy, 8> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002239 // Aggregate privates and sort them by the alignment.
Alexey Bataev9e034042015-05-05 04:05:12 +00002240 auto I = PrivateCopies.begin();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002241 for (auto *E : PrivateVars) {
2242 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2243 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00002244 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00002245 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
2246 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002247 ++I;
2248 }
Alexey Bataev9e034042015-05-05 04:05:12 +00002249 I = FirstprivateCopies.begin();
2250 auto IElemInitRef = FirstprivateInits.begin();
2251 for (auto *E : FirstprivateVars) {
2252 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2253 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00002254 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00002255 PrivateHelpersTy(
2256 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
2257 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
2258 ++I, ++IElemInitRef;
2259 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002260 llvm::array_pod_sort(Privates.begin(), Privates.end(),
2261 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002262 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2263 // Build type kmp_routine_entry_t (if not built yet).
2264 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002265 // Build type kmp_task_t (if not built yet).
2266 if (KmpTaskTQTy.isNull()) {
2267 KmpTaskTQTy = C.getRecordType(
2268 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
2269 }
2270 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002271 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002272 auto *KmpTaskTWithPrivatesQTyRD =
2273 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
2274 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
2275 QualType KmpTaskTWithPrivatesPtrQTy =
2276 C.getPointerType(KmpTaskTWithPrivatesQTy);
2277 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
2278 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002279 auto *KmpTaskTWithPrivatesTySize = getTypeSize(CGF, KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002280 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
2281
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002282 // Emit initial values for private copies (if any).
2283 llvm::Value *TaskPrivatesMap = nullptr;
2284 auto *TaskPrivatesMapTy =
2285 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
2286 3)
2287 ->getType();
2288 if (!Privates.empty()) {
2289 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
2290 TaskPrivatesMap = emitTaskPrivateMappingFunction(
2291 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
2292 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2293 TaskPrivatesMap, TaskPrivatesMapTy);
2294 } else {
2295 TaskPrivatesMap = llvm::ConstantPointerNull::get(
2296 cast<llvm::PointerType>(TaskPrivatesMapTy));
2297 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002298 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
2299 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002300 auto *TaskEntry = emitProxyTaskFunction(
2301 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002302 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00002303
2304 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
2305 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2306 // kmp_routine_entry_t *task_entry);
2307 // Task flags. Format is taken from
2308 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
2309 // description of kmp_tasking_flags struct.
2310 const unsigned TiedFlag = 0x1;
2311 const unsigned FinalFlag = 0x2;
2312 unsigned Flags = Tied ? TiedFlag : 0;
2313 auto *TaskFlags =
2314 Final.getPointer()
2315 ? CGF.Builder.CreateSelect(Final.getPointer(),
2316 CGF.Builder.getInt32(FinalFlag),
2317 CGF.Builder.getInt32(/*C=*/0))
2318 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
2319 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataev40e36f12015-11-24 13:01:44 +00002320 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002321 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
2322 getThreadID(CGF, Loc), TaskFlags,
2323 KmpTaskTWithPrivatesTySize, SharedsSize,
2324 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2325 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00002326 auto *NewTask = CGF.EmitRuntimeCall(
2327 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002328 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2329 NewTask, KmpTaskTWithPrivatesPtrTy);
2330 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
2331 KmpTaskTWithPrivatesQTy);
2332 LValue TDBase =
2333 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00002334 // Fill the data in the resulting kmp_task_t record.
2335 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00002336 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002337 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00002338 KmpTaskSharedsPtr =
2339 Address(CGF.EmitLoadOfScalar(
2340 CGF.EmitLValueForField(
2341 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
2342 KmpTaskTShareds)),
2343 Loc),
2344 CGF.getNaturalTypeAlignment(SharedsTy));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002345 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002346 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002347 // Emit initial values for private copies (if any).
2348 bool NeedsCleanup = false;
2349 if (!Privates.empty()) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002350 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
2351 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002352 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002353 LValue SharedsBase;
2354 if (!FirstprivateVars.empty()) {
John McCall7f416cc2015-09-08 08:05:57 +00002355 SharedsBase = CGF.MakeAddrLValue(
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002356 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2357 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
2358 SharedsTy);
2359 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002360 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
2361 cast<CapturedStmt>(*D.getAssociatedStmt()));
2362 for (auto &&Pair : Privates) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002363 auto *VD = Pair.second.PrivateCopy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002364 auto *Init = VD->getAnyInitializer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002365 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002366 if (Init) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002367 if (auto *Elem = Pair.second.PrivateElemInit) {
2368 auto *OriginalVD = Pair.second.Original;
2369 auto *SharedField = CapturesInfo.lookup(OriginalVD);
2370 auto SharedRefLValue =
2371 CGF.EmitLValueForField(SharedsBase, SharedField);
Alexey Bataevc71a4092015-09-11 10:29:41 +00002372 SharedRefLValue = CGF.MakeAddrLValue(
2373 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
2374 SharedRefLValue.getType(), AlignmentSource::Decl);
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002375 QualType Type = OriginalVD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002376 if (Type->isArrayType()) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002377 // Initialize firstprivate array.
2378 if (!isa<CXXConstructExpr>(Init) ||
2379 CGF.isTrivialInitializer(Init)) {
2380 // Perform simple memcpy.
2381 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002382 SharedRefLValue.getAddress(), Type);
Alexey Bataev9e034042015-05-05 04:05:12 +00002383 } else {
2384 // Initialize firstprivate array using element-by-element
2385 // intialization.
2386 CGF.EmitOMPAggregateAssign(
2387 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002388 Type, [&CGF, Elem, Init, &CapturesInfo](
John McCall7f416cc2015-09-08 08:05:57 +00002389 Address DestElement, Address SrcElement) {
Alexey Bataev9e034042015-05-05 04:05:12 +00002390 // Clean up any temporaries needed by the initialization.
2391 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00002392 InitScope.addPrivate(Elem, [SrcElement]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00002393 return SrcElement;
2394 });
2395 (void)InitScope.Privatize();
2396 // Emit initialization for single element.
Alexey Bataevd157d472015-06-24 03:35:38 +00002397 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
2398 CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00002399 CGF.EmitAnyExprToMem(Init, DestElement,
2400 Init->getType().getQualifiers(),
2401 /*IsInitializer=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00002402 });
2403 }
2404 } else {
2405 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00002406 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00002407 return SharedRefLValue.getAddress();
2408 });
2409 (void)InitScope.Privatize();
Alexey Bataevd157d472015-06-24 03:35:38 +00002410 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00002411 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
2412 /*capturedByInit=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00002413 }
2414 } else {
2415 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
2416 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002417 }
2418 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00002419 ++FI;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002420 }
2421 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002422 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002423 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00002424 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
2425 KmpTaskTWithPrivatesPtrQTy,
2426 KmpTaskTWithPrivatesQTy)
2427 : llvm::ConstantPointerNull::get(
2428 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
2429 LValue Destructor = CGF.EmitLValueForField(
2430 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
2431 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2432 DestructorFn, KmpRoutineEntryPtrTy),
2433 Destructor);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002434
2435 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00002436 Address DependenciesArray = Address::invalid();
2437 unsigned NumDependencies = Dependences.size();
2438 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002439 // Dependence kind for RTL.
Alexey Bataev92e82f92015-11-23 13:33:42 +00002440 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002441 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
2442 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002443 QualType FlagsTy =
2444 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002445 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
2446 if (KmpDependInfoTy.isNull()) {
2447 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
2448 KmpDependInfoRD->startDefinition();
2449 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
2450 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
2451 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
2452 KmpDependInfoRD->completeDefinition();
2453 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
2454 } else {
2455 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
2456 }
John McCall7f416cc2015-09-08 08:05:57 +00002457 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002458 // Define type kmp_depend_info[<Dependences.size()>];
2459 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00002460 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002461 ArrayType::Normal, /*IndexTypeQuals=*/0);
2462 // kmp_depend_info[<Dependences.size()>] deps;
John McCall7f416cc2015-09-08 08:05:57 +00002463 DependenciesArray = CGF.CreateMemTemp(KmpDependInfoArrayTy);
2464 for (unsigned i = 0; i < NumDependencies; ++i) {
2465 const Expr *E = Dependences[i].second;
2466 auto Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002467 llvm::Value *Size;
2468 QualType Ty = E->getType();
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002469 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
2470 LValue UpAddrLVal =
2471 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
2472 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00002473 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002474 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00002475 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002476 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
2477 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002478 } else
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00002479 Size = getTypeSize(CGF, Ty);
John McCall7f416cc2015-09-08 08:05:57 +00002480 auto Base = CGF.MakeAddrLValue(
2481 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002482 KmpDependInfoTy);
2483 // deps[i].base_addr = &<Dependences[i].second>;
2484 auto BaseAddrLVal = CGF.EmitLValueForField(
2485 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00002486 CGF.EmitStoreOfScalar(
2487 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
2488 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002489 // deps[i].len = sizeof(<Dependences[i].second>);
2490 auto LenLVal = CGF.EmitLValueForField(
2491 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
2492 CGF.EmitStoreOfScalar(Size, LenLVal);
2493 // deps[i].flags = <Dependences[i].first>;
2494 RTLDependenceKindTy DepKind;
2495 switch (Dependences[i].first) {
2496 case OMPC_DEPEND_in:
2497 DepKind = DepIn;
2498 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00002499 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002500 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002501 case OMPC_DEPEND_inout:
2502 DepKind = DepInOut;
2503 break;
2504 case OMPC_DEPEND_unknown:
2505 llvm_unreachable("Unknown task dependence type");
2506 }
2507 auto FlagsLVal = CGF.EmitLValueForField(
2508 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
2509 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
2510 FlagsLVal);
2511 }
John McCall7f416cc2015-09-08 08:05:57 +00002512 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2513 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002514 CGF.VoidPtrTy);
2515 }
2516
Alexey Bataev62b63b12015-03-10 07:28:44 +00002517 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
2518 // libcall.
2519 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2520 // *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002521 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2522 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2523 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
2524 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00002525 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002526 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00002527 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
2528 llvm::Value *DepTaskArgs[7];
2529 if (NumDependencies) {
2530 DepTaskArgs[0] = UpLoc;
2531 DepTaskArgs[1] = ThreadID;
2532 DepTaskArgs[2] = NewTask;
2533 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
2534 DepTaskArgs[4] = DependenciesArray.getPointer();
2535 DepTaskArgs[5] = CGF.Builder.getInt32(0);
2536 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2537 }
2538 auto &&ThenCodeGen = [this, NumDependencies,
2539 &TaskArgs, &DepTaskArgs](CodeGenFunction &CGF) {
2540 // TODO: add check for untied tasks.
2541 if (NumDependencies) {
2542 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps),
2543 DepTaskArgs);
2544 } else {
2545 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
2546 TaskArgs);
2547 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002548 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00002549 typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value>
2550 IfCallEndCleanup;
John McCall7f416cc2015-09-08 08:05:57 +00002551
2552 llvm::Value *DepWaitTaskArgs[6];
2553 if (NumDependencies) {
2554 DepWaitTaskArgs[0] = UpLoc;
2555 DepWaitTaskArgs[1] = ThreadID;
2556 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
2557 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
2558 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
2559 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
2560 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002561 auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
John McCall7f416cc2015-09-08 08:05:57 +00002562 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002563 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
2564 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2565 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
2566 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
2567 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00002568 if (NumDependencies)
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002569 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
2570 DepWaitTaskArgs);
2571 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
2572 // kmp_task_t *new_task);
2573 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0),
2574 TaskArgs);
2575 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
2576 // kmp_task_t *new_task);
2577 CGF.EHStack.pushCleanup<IfCallEndCleanup>(
2578 NormalAndEHCleanup,
2579 createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0),
2580 llvm::makeArrayRef(TaskArgs));
Alexey Bataev1d677132015-04-22 13:57:31 +00002581
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002582 // Call proxy_task_entry(gtid, new_task);
2583 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
2584 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
2585 };
John McCall7f416cc2015-09-08 08:05:57 +00002586
Alexey Bataev1d677132015-04-22 13:57:31 +00002587 if (IfCond) {
2588 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
2589 } else {
2590 CodeGenFunction::RunCleanupsScope Scope(CGF);
2591 ThenCodeGen(CGF);
2592 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002593}
2594
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002595/// \brief Emit reduction operation for each element of array (required for
2596/// array sections) LHS op = RHS.
2597/// \param Type Type of array.
2598/// \param LHSVar Variable on the left side of the reduction operation
2599/// (references element of array in original variable).
2600/// \param RHSVar Variable on the right side of the reduction operation
2601/// (references element of array in original variable).
2602/// \param RedOpGen Generator of reduction operation with use of LHSVar and
2603/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00002604static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002605 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
2606 const VarDecl *RHSVar,
2607 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
2608 const Expr *, const Expr *)> &RedOpGen,
2609 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
2610 const Expr *UpExpr = nullptr) {
2611 // Perform element-by-element initialization.
2612 QualType ElementTy;
2613 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
2614 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
2615
2616 // Drill down to the base element type on both arrays.
2617 auto ArrayTy = Type->getAsArrayTypeUnsafe();
2618 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
2619
2620 auto RHSBegin = RHSAddr.getPointer();
2621 auto LHSBegin = LHSAddr.getPointer();
2622 // Cast from pointer to array type to pointer to single element.
2623 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
2624 // The basic structure here is a while-do loop.
2625 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
2626 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
2627 auto IsEmpty =
2628 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
2629 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
2630
2631 // Enter the loop body, making that address the current address.
2632 auto EntryBB = CGF.Builder.GetInsertBlock();
2633 CGF.EmitBlock(BodyBB);
2634
2635 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
2636
2637 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
2638 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
2639 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
2640 Address RHSElementCurrent =
2641 Address(RHSElementPHI,
2642 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
2643
2644 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
2645 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
2646 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
2647 Address LHSElementCurrent =
2648 Address(LHSElementPHI,
2649 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
2650
2651 // Emit copy.
2652 CodeGenFunction::OMPPrivateScope Scope(CGF);
2653 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
2654 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
2655 Scope.Privatize();
2656 RedOpGen(CGF, XExpr, EExpr, UpExpr);
2657 Scope.ForceCleanup();
2658
2659 // Shift the address forward by one element.
2660 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
2661 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
2662 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
2663 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
2664 // Check whether we've reached the end.
2665 auto Done =
2666 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
2667 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
2668 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
2669 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
2670
2671 // Done.
2672 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
2673}
2674
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002675static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
2676 llvm::Type *ArgsType,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002677 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002678 ArrayRef<const Expr *> LHSExprs,
2679 ArrayRef<const Expr *> RHSExprs,
2680 ArrayRef<const Expr *> ReductionOps) {
2681 auto &C = CGM.getContext();
2682
2683 // void reduction_func(void *LHSArg, void *RHSArg);
2684 FunctionArgList Args;
2685 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2686 C.VoidPtrTy);
2687 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2688 C.VoidPtrTy);
2689 Args.push_back(&LHSArg);
2690 Args.push_back(&RHSArg);
2691 FunctionType::ExtInfo EI;
2692 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
2693 C.VoidTy, Args, EI, /*isVariadic=*/false);
2694 auto *Fn = llvm::Function::Create(
2695 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
2696 ".omp.reduction.reduction_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002697 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002698 CodeGenFunction CGF(CGM);
2699 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
2700
2701 // Dst = (void*[n])(LHSArg);
2702 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00002703 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2704 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2705 ArgsType), CGF.getPointerAlign());
2706 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2707 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2708 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002709
2710 // ...
2711 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
2712 // ...
2713 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002714 auto IPriv = Privates.begin();
2715 unsigned Idx = 0;
2716 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00002717 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
2718 Scope.addPrivate(RHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002719 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00002720 });
2721 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
2722 Scope.addPrivate(LHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002723 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00002724 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002725 QualType PrivTy = (*IPriv)->getType();
2726 if (PrivTy->isArrayType()) {
2727 // Get array size and emit VLA type.
2728 ++Idx;
2729 Address Elem =
2730 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
2731 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
2732 CodeGenFunction::OpaqueValueMapping OpaqueMap(
2733 CGF,
2734 cast<OpaqueValueExpr>(
2735 CGF.getContext().getAsVariableArrayType(PrivTy)->getSizeExpr()),
2736 RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
2737 CGF.EmitVariablyModifiedType(PrivTy);
2738 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002739 }
2740 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002741 IPriv = Privates.begin();
2742 auto ILHS = LHSExprs.begin();
2743 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002744 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002745 if ((*IPriv)->getType()->isArrayType()) {
2746 // Emit reduction for array section.
2747 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
2748 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
2749 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
2750 [=](CodeGenFunction &CGF, const Expr *,
2751 const Expr *,
2752 const Expr *) { CGF.EmitIgnoredExpr(E); });
2753 } else
2754 // Emit reduction for array subscript or single variable.
2755 CGF.EmitIgnoredExpr(E);
2756 ++IPriv, ++ILHS, ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002757 }
2758 Scope.ForceCleanup();
2759 CGF.FinishFunction();
2760 return Fn;
2761}
2762
2763void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002764 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002765 ArrayRef<const Expr *> LHSExprs,
2766 ArrayRef<const Expr *> RHSExprs,
2767 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002768 bool WithNowait, bool SimpleReduction) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002769 // Next code should be emitted for reduction:
2770 //
2771 // static kmp_critical_name lock = { 0 };
2772 //
2773 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
2774 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
2775 // ...
2776 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
2777 // *(Type<n>-1*)rhs[<n>-1]);
2778 // }
2779 //
2780 // ...
2781 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
2782 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2783 // RedList, reduce_func, &<lock>)) {
2784 // case 1:
2785 // ...
2786 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2787 // ...
2788 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2789 // break;
2790 // case 2:
2791 // ...
2792 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2793 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00002794 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002795 // break;
2796 // default:;
2797 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002798 //
2799 // if SimpleReduction is true, only the next code is generated:
2800 // ...
2801 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2802 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002803
2804 auto &C = CGM.getContext();
2805
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002806 if (SimpleReduction) {
2807 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002808 auto IPriv = Privates.begin();
2809 auto ILHS = LHSExprs.begin();
2810 auto IRHS = RHSExprs.begin();
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002811 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002812 if ((*IPriv)->getType()->isArrayType()) {
2813 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
2814 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
2815 EmitOMPAggregateReduction(
2816 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
2817 [=](CodeGenFunction &CGF, const Expr *, const Expr *,
2818 const Expr *) { CGF.EmitIgnoredExpr(E); });
2819 } else
2820 CGF.EmitIgnoredExpr(E);
2821 ++IPriv, ++ILHS, ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00002822 }
2823 return;
2824 }
2825
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002826 // 1. Build a list of reduction variables.
2827 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002828 auto Size = RHSExprs.size();
2829 for (auto *E : Privates) {
2830 if (E->getType()->isArrayType())
2831 // Reserve place for array size.
2832 ++Size;
2833 }
2834 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002835 QualType ReductionArrayTy =
2836 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2837 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00002838 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002839 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002840 auto IPriv = Privates.begin();
2841 unsigned Idx = 0;
2842 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00002843 Address Elem =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002844 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00002845 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002846 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002847 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
2848 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002849 if ((*IPriv)->getType()->isArrayType()) {
2850 // Store array size.
2851 ++Idx;
2852 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
2853 CGF.getPointerSize());
2854 CGF.Builder.CreateStore(
2855 CGF.Builder.CreateIntToPtr(
2856 CGF.Builder.CreateIntCast(
2857 CGF.getVLASize(CGF.getContext().getAsVariableArrayType(
2858 (*IPriv)->getType()))
2859 .first,
2860 CGF.SizeTy, /*isSigned=*/false),
2861 CGF.VoidPtrTy),
2862 Elem);
2863 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002864 }
2865
2866 // 2. Emit reduce_func().
2867 auto *ReductionFn = emitReductionFunction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002868 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
2869 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002870
2871 // 3. Create static kmp_critical_name lock = { 0 };
2872 auto *Lock = getCriticalRegionLock(".reduction");
2873
2874 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
2875 // RedList, reduce_func, &<lock>);
2876 auto *IdentTLoc = emitUpdateLocation(
2877 CGF, Loc,
2878 static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE));
2879 auto *ThreadId = getThreadID(CGF, Loc);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002880 auto *ReductionArrayTySize = getTypeSize(CGF, ReductionArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00002881 auto *RL =
2882 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
2883 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002884 llvm::Value *Args[] = {
2885 IdentTLoc, // ident_t *<loc>
2886 ThreadId, // i32 <gtid>
2887 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
2888 ReductionArrayTySize, // size_type sizeof(RedList)
2889 RL, // void *RedList
2890 ReductionFn, // void (*) (void *, void *) <reduce_func>
2891 Lock // kmp_critical_name *&<lock>
2892 };
2893 auto Res = CGF.EmitRuntimeCall(
2894 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
2895 : OMPRTL__kmpc_reduce),
2896 Args);
2897
2898 // 5. Build switch(res)
2899 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
2900 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
2901
2902 // 6. Build case 1:
2903 // ...
2904 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
2905 // ...
2906 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2907 // break;
2908 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
2909 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
2910 CGF.EmitBlock(Case1BB);
2911
2912 {
2913 CodeGenFunction::RunCleanupsScope Scope(CGF);
2914 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
2915 llvm::Value *EndArgs[] = {
2916 IdentTLoc, // ident_t *<loc>
2917 ThreadId, // i32 <gtid>
2918 Lock // kmp_critical_name *&<lock>
2919 };
Alexey Bataeva744ff52015-05-05 09:24:37 +00002920 CGF.EHStack
2921 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
2922 NormalAndEHCleanup,
2923 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
2924 : OMPRTL__kmpc_end_reduce),
2925 llvm::makeArrayRef(EndArgs));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002926 auto IPriv = Privates.begin();
2927 auto ILHS = LHSExprs.begin();
2928 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002929 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002930 if ((*IPriv)->getType()->isArrayType()) {
2931 // Emit reduction for array section.
2932 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
2933 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
2934 EmitOMPAggregateReduction(
2935 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
2936 [=](CodeGenFunction &CGF, const Expr *, const Expr *,
2937 const Expr *) { CGF.EmitIgnoredExpr(E); });
2938 } else
2939 // Emit reduction for array subscript or single variable.
2940 CGF.EmitIgnoredExpr(E);
2941 ++IPriv, ++ILHS, ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002942 }
2943 }
2944
2945 CGF.EmitBranch(DefaultBB);
2946
2947 // 7. Build case 2:
2948 // ...
2949 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
2950 // ...
2951 // break;
2952 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
2953 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
2954 CGF.EmitBlock(Case2BB);
2955
2956 {
2957 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataev69a47792015-05-07 03:54:03 +00002958 if (!WithNowait) {
2959 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
2960 llvm::Value *EndArgs[] = {
2961 IdentTLoc, // ident_t *<loc>
2962 ThreadId, // i32 <gtid>
2963 Lock // kmp_critical_name *&<lock>
2964 };
2965 CGF.EHStack
2966 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>(
2967 NormalAndEHCleanup,
2968 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
2969 llvm::makeArrayRef(EndArgs));
2970 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002971 auto ILHS = LHSExprs.begin();
2972 auto IRHS = RHSExprs.begin();
2973 auto IPriv = Privates.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002974 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002975 const Expr *XExpr = nullptr;
2976 const Expr *EExpr = nullptr;
2977 const Expr *UpExpr = nullptr;
2978 BinaryOperatorKind BO = BO_Comma;
2979 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
2980 if (BO->getOpcode() == BO_Assign) {
2981 XExpr = BO->getLHS();
2982 UpExpr = BO->getRHS();
2983 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002984 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002985 // Try to emit update expression as a simple atomic.
2986 auto *RHSExpr = UpExpr;
2987 if (RHSExpr) {
2988 // Analyze RHS part of the whole expression.
2989 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
2990 RHSExpr->IgnoreParenImpCasts())) {
2991 // If this is a conditional operator, analyze its condition for
2992 // min/max reduction operator.
2993 RHSExpr = ACO->getCond();
2994 }
2995 if (auto *BORHS =
2996 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
2997 EExpr = BORHS->getRHS();
2998 BO = BORHS->getOpcode();
2999 }
Alexey Bataev69a47792015-05-07 03:54:03 +00003000 }
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003001 if (XExpr) {
3002 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3003 auto &&AtomicRedGen = [this, BO, VD, IPriv,
3004 Loc](CodeGenFunction &CGF, const Expr *XExpr,
3005 const Expr *EExpr, const Expr *UpExpr) {
3006 LValue X = CGF.EmitLValue(XExpr);
3007 RValue E;
3008 if (EExpr)
3009 E = CGF.EmitAnyExpr(EExpr);
3010 CGF.EmitOMPAtomicSimpleUpdateExpr(
3011 X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
3012 [&CGF, UpExpr, VD, IPriv](RValue XRValue) {
3013 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
3014 PrivateScope.addPrivate(VD, [&CGF, VD, XRValue]() -> Address {
John McCall7f416cc2015-09-08 08:05:57 +00003015 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003016 CGF.EmitStoreThroughLValue(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003017 XRValue, CGF.MakeAddrLValue(LHSTemp, VD->getType()));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003018 return LHSTemp;
3019 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003020 (void)PrivateScope.Privatize();
3021 return CGF.EmitAnyExpr(UpExpr);
3022 });
3023 };
3024 if ((*IPriv)->getType()->isArrayType()) {
3025 // Emit atomic reduction for array section.
3026 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3027 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
3028 AtomicRedGen, XExpr, EExpr, UpExpr);
3029 } else
3030 // Emit atomic reduction for array subscript or single variable.
3031 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
3032 } else {
3033 // Emit as a critical region.
3034 auto &&CritRedGen = [this, E, Loc](CodeGenFunction &CGF, const Expr *,
3035 const Expr *, const Expr *) {
3036 emitCriticalRegion(
3037 CGF, ".atomic_reduction",
3038 [E](CodeGenFunction &CGF) { CGF.EmitIgnoredExpr(E); }, Loc);
3039 };
3040 if ((*IPriv)->getType()->isArrayType()) {
3041 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3042 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3043 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3044 CritRedGen);
3045 } else
3046 CritRedGen(CGF, nullptr, nullptr, nullptr);
3047 }
3048 ++ILHS, ++IRHS, ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003049 }
3050 }
3051
3052 CGF.EmitBranch(DefaultBB);
3053 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
3054}
3055
Alexey Bataev8b8e2022015-04-27 05:22:09 +00003056void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
3057 SourceLocation Loc) {
3058 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
3059 // global_tid);
3060 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3061 // Ignore return result until untied tasks are supported.
3062 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
3063}
3064
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003065void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003066 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00003067 const RegionCodeGenTy &CodeGen,
3068 bool HasCancel) {
3069 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003070 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003071}
3072
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003073namespace {
3074enum RTCancelKind {
3075 CancelNoreq = 0,
3076 CancelParallel = 1,
3077 CancelLoop = 2,
3078 CancelSections = 3,
3079 CancelTaskgroup = 4
3080};
3081}
3082
3083static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
3084 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00003085 if (CancelRegion == OMPD_parallel)
3086 CancelKind = CancelParallel;
3087 else if (CancelRegion == OMPD_for)
3088 CancelKind = CancelLoop;
3089 else if (CancelRegion == OMPD_sections)
3090 CancelKind = CancelSections;
3091 else {
3092 assert(CancelRegion == OMPD_taskgroup);
3093 CancelKind = CancelTaskgroup;
3094 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003095 return CancelKind;
3096}
3097
3098void CGOpenMPRuntime::emitCancellationPointCall(
3099 CodeGenFunction &CGF, SourceLocation Loc,
3100 OpenMPDirectiveKind CancelRegion) {
3101 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
3102 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003103 if (auto *OMPRegionInfo =
3104 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003105 if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
3106 return;
3107 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003108 llvm::Value *Args[] = {
3109 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3110 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003111 // Ignore return result until untied tasks are supported.
3112 auto *Result = CGF.EmitRuntimeCall(
3113 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
3114 // if (__kmpc_cancellationpoint()) {
3115 // __kmpc_cancel_barrier();
3116 // exit from construct;
3117 // }
3118 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
3119 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
3120 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
3121 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3122 CGF.EmitBlock(ExitBB);
3123 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00003124 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003125 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00003126 auto CancelDest =
3127 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003128 CGF.EmitBranchThroughCleanup(CancelDest);
3129 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3130 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00003131 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00003132}
3133
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003134void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00003135 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003136 OpenMPDirectiveKind CancelRegion) {
3137 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
3138 // kmp_int32 cncl_kind);
3139 if (auto *OMPRegionInfo =
3140 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003141 if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
3142 return;
Alexey Bataev87933c72015-09-18 08:07:34 +00003143 auto &&ThenGen = [this, Loc, CancelRegion,
3144 OMPRegionInfo](CodeGenFunction &CGF) {
3145 llvm::Value *Args[] = {
3146 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3147 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
3148 // Ignore return result until untied tasks are supported.
3149 auto *Result =
3150 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
3151 // if (__kmpc_cancel()) {
3152 // __kmpc_cancel_barrier();
3153 // exit from construct;
3154 // }
3155 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
3156 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
3157 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
3158 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3159 CGF.EmitBlock(ExitBB);
3160 // __kmpc_cancel_barrier();
3161 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
3162 // exit from construct;
3163 auto CancelDest =
3164 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
3165 CGF.EmitBranchThroughCleanup(CancelDest);
3166 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3167 };
3168 if (IfCond)
3169 emitOMPIfClause(CGF, IfCond, ThenGen, [](CodeGenFunction &) {});
3170 else
3171 ThenGen(CGF);
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00003172 }
3173}
Samuel Antaobed3c462015-10-02 16:14:20 +00003174
3175llvm::Value *
3176CGOpenMPRuntime::emitTargetOutlinedFunction(const OMPExecutableDirective &D,
3177 const RegionCodeGenTy &CodeGen) {
3178 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
3179
3180 CodeGenFunction CGF(CGM, true);
3181 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen);
3182 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
3183 return CGF.GenerateOpenMPCapturedStmtFunction(CS, /*UseOnlyReferences=*/true);
3184}
3185
3186void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
3187 const OMPExecutableDirective &D,
3188 llvm::Value *OutlinedFn,
3189 const Expr *IfCond, const Expr *Device,
3190 ArrayRef<llvm::Value *> CapturedVars) {
3191 /// \brief Values for bit flags used to specify the mapping type for
3192 /// offloading.
3193 enum OpenMPOffloadMappingFlags {
3194 /// \brief Allocate memory on the device and move data from host to device.
3195 OMP_MAP_TO = 0x01,
3196 /// \brief Allocate memory on the device and move data from device to host.
3197 OMP_MAP_FROM = 0x02,
3198 };
3199
3200 enum OpenMPOffloadingReservedDeviceIDs {
3201 /// \brief Device ID if the device was not defined, runtime should get it
3202 /// from environment variables in the spec.
3203 OMP_DEVICEID_UNDEF = -1,
3204 };
3205
3206 // Fill up the arrays with the all the captured variables.
3207 SmallVector<llvm::Value *, 16> BasePointers;
3208 SmallVector<llvm::Value *, 16> Pointers;
3209 SmallVector<llvm::Value *, 16> Sizes;
3210 SmallVector<unsigned, 16> MapTypes;
3211
3212 bool hasVLACaptures = false;
3213
3214 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
3215 auto RI = CS.getCapturedRecordDecl()->field_begin();
3216 // auto II = CS.capture_init_begin();
3217 auto CV = CapturedVars.begin();
3218 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
3219 CE = CS.capture_end();
3220 CI != CE; ++CI, ++RI, ++CV) {
3221 StringRef Name;
3222 QualType Ty;
3223 llvm::Value *BasePointer;
3224 llvm::Value *Pointer;
3225 llvm::Value *Size;
3226 unsigned MapType;
3227
3228 if (CI->capturesVariableArrayType()) {
3229 BasePointer = Pointer = *CV;
3230 Size = getTypeSize(CGF, RI->getType());
3231 hasVLACaptures = true;
3232 // VLA sizes don't need to be copied back from the device.
3233 MapType = OMP_MAP_TO;
3234 } else if (CI->capturesThis()) {
3235 BasePointer = Pointer = *CV;
3236 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr());
3237 Size = getTypeSize(CGF, PtrTy->getPointeeType());
3238 // Default map type.
3239 MapType = OMP_MAP_TO | OMP_MAP_FROM;
3240 } else {
3241 BasePointer = Pointer = *CV;
3242
3243 const ReferenceType *PtrTy =
3244 cast<ReferenceType>(RI->getType().getTypePtr());
3245 QualType ElementType = PtrTy->getPointeeType();
3246 Size = getTypeSize(CGF, ElementType);
3247 // Default map type.
3248 MapType = OMP_MAP_TO | OMP_MAP_FROM;
3249 }
3250
3251 BasePointers.push_back(BasePointer);
3252 Pointers.push_back(Pointer);
3253 Sizes.push_back(Size);
3254 MapTypes.push_back(MapType);
3255 }
3256
3257 // Keep track on whether the host function has to be executed.
3258 auto OffloadErrorQType =
3259 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
3260 auto OffloadError = CGF.MakeAddrLValue(
3261 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
3262 OffloadErrorQType);
3263 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
3264 OffloadError);
3265
3266 // Fill up the pointer arrays and transfer execution to the device.
3267 auto &&ThenGen = [this, &BasePointers, &Pointers, &Sizes, &MapTypes,
3268 hasVLACaptures, Device, OffloadError,
3269 OffloadErrorQType](CodeGenFunction &CGF) {
3270 unsigned PointerNumVal = BasePointers.size();
3271 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal);
3272 llvm::Value *BasePointersArray;
3273 llvm::Value *PointersArray;
3274 llvm::Value *SizesArray;
3275 llvm::Value *MapTypesArray;
3276
3277 if (PointerNumVal) {
3278 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
3279 QualType PointerArrayType = CGF.getContext().getConstantArrayType(
3280 CGF.getContext().VoidPtrTy, PointerNumAP, ArrayType::Normal,
3281 /*IndexTypeQuals=*/0);
3282
3283 BasePointersArray =
3284 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
3285 PointersArray =
3286 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
3287
3288 // If we don't have any VLA types, we can use a constant array for the map
3289 // sizes, otherwise we need to fill up the arrays as we do for the
3290 // pointers.
3291 if (hasVLACaptures) {
3292 QualType SizeArrayType = CGF.getContext().getConstantArrayType(
3293 CGF.getContext().getSizeType(), PointerNumAP, ArrayType::Normal,
3294 /*IndexTypeQuals=*/0);
3295 SizesArray =
3296 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
3297 } else {
3298 // We expect all the sizes to be constant, so we collect them to create
3299 // a constant array.
3300 SmallVector<llvm::Constant *, 16> ConstSizes;
3301 for (auto S : Sizes)
3302 ConstSizes.push_back(cast<llvm::Constant>(S));
3303
3304 auto *SizesArrayInit = llvm::ConstantArray::get(
3305 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
3306 auto *SizesArrayGbl = new llvm::GlobalVariable(
3307 CGM.getModule(), SizesArrayInit->getType(),
3308 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
3309 SizesArrayInit, ".offload_sizes");
3310 SizesArrayGbl->setUnnamedAddr(true);
3311 SizesArray = SizesArrayGbl;
3312 }
3313
3314 // The map types are always constant so we don't need to generate code to
3315 // fill arrays. Instead, we create an array constant.
3316 llvm::Constant *MapTypesArrayInit =
3317 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
3318 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
3319 CGM.getModule(), MapTypesArrayInit->getType(),
3320 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
3321 MapTypesArrayInit, ".offload_maptypes");
3322 MapTypesArrayGbl->setUnnamedAddr(true);
3323 MapTypesArray = MapTypesArrayGbl;
3324
3325 for (unsigned i = 0; i < PointerNumVal; ++i) {
3326 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
3327 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal),
3328 BasePointersArray, 0, i);
3329 Address BPAddr(BP, CGM.getContext().getTypeAlignInChars(
3330 CGM.getContext().VoidPtrTy));
3331 CGF.Builder.CreateStore(
3332 CGF.Builder.CreateBitCast(BasePointers[i], CGM.VoidPtrTy), BPAddr);
3333
3334 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
3335 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
3336 0, i);
3337 Address PAddr(P, CGM.getContext().getTypeAlignInChars(
3338 CGM.getContext().VoidPtrTy));
3339 CGF.Builder.CreateStore(
3340 CGF.Builder.CreateBitCast(Pointers[i], CGM.VoidPtrTy), PAddr);
3341
3342 if (hasVLACaptures) {
3343 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
3344 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
3345 /*Idx0=*/0,
3346 /*Idx1=*/i);
3347 Address SAddr(S, CGM.getContext().getTypeAlignInChars(
3348 CGM.getContext().getSizeType()));
3349 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(
3350 Sizes[i], CGM.SizeTy, /*isSigned=*/true),
3351 SAddr);
3352 }
3353 }
3354
3355 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3356 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), BasePointersArray,
3357 /*Idx0=*/0, /*Idx1=*/0);
3358 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3359 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
3360 /*Idx0=*/0,
3361 /*Idx1=*/0);
3362 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3363 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
3364 /*Idx0=*/0, /*Idx1=*/0);
3365 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
3366 llvm::ArrayType::get(CGM.Int32Ty, PointerNumVal), MapTypesArray,
3367 /*Idx0=*/0,
3368 /*Idx1=*/0);
3369
3370 } else {
3371 BasePointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
3372 PointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
3373 SizesArray = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
3374 MapTypesArray =
3375 llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo());
3376 }
3377
3378 // On top of the arrays that were filled up, the target offloading call
3379 // takes as arguments the device id as well as the host pointer. The host
3380 // pointer is used by the runtime library to identify the current target
3381 // region, so it only has to be unique and not necessarily point to
3382 // anything. It could be the pointer to the outlined function that
3383 // implements the target region, but we aren't using that so that the
3384 // compiler doesn't need to keep that, and could therefore inline the host
3385 // function if proven worthwhile during optimization.
3386
3387 llvm::Value *HostPtr = new llvm::GlobalVariable(
3388 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
3389 llvm::GlobalValue::PrivateLinkage,
3390 llvm::Constant::getNullValue(CGM.Int8Ty), ".offload_hstptr");
3391
3392 // Emit device ID if any.
3393 llvm::Value *DeviceID;
3394 if (Device)
3395 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
3396 CGM.Int32Ty, /*isSigned=*/true);
3397 else
3398 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
3399
3400 llvm::Value *OffloadingArgs[] = {
3401 DeviceID, HostPtr, PointerNum, BasePointersArray,
3402 PointersArray, SizesArray, MapTypesArray};
3403 auto Return = CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target),
3404 OffloadingArgs);
3405
3406 CGF.EmitStoreOfScalar(Return, OffloadError);
3407 };
3408
3409 if (IfCond) {
3410 // Notify that the host version must be executed.
3411 auto &&ElseGen = [this, OffloadError,
3412 OffloadErrorQType](CodeGenFunction &CGF) {
3413 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/-1u),
3414 OffloadError);
3415 };
3416 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
3417 } else {
3418 CodeGenFunction::RunCleanupsScope Scope(CGF);
3419 ThenGen(CGF);
3420 }
3421
3422 // Check the error code and execute the host version if required.
3423 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
3424 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
3425 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
3426 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
3427 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
3428
3429 CGF.EmitBlock(OffloadFailedBlock);
3430 CGF.Builder.CreateCall(OutlinedFn, BasePointers);
3431 CGF.EmitBranch(OffloadContBlock);
3432
3433 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
3434 return;
3435}