blob: dd143147b723f68c54b9d7d331303b379d3ae518 [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides a class for OpenMP runtime code generation.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGOpenMPRuntime.h"
15#include "CodeGenFunction.h"
Alexey Bataev36bf0112015-03-10 05:15:26 +000016#include "CGCleanup.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000017#include "clang/AST/Decl.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000018#include "clang/AST/StmtOpenMP.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000019#include "llvm/ADT/ArrayRef.h"
Alexey Bataevd74d0602014-10-13 06:02:40 +000020#include "llvm/IR/CallSite.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000021#include "llvm/IR/DerivedTypes.h"
22#include "llvm/IR/GlobalValue.h"
23#include "llvm/IR/Value.h"
24#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000025#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000026
27using namespace clang;
28using namespace CodeGen;
29
Benjamin Kramerc52193f2014-10-10 13:57:57 +000030namespace {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000031/// \brief Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000032class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
33public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000034 /// \brief Kinds of OpenMP regions used in codegen.
35 enum CGOpenMPRegionKind {
36 /// \brief Region with outlined function for standalone 'parallel'
37 /// directive.
38 ParallelOutlinedRegion,
39 /// \brief Region with outlined function for standalone 'task' directive.
40 TaskOutlinedRegion,
41 /// \brief Region for constructs that do not require function outlining,
42 /// like 'for', 'sections', 'atomic' etc. directives.
43 InlinedRegion,
44 };
Alexey Bataev18095712014-10-10 12:19:54 +000045
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000046 CGOpenMPRegionInfo(const CapturedStmt &CS,
47 const CGOpenMPRegionKind RegionKind,
48 const RegionCodeGenTy &CodeGen)
49 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
50 CodeGen(CodeGen) {}
51
52 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
53 const RegionCodeGenTy &CodeGen)
54 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind),
55 CodeGen(CodeGen) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000056
57 /// \brief Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000058 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000059 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000060
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000061 /// \brief Emit the captured statement body.
62 virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
63
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000064 /// \brief Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000065 /// \return LValue for thread id variable. This LValue always has type int32*.
66 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000067
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000068 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000069
Alexey Bataev18095712014-10-10 12:19:54 +000070 static bool classof(const CGCapturedStmtInfo *Info) {
71 return Info->getKind() == CR_OpenMP;
72 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000073
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000074protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000075 CGOpenMPRegionKind RegionKind;
76 const RegionCodeGenTy &CodeGen;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000077};
Alexey Bataev18095712014-10-10 12:19:54 +000078
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000079/// \brief API for captured statement code generation in OpenMP constructs.
80class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
81public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000082 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
83 const RegionCodeGenTy &CodeGen)
84 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen),
85 ThreadIDVar(ThreadIDVar) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000086 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
87 }
88 /// \brief Get a variable or parameter for storing global thread id
89 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +000090 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000091
Alexey Bataev18095712014-10-10 12:19:54 +000092 /// \brief Get the name of the capture helper.
Benjamin Kramerc52193f2014-10-10 13:57:57 +000093 StringRef getHelperName() const override { return ".omp_outlined."; }
Alexey Bataev18095712014-10-10 12:19:54 +000094
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000095 static bool classof(const CGCapturedStmtInfo *Info) {
96 return CGOpenMPRegionInfo::classof(Info) &&
97 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
98 ParallelOutlinedRegion;
99 }
100
Alexey Bataev18095712014-10-10 12:19:54 +0000101private:
102 /// \brief A variable or parameter storing global thread id for OpenMP
103 /// constructs.
104 const VarDecl *ThreadIDVar;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000105};
106
Alexey Bataev62b63b12015-03-10 07:28:44 +0000107/// \brief API for captured statement code generation in OpenMP constructs.
108class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo {
109public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000110 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000111 const VarDecl *ThreadIDVar,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000112 const RegionCodeGenTy &CodeGen)
113 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen),
114 ThreadIDVar(ThreadIDVar) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000115 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
116 }
117 /// \brief Get a variable or parameter for storing global thread id
118 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000119 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000120
121 /// \brief Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000122 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000123
Alexey Bataev62b63b12015-03-10 07:28:44 +0000124 /// \brief Get the name of the capture helper.
125 StringRef getHelperName() const override { return ".omp_outlined."; }
126
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000127 static bool classof(const CGCapturedStmtInfo *Info) {
128 return CGOpenMPRegionInfo::classof(Info) &&
129 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
130 TaskOutlinedRegion;
131 }
132
Alexey Bataev62b63b12015-03-10 07:28:44 +0000133private:
134 /// \brief A variable or parameter storing global thread id for OpenMP
135 /// constructs.
136 const VarDecl *ThreadIDVar;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000137};
138
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000139/// \brief API for inlined captured statement code generation in OpenMP
140/// constructs.
141class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
142public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000143 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
144 const RegionCodeGenTy &CodeGen)
145 : CGOpenMPRegionInfo(InlinedRegion, CodeGen), OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000146 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
147 // \brief Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000148 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000149 if (OuterRegionInfo)
150 return OuterRegionInfo->getContextValue();
151 llvm_unreachable("No context value for inlined OpenMP region");
152 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000153 virtual void setContextValue(llvm::Value *V) override {
154 if (OuterRegionInfo) {
155 OuterRegionInfo->setContextValue(V);
156 return;
157 }
158 llvm_unreachable("No context value for inlined OpenMP region");
159 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000160 /// \brief Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000161 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000162 if (OuterRegionInfo)
163 return OuterRegionInfo->lookup(VD);
164 llvm_unreachable("Trying to reference VarDecl that is neither local nor "
165 "captured in outer OpenMP region");
166 }
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000167 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000168 if (OuterRegionInfo)
169 return OuterRegionInfo->getThisFieldDecl();
170 return nullptr;
171 }
172 /// \brief Get a variable or parameter for storing global thread id
173 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000174 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000175 if (OuterRegionInfo)
176 return OuterRegionInfo->getThreadIDVariable();
177 return nullptr;
178 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000179
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000180 /// \brief Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000181 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000182 if (auto *OuterRegionInfo = getOldCSI())
183 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000184 llvm_unreachable("No helper name for inlined OpenMP construct");
185 }
186
187 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
188
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000189 static bool classof(const CGCapturedStmtInfo *Info) {
190 return CGOpenMPRegionInfo::classof(Info) &&
191 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
192 }
193
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000194private:
195 /// \brief CodeGen info about outer OpenMP region.
196 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
197 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000198};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000199
200/// \brief RAII for emitting code of OpenMP constructs.
201class InlinedOpenMPRegionRAII {
202 CodeGenFunction &CGF;
203
204public:
205 /// \brief Constructs region for combined constructs.
206 /// \param CodeGen Code generation sequence for combined directives. Includes
207 /// a list of functions used for code generation of implicitly inlined
208 /// regions.
209 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen)
210 : CGF(CGF) {
211 // Start emission for the construct.
212 CGF.CapturedStmtInfo =
213 new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen);
214 }
215 ~InlinedOpenMPRegionRAII() {
216 // Restore original CapturedStmtInfo only if we're done with code emission.
217 auto *OldCSI =
218 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
219 delete CGF.CapturedStmtInfo;
220 CGF.CapturedStmtInfo = OldCSI;
221 }
222};
223
Benjamin Kramerc52193f2014-10-10 13:57:57 +0000224} // namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000225
226LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
227 return CGF.MakeNaturalAlignAddrLValue(
Alexey Bataev62b63b12015-03-10 07:28:44 +0000228 CGF.Builder.CreateAlignedLoad(
229 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
230 CGF.PointerAlignInBytes),
231 getThreadIDVariable()
232 ->getType()
233 ->castAs<PointerType>()
234 ->getPointeeType());
Alexey Bataev18095712014-10-10 12:19:54 +0000235}
236
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000237void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
238 // 1.2.2 OpenMP Language Terminology
239 // Structured block - An executable statement with a single entry at the
240 // top and a single exit at the bottom.
241 // The point of exit cannot be a branch out of the structured block.
242 // longjmp() and throw() must not violate the entry/exit criteria.
243 CGF.EHStack.pushTerminate();
244 {
245 CodeGenFunction::RunCleanupsScope Scope(CGF);
246 CodeGen(CGF);
247 }
248 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000249}
250
Alexey Bataev62b63b12015-03-10 07:28:44 +0000251LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
252 CodeGenFunction &CGF) {
253 return CGF.MakeNaturalAlignAddrLValue(
254 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
255 getThreadIDVariable()->getType());
256}
257
Alexey Bataev9959db52014-05-06 10:08:46 +0000258CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
Alexey Bataev62b63b12015-03-10 07:28:44 +0000259 : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000260 IdentTy = llvm::StructType::create(
261 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
262 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000263 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000264 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
Alexey Bataev23b69422014-06-18 07:08:49 +0000265 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
266 llvm::PointerType::getUnqual(CGM.Int32Ty)};
Alexey Bataev9959db52014-05-06 10:08:46 +0000267 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000268 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Alexey Bataev9959db52014-05-06 10:08:46 +0000269}
270
Alexey Bataev91797552015-03-18 04:13:55 +0000271void CGOpenMPRuntime::clear() {
272 InternalVars.clear();
273}
274
Alexey Bataev9959db52014-05-06 10:08:46 +0000275llvm::Value *
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000276CGOpenMPRuntime::emitParallelOutlinedFunction(const OMPExecutableDirective &D,
277 const VarDecl *ThreadIDVar,
278 const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000279 assert(ThreadIDVar->getType()->isPointerType() &&
280 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +0000281 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
282 CodeGenFunction CGF(CGM, true);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000283 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen);
Alexey Bataev18095712014-10-10 12:19:54 +0000284 CGF.CapturedStmtInfo = &CGInfo;
285 return CGF.GenerateCapturedStmtFunction(*CS);
286}
287
288llvm::Value *
Alexey Bataev62b63b12015-03-10 07:28:44 +0000289CGOpenMPRuntime::emitTaskOutlinedFunction(const OMPExecutableDirective &D,
290 const VarDecl *ThreadIDVar,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000291 const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000292 assert(!ThreadIDVar->getType()->isPointerType() &&
293 "thread id variable must be of type kmp_int32 for tasks");
294 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
295 CodeGenFunction CGF(CGM, true);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000296 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000297 CGF.CapturedStmtInfo = &CGInfo;
298 return CGF.GenerateCapturedStmtFunction(*CS);
299}
300
301llvm::Value *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000302CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000303 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000304 if (!Entry) {
305 if (!DefaultOpenMPPSource) {
306 // Initialize default location for psource field of ident_t structure of
307 // all ident_t objects. Format is ";file;function;line;column;;".
308 // Taken from
309 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
310 DefaultOpenMPPSource =
311 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;");
312 DefaultOpenMPPSource =
313 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
314 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000315 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
316 CGM.getModule(), IdentTy, /*isConstant*/ true,
317 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000318 DefaultOpenMPLocation->setUnnamedAddr(true);
Alexey Bataev9959db52014-05-06 10:08:46 +0000319
320 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000321 llvm::Constant *Values[] = {Zero,
322 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
323 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000324 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
325 DefaultOpenMPLocation->setInitializer(Init);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000326 OpenMPDefaultLocMap[Flags] = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000327 return DefaultOpenMPLocation;
328 }
329 return Entry;
330}
331
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000332llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
333 SourceLocation Loc,
334 OpenMPLocationFlags Flags) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000335 // If no debug info is generated - return global default location.
336 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
337 Loc.isInvalid())
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000338 return getOrCreateDefaultLocation(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000339
340 assert(CGF.CurFn && "No function in current CodeGenFunction.");
341
Alexey Bataev9959db52014-05-06 10:08:46 +0000342 llvm::Value *LocValue = nullptr;
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000343 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
344 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataev18095712014-10-10 12:19:54 +0000345 LocValue = I->second.DebugLoc;
Alexander Musmanc6388682014-12-15 07:07:06 +0000346 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
347 // GetOpenMPThreadID was called before this routine.
348 if (LocValue == nullptr) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000349 // Generate "ident_t .kmpc_loc.addr;"
350 llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr");
Alexey Bataev9959db52014-05-06 10:08:46 +0000351 AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy));
Alexey Bataev18095712014-10-10 12:19:54 +0000352 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
353 Elem.second.DebugLoc = AI;
Alexey Bataev9959db52014-05-06 10:08:46 +0000354 LocValue = AI;
355
356 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
357 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000358 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataev9959db52014-05-06 10:08:46 +0000359 llvm::ConstantExpr::getSizeOf(IdentTy),
360 CGM.PointerAlignInBytes);
361 }
362
363 // char **psource = &.kmpc_loc_<flags>.addr.psource;
David Blaikie1ed728c2015-04-05 22:45:47 +0000364 auto *PSource = CGF.Builder.CreateConstInBoundsGEP2_32(IdentTy, LocValue, 0,
365 IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000366
Alexey Bataevf002aca2014-05-30 05:48:40 +0000367 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
368 if (OMPDebugLoc == nullptr) {
369 SmallString<128> Buffer2;
370 llvm::raw_svector_ostream OS2(Buffer2);
371 // Build debug location
372 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
373 OS2 << ";" << PLoc.getFilename() << ";";
374 if (const FunctionDecl *FD =
375 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
376 OS2 << FD->getQualifiedNameAsString();
377 }
378 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
379 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
380 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000381 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000382 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000383 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
384
Alexey Bataev9959db52014-05-06 10:08:46 +0000385 return LocValue;
386}
387
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000388llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
389 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000390 assert(CGF.CurFn && "No function in current CodeGenFunction.");
391
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000392 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000393 // Check whether we've already cached a load of the thread id in this
394 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000395 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000396 if (I != OpenMPLocThreadIDMap.end()) {
397 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000398 if (ThreadID != nullptr)
399 return ThreadID;
400 }
401 if (auto OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000402 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000403 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000404 // Check if this an outlined function with thread id passed as argument.
405 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000406 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
407 // If value loaded in entry block, cache it and use it everywhere in
408 // function.
409 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
410 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
411 Elem.second.ThreadID = ThreadID;
412 }
413 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000414 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000415 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000416
417 // This is not an outlined function region - need to call __kmpc_int32
418 // kmpc_global_thread_num(ident_t *loc).
419 // Generate thread id value and cache this value for use across the
420 // function.
421 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
422 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
423 ThreadID =
424 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
425 emitUpdateLocation(CGF, Loc));
426 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
427 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000428 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000429}
430
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000431void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000432 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000433 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
434 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataev9959db52014-05-06 10:08:46 +0000435}
436
437llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
438 return llvm::PointerType::getUnqual(IdentTy);
439}
440
441llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
442 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
443}
444
445llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000446CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000447 llvm::Constant *RTLFn = nullptr;
448 switch (Function) {
449 case OMPRTL__kmpc_fork_call: {
450 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
451 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +0000452 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
453 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000454 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000455 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +0000456 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
457 break;
458 }
459 case OMPRTL__kmpc_global_thread_num: {
460 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +0000461 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000462 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000463 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +0000464 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
465 break;
466 }
Alexey Bataev97720002014-11-11 04:05:39 +0000467 case OMPRTL__kmpc_threadprivate_cached: {
468 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
469 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
470 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
471 CGM.VoidPtrTy, CGM.SizeTy,
472 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
473 llvm::FunctionType *FnTy =
474 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
475 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
476 break;
477 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000478 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000479 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
480 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000481 llvm::Type *TypeParams[] = {
482 getIdentTyPointerTy(), CGM.Int32Ty,
483 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
484 llvm::FunctionType *FnTy =
485 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
486 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
487 break;
488 }
Alexey Bataev97720002014-11-11 04:05:39 +0000489 case OMPRTL__kmpc_threadprivate_register: {
490 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
491 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
492 // typedef void *(*kmpc_ctor)(void *);
493 auto KmpcCtorTy =
494 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
495 /*isVarArg*/ false)->getPointerTo();
496 // typedef void *(*kmpc_cctor)(void *, void *);
497 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
498 auto KmpcCopyCtorTy =
499 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
500 /*isVarArg*/ false)->getPointerTo();
501 // typedef void (*kmpc_dtor)(void *);
502 auto KmpcDtorTy =
503 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
504 ->getPointerTo();
505 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
506 KmpcCopyCtorTy, KmpcDtorTy};
507 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
508 /*isVarArg*/ false);
509 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
510 break;
511 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000512 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000513 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
514 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000515 llvm::Type *TypeParams[] = {
516 getIdentTyPointerTy(), CGM.Int32Ty,
517 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
518 llvm::FunctionType *FnTy =
519 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
520 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
521 break;
522 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000523 case OMPRTL__kmpc_cancel_barrier: {
524 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
525 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000526 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
527 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000528 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
529 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000530 break;
531 }
Alexander Musmanc6388682014-12-15 07:07:06 +0000532 case OMPRTL__kmpc_for_static_fini: {
533 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
534 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
535 llvm::FunctionType *FnTy =
536 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
537 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
538 break;
539 }
Alexey Bataevb2059782014-10-13 08:23:51 +0000540 case OMPRTL__kmpc_push_num_threads: {
541 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
542 // kmp_int32 num_threads)
543 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
544 CGM.Int32Ty};
545 llvm::FunctionType *FnTy =
546 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
547 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
548 break;
549 }
Alexey Bataevd74d0602014-10-13 06:02:40 +0000550 case OMPRTL__kmpc_serialized_parallel: {
551 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
552 // global_tid);
553 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
554 llvm::FunctionType *FnTy =
555 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
556 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
557 break;
558 }
559 case OMPRTL__kmpc_end_serialized_parallel: {
560 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
561 // global_tid);
562 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
563 llvm::FunctionType *FnTy =
564 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
565 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
566 break;
567 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000568 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000569 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000570 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
571 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000572 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000573 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
574 break;
575 }
Alexey Bataev8d690652014-12-04 07:23:53 +0000576 case OMPRTL__kmpc_master: {
577 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
578 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
579 llvm::FunctionType *FnTy =
580 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
581 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
582 break;
583 }
584 case OMPRTL__kmpc_end_master: {
585 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
586 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
587 llvm::FunctionType *FnTy =
588 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
589 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
590 break;
591 }
Alexey Bataev9f797f32015-02-05 05:57:51 +0000592 case OMPRTL__kmpc_omp_taskyield: {
593 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
594 // int end_part);
595 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
596 llvm::FunctionType *FnTy =
597 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
598 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
599 break;
600 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +0000601 case OMPRTL__kmpc_single: {
602 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
603 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
604 llvm::FunctionType *FnTy =
605 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
606 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
607 break;
608 }
609 case OMPRTL__kmpc_end_single: {
610 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
611 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
612 llvm::FunctionType *FnTy =
613 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
614 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
615 break;
616 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000617 case OMPRTL__kmpc_omp_task_alloc: {
618 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
619 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
620 // kmp_routine_entry_t *task_entry);
621 assert(KmpRoutineEntryPtrTy != nullptr &&
622 "Type kmp_routine_entry_t must be created.");
623 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
624 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
625 // Return void * and then cast to particular kmp_task_t type.
626 llvm::FunctionType *FnTy =
627 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
628 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
629 break;
630 }
631 case OMPRTL__kmpc_omp_task: {
632 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
633 // *new_task);
634 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
635 CGM.VoidPtrTy};
636 llvm::FunctionType *FnTy =
637 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
638 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
639 break;
640 }
Alexey Bataeva63048e2015-03-23 06:18:07 +0000641 case OMPRTL__kmpc_copyprivate: {
642 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
643 // kmp_int32 cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
644 // kmp_int32 didit);
645 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
646 auto *CpyFnTy =
647 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
648 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
649 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
650 CGM.Int32Ty};
651 llvm::FunctionType *FnTy =
652 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
653 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
654 break;
655 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +0000656 case OMPRTL__kmpc_reduce: {
657 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
658 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
659 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
660 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
661 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
662 /*isVarArg=*/false);
663 llvm::Type *TypeParams[] = {
664 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
665 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
666 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
667 llvm::FunctionType *FnTy =
668 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
669 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
670 break;
671 }
672 case OMPRTL__kmpc_reduce_nowait: {
673 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
674 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
675 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
676 // *lck);
677 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
678 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
679 /*isVarArg=*/false);
680 llvm::Type *TypeParams[] = {
681 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
682 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
683 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
684 llvm::FunctionType *FnTy =
685 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
686 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
687 break;
688 }
689 case OMPRTL__kmpc_end_reduce: {
690 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
691 // kmp_critical_name *lck);
692 llvm::Type *TypeParams[] = {
693 getIdentTyPointerTy(), CGM.Int32Ty,
694 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
695 llvm::FunctionType *FnTy =
696 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
697 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
698 break;
699 }
700 case OMPRTL__kmpc_end_reduce_nowait: {
701 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
702 // kmp_critical_name *lck);
703 llvm::Type *TypeParams[] = {
704 getIdentTyPointerTy(), CGM.Int32Ty,
705 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
706 llvm::FunctionType *FnTy =
707 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
708 RTLFn =
709 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
710 break;
711 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000712 }
713 return RTLFn;
714}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000715
Alexander Musman21212e42015-03-13 10:38:23 +0000716llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
717 bool IVSigned) {
718 assert((IVSize == 32 || IVSize == 64) &&
719 "IV size is not compatible with the omp runtime");
720 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
721 : "__kmpc_for_static_init_4u")
722 : (IVSigned ? "__kmpc_for_static_init_8"
723 : "__kmpc_for_static_init_8u");
724 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
725 auto PtrTy = llvm::PointerType::getUnqual(ITy);
726 llvm::Type *TypeParams[] = {
727 getIdentTyPointerTy(), // loc
728 CGM.Int32Ty, // tid
729 CGM.Int32Ty, // schedtype
730 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
731 PtrTy, // p_lower
732 PtrTy, // p_upper
733 PtrTy, // p_stride
734 ITy, // incr
735 ITy // chunk
736 };
737 llvm::FunctionType *FnTy =
738 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
739 return CGM.CreateRuntimeFunction(FnTy, Name);
740}
741
Alexander Musman92bdaab2015-03-12 13:37:50 +0000742llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
743 bool IVSigned) {
744 assert((IVSize == 32 || IVSize == 64) &&
745 "IV size is not compatible with the omp runtime");
746 auto Name =
747 IVSize == 32
748 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
749 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
750 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
751 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
752 CGM.Int32Ty, // tid
753 CGM.Int32Ty, // schedtype
754 ITy, // lower
755 ITy, // upper
756 ITy, // stride
757 ITy // chunk
758 };
759 llvm::FunctionType *FnTy =
760 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
761 return CGM.CreateRuntimeFunction(FnTy, Name);
762}
763
764llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
765 bool IVSigned) {
766 assert((IVSize == 32 || IVSize == 64) &&
767 "IV size is not compatible with the omp runtime");
768 auto Name =
769 IVSize == 32
770 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
771 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
772 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
773 auto PtrTy = llvm::PointerType::getUnqual(ITy);
774 llvm::Type *TypeParams[] = {
775 getIdentTyPointerTy(), // loc
776 CGM.Int32Ty, // tid
777 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
778 PtrTy, // p_lower
779 PtrTy, // p_upper
780 PtrTy // p_stride
781 };
782 llvm::FunctionType *FnTy =
783 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
784 return CGM.CreateRuntimeFunction(FnTy, Name);
785}
786
Alexey Bataev97720002014-11-11 04:05:39 +0000787llvm::Constant *
788CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
789 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000790 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +0000791 Twine(CGM.getMangledName(VD)) + ".cache.");
792}
793
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000794llvm::Value *CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
795 const VarDecl *VD,
796 llvm::Value *VDAddr,
797 SourceLocation Loc) {
Alexey Bataev97720002014-11-11 04:05:39 +0000798 auto VarTy = VDAddr->getType()->getPointerElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000799 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev97720002014-11-11 04:05:39 +0000800 CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy),
801 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
802 getOrCreateThreadPrivateCache(VD)};
803 return CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000804 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args);
Alexey Bataev97720002014-11-11 04:05:39 +0000805}
806
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000807void CGOpenMPRuntime::emitThreadPrivateVarInit(
Alexey Bataev97720002014-11-11 04:05:39 +0000808 CodeGenFunction &CGF, llvm::Value *VDAddr, llvm::Value *Ctor,
809 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
810 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
811 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000812 auto OMPLoc = emitUpdateLocation(CGF, Loc);
813 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +0000814 OMPLoc);
815 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
816 // to register constructor/destructor for variable.
817 llvm::Value *Args[] = {OMPLoc,
818 CGF.Builder.CreatePointerCast(VDAddr, CGM.VoidPtrTy),
819 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000820 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000821 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +0000822}
823
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000824llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
Alexey Bataev97720002014-11-11 04:05:39 +0000825 const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc,
826 bool PerformInit, CodeGenFunction *CGF) {
827 VD = VD->getDefinition(CGM.getContext());
828 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
829 ThreadPrivateWithDefinition.insert(VD);
830 QualType ASTTy = VD->getType();
831
832 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
833 auto Init = VD->getAnyInitializer();
834 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
835 // Generate function that re-emits the declaration's initializer into the
836 // threadprivate copy of the variable VD
837 CodeGenFunction CtorCGF(CGM);
838 FunctionArgList Args;
839 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
840 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
841 Args.push_back(&Dst);
842
843 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
844 CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(),
845 /*isVariadic=*/false);
846 auto FTy = CGM.getTypes().GetFunctionType(FI);
847 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
848 FTy, ".__kmpc_global_ctor_.", Loc);
849 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
850 Args, SourceLocation());
851 auto ArgVal = CtorCGF.EmitLoadOfScalar(
852 CtorCGF.GetAddrOfLocalVar(&Dst),
853 /*Volatile=*/false, CGM.PointerAlignInBytes,
854 CGM.getContext().VoidPtrTy, Dst.getLocation());
855 auto Arg = CtorCGF.Builder.CreatePointerCast(
856 ArgVal,
857 CtorCGF.ConvertTypeForMem(CGM.getContext().getPointerType(ASTTy)));
858 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
859 /*IsInitializer=*/true);
860 ArgVal = CtorCGF.EmitLoadOfScalar(
861 CtorCGF.GetAddrOfLocalVar(&Dst),
862 /*Volatile=*/false, CGM.PointerAlignInBytes,
863 CGM.getContext().VoidPtrTy, Dst.getLocation());
864 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
865 CtorCGF.FinishFunction();
866 Ctor = Fn;
867 }
868 if (VD->getType().isDestructedType() != QualType::DK_none) {
869 // Generate function that emits destructor call for the threadprivate copy
870 // of the variable VD
871 CodeGenFunction DtorCGF(CGM);
872 FunctionArgList Args;
873 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
874 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
875 Args.push_back(&Dst);
876
877 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
878 CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(),
879 /*isVariadic=*/false);
880 auto FTy = CGM.getTypes().GetFunctionType(FI);
881 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
882 FTy, ".__kmpc_global_dtor_.", Loc);
883 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
884 SourceLocation());
885 auto ArgVal = DtorCGF.EmitLoadOfScalar(
886 DtorCGF.GetAddrOfLocalVar(&Dst),
887 /*Volatile=*/false, CGM.PointerAlignInBytes,
888 CGM.getContext().VoidPtrTy, Dst.getLocation());
889 DtorCGF.emitDestroy(ArgVal, ASTTy,
890 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
891 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
892 DtorCGF.FinishFunction();
893 Dtor = Fn;
894 }
895 // Do not emit init function if it is not required.
896 if (!Ctor && !Dtor)
897 return nullptr;
898
899 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
900 auto CopyCtorTy =
901 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
902 /*isVarArg=*/false)->getPointerTo();
903 // Copying constructor for the threadprivate variable.
904 // Must be NULL - reserved by runtime, but currently it requires that this
905 // parameter is always NULL. Otherwise it fires assertion.
906 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
907 if (Ctor == nullptr) {
908 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
909 /*isVarArg=*/false)->getPointerTo();
910 Ctor = llvm::Constant::getNullValue(CtorTy);
911 }
912 if (Dtor == nullptr) {
913 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
914 /*isVarArg=*/false)->getPointerTo();
915 Dtor = llvm::Constant::getNullValue(DtorTy);
916 }
917 if (!CGF) {
918 auto InitFunctionTy =
919 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
920 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
921 InitFunctionTy, ".__omp_threadprivate_init_.");
922 CodeGenFunction InitCGF(CGM);
923 FunctionArgList ArgList;
924 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
925 CGM.getTypes().arrangeNullaryFunction(), ArgList,
926 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000927 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +0000928 InitCGF.FinishFunction();
929 return InitFunction;
930 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000931 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +0000932 }
933 return nullptr;
934}
935
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000936void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
937 llvm::Value *OutlinedFn,
938 llvm::Value *CapturedStruct) {
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000939 // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
940 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000941 emitUpdateLocation(CGF, Loc),
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000942 CGF.Builder.getInt32(1), // Number of arguments after 'microtask' argument
943 // (there is only one additional argument - 'context')
944 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()),
945 CGF.EmitCastToVoidPtr(CapturedStruct)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000946 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000947 CGF.EmitRuntimeCall(RTLFn, Args);
948}
949
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000950void CGOpenMPRuntime::emitSerialCall(CodeGenFunction &CGF, SourceLocation Loc,
951 llvm::Value *OutlinedFn,
952 llvm::Value *CapturedStruct) {
953 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +0000954 // Build calls:
955 // __kmpc_serialized_parallel(&Loc, GTid);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000956 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), ThreadID};
957 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel),
958 Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +0000959
960 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000961 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +0000962 auto Int32Ty =
963 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
964 auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr");
965 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
966 llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct};
967 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
968
969 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000970 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID};
971 CGF.EmitRuntimeCall(
972 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +0000973}
974
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +0000975// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +0000976// thread-ID variable (it is passed in a first argument of the outlined function
977// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
978// regular serial code region, get thread ID by calling kmp_int32
979// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
980// return the address of that temp.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000981llvm::Value *CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
Alexey Bataevd74d0602014-10-13 06:02:40 +0000982 SourceLocation Loc) {
983 if (auto OMPRegionInfo =
984 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000985 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +0000986 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000987
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000988 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +0000989 auto Int32Ty =
990 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
991 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
992 CGF.EmitStoreOfScalar(ThreadID,
993 CGF.MakeNaturalAlignAddrLValue(ThreadIDTemp, Int32Ty));
994
995 return ThreadIDTemp;
996}
997
Alexey Bataev97720002014-11-11 04:05:39 +0000998llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000999CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001000 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001001 SmallString<256> Buffer;
1002 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001003 Out << Name;
1004 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001005 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1006 if (Elem.second) {
1007 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001008 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001009 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001010 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001011
David Blaikie13156b62014-11-19 03:06:06 +00001012 return Elem.second = new llvm::GlobalVariable(
1013 CGM.getModule(), Ty, /*IsConstant*/ false,
1014 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1015 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001016}
1017
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001018llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001019 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001020 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001021}
1022
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001023namespace {
1024class CallEndCleanup : public EHScopeStack::Cleanup {
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001025public:
1026 typedef ArrayRef<llvm::Value *> CleanupValuesTy;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001027private:
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001028 llvm::Value *Callee;
1029 llvm::SmallVector<llvm::Value *, 8> Args;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001030
1031public:
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001032 CallEndCleanup(llvm::Value *Callee, CleanupValuesTy Args)
1033 : Callee(Callee), Args(Args.begin(), Args.end()) {}
1034 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
1035 CGF.EmitRuntimeCall(Callee, Args);
1036 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001037};
1038} // namespace
1039
1040void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1041 StringRef CriticalName,
1042 const RegionCodeGenTy &CriticalOpGen,
1043 SourceLocation Loc) {
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001044 // __kmpc_critical(ident_t *, gtid, Lock);
1045 // CriticalOpGen();
1046 // __kmpc_end_critical(ident_t *, gtid, Lock);
1047 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001048 {
1049 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001050 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1051 getCriticalRegionLock(CriticalName)};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001052 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001053 // Build a call to __kmpc_end_critical
1054 CGF.EHStack.pushCleanup<CallEndCleanup>(
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001055 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
1056 llvm::makeArrayRef(Args));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001057 emitInlinedDirective(CGF, CriticalOpGen);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001058 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001059}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001060
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001061static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001062 const RegionCodeGenTy &BodyOpGen) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001063 llvm::Value *CallBool = CGF.EmitScalarConversion(
1064 IfCond,
1065 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
1066 CGF.getContext().BoolTy);
1067
1068 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1069 auto *ContBlock = CGF.createBasicBlock("omp_if.end");
1070 // Generate the branch (If-stmt)
1071 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1072 CGF.EmitBlock(ThenBlock);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001073 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, BodyOpGen);
Alexey Bataev8d690652014-12-04 07:23:53 +00001074 // Emit the rest of bblocks/branches
1075 CGF.EmitBranch(ContBlock);
1076 CGF.EmitBlock(ContBlock, true);
1077}
1078
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001079void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001080 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001081 SourceLocation Loc) {
Alexey Bataev8d690652014-12-04 07:23:53 +00001082 // if(__kmpc_master(ident_t *, gtid)) {
1083 // MasterOpGen();
1084 // __kmpc_end_master(ident_t *, gtid);
1085 // }
1086 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001087 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001088 auto *IsMaster =
1089 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001090 emitIfStmt(CGF, IsMaster, [&](CodeGenFunction &CGF) -> void {
1091 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001092 CGF.EHStack.pushCleanup<CallEndCleanup>(
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001093 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
1094 llvm::makeArrayRef(Args));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001095 MasterOpGen(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00001096 });
1097}
1098
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001099void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
1100 SourceLocation Loc) {
Alexey Bataev9f797f32015-02-05 05:57:51 +00001101 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
1102 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001103 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00001104 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001105 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev9f797f32015-02-05 05:57:51 +00001106}
1107
Alexey Bataeva63048e2015-03-23 06:18:07 +00001108static llvm::Value *emitCopyprivateCopyFunction(
1109 CodeGenModule &CGM, llvm::Type *ArgsType, ArrayRef<const Expr *> SrcExprs,
1110 ArrayRef<const Expr *> DstExprs, ArrayRef<const Expr *> AssignmentOps) {
1111 auto &C = CGM.getContext();
1112 // void copy_func(void *LHSArg, void *RHSArg);
1113 FunctionArgList Args;
1114 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1115 C.VoidPtrTy);
1116 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1117 C.VoidPtrTy);
1118 Args.push_back(&LHSArg);
1119 Args.push_back(&RHSArg);
1120 FunctionType::ExtInfo EI;
1121 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1122 C.VoidTy, Args, EI, /*isVariadic=*/false);
1123 auto *Fn = llvm::Function::Create(
1124 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
1125 ".omp.copyprivate.copy_func", &CGM.getModule());
1126 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
1127 CodeGenFunction CGF(CGM);
1128 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
1129 // Dst = (void*[n])(LHSArg);
1130 // Src = (void*[n])(RHSArg);
1131 auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1132 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
1133 CGF.PointerAlignInBytes),
1134 ArgsType);
1135 auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1136 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
1137 CGF.PointerAlignInBytes),
1138 ArgsType);
1139 // *(Type0*)Dst[0] = *(Type0*)Src[0];
1140 // *(Type1*)Dst[1] = *(Type1*)Src[1];
1141 // ...
1142 // *(Typen*)Dst[n] = *(Typen*)Src[n];
1143 CodeGenFunction::OMPPrivateScope Scope(CGF);
1144 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
1145 Scope.addPrivate(
1146 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()),
1147 [&]() -> llvm::Value *{
1148 return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
David Blaikie1ed728c2015-04-05 22:45:47 +00001149 CGF.Builder.CreateAlignedLoad(
1150 CGF.Builder.CreateStructGEP(nullptr, RHS, I),
1151 CGM.PointerAlignInBytes),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001152 CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
1153 });
1154 Scope.addPrivate(
1155 cast<VarDecl>(cast<DeclRefExpr>(DstExprs[I])->getDecl()),
1156 [&]() -> llvm::Value *{
1157 return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
David Blaikie1ed728c2015-04-05 22:45:47 +00001158 CGF.Builder.CreateAlignedLoad(
1159 CGF.Builder.CreateStructGEP(nullptr, LHS, I),
1160 CGM.PointerAlignInBytes),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001161 CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
1162 });
1163 }
1164 Scope.Privatize();
1165 for (auto *E : AssignmentOps) {
1166 CGF.EmitIgnoredExpr(E);
1167 }
1168 Scope.ForceCleanup();
1169 CGF.FinishFunction();
1170 return Fn;
1171}
1172
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001173void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001174 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001175 SourceLocation Loc,
1176 ArrayRef<const Expr *> CopyprivateVars,
1177 ArrayRef<const Expr *> SrcExprs,
1178 ArrayRef<const Expr *> DstExprs,
1179 ArrayRef<const Expr *> AssignmentOps) {
1180 assert(CopyprivateVars.size() == SrcExprs.size() &&
1181 CopyprivateVars.size() == DstExprs.size() &&
1182 CopyprivateVars.size() == AssignmentOps.size());
1183 auto &C = CGM.getContext();
1184 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001185 // if(__kmpc_single(ident_t *, gtid)) {
1186 // SingleOpGen();
1187 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001188 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001189 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001190 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1191 // <copy_func>, did_it);
1192
1193 llvm::AllocaInst *DidIt = nullptr;
1194 if (!CopyprivateVars.empty()) {
1195 // int32 did_it = 0;
1196 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1197 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
1198 CGF.InitTempAlloca(DidIt, CGF.Builder.getInt32(0));
1199 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001200 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001201 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001202 auto *IsSingle =
1203 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001204 emitIfStmt(CGF, IsSingle, [&](CodeGenFunction &CGF) -> void {
1205 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001206 CGF.EHStack.pushCleanup<CallEndCleanup>(
1207 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
1208 llvm::makeArrayRef(Args));
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001209 SingleOpGen(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001210 if (DidIt) {
1211 // did_it = 1;
1212 CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(1), DidIt,
1213 DidIt->getAlignment());
1214 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001215 });
Alexey Bataeva63048e2015-03-23 06:18:07 +00001216 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
1217 // <copy_func>, did_it);
1218 if (DidIt) {
1219 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
1220 auto CopyprivateArrayTy =
1221 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
1222 /*IndexTypeQuals=*/0);
1223 // Create a list of all private variables for copyprivate.
1224 auto *CopyprivateList =
1225 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
1226 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
David Blaikie1ed728c2015-04-05 22:45:47 +00001227 auto *Elem = CGF.Builder.CreateStructGEP(
1228 CopyprivateList->getAllocatedType(), CopyprivateList, I);
Alexey Bataeva63048e2015-03-23 06:18:07 +00001229 CGF.Builder.CreateAlignedStore(
1230 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1231 CGF.EmitLValue(CopyprivateVars[I]).getAddress(), CGF.VoidPtrTy),
1232 Elem, CGM.PointerAlignInBytes);
1233 }
1234 // Build function that copies private values from single region to all other
1235 // threads in the corresponding parallel region.
1236 auto *CpyFn = emitCopyprivateCopyFunction(
1237 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
1238 SrcExprs, DstExprs, AssignmentOps);
1239 auto *BufSize = CGF.Builder.getInt32(
1240 C.getTypeSizeInChars(CopyprivateArrayTy).getQuantity());
1241 auto *CL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
1242 CGF.VoidPtrTy);
1243 auto *DidItVal =
1244 CGF.Builder.CreateAlignedLoad(DidIt, CGF.PointerAlignInBytes);
1245 llvm::Value *Args[] = {
1246 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
1247 getThreadID(CGF, Loc), // i32 <gtid>
1248 BufSize, // i32 <buf_size>
1249 CL, // void *<copyprivate list>
1250 CpyFn, // void (*) (void *, void *) <copy_func>
1251 DidItVal // i32 did_it
1252 };
1253 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
1254 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001255}
1256
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001257void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf2685682015-03-30 04:30:22 +00001258 OpenMPDirectiveKind Kind) {
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001259 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataevf2685682015-03-30 04:30:22 +00001260 OpenMPLocationFlags Flags = OMP_IDENT_KMPC;
1261 if (Kind == OMPD_for) {
1262 Flags =
1263 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_FOR);
1264 } else if (Kind == OMPD_sections) {
1265 Flags = static_cast<OpenMPLocationFlags>(Flags |
1266 OMP_IDENT_BARRIER_IMPL_SECTIONS);
1267 } else if (Kind == OMPD_single) {
1268 Flags =
1269 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_SINGLE);
1270 } else if (Kind == OMPD_barrier) {
1271 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_EXPL);
1272 } else {
1273 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL);
1274 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001275 // Build call __kmpc_cancel_barrier(loc, thread_id);
1276 // Replace __kmpc_barrier() function by __kmpc_cancel_barrier() because this
1277 // one provides the same functionality and adds initial support for
1278 // cancellation constructs introduced in OpenMP 4.0. __kmpc_cancel_barrier()
1279 // is provided default by the runtime library so it safe to make such
1280 // replacement.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001281 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
1282 getThreadID(CGF, Loc)};
1283 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001284}
1285
Alexander Musmanc6388682014-12-15 07:07:06 +00001286/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
1287/// the enum sched_type in kmp.h).
1288enum OpenMPSchedType {
1289 /// \brief Lower bound for default (unordered) versions.
1290 OMP_sch_lower = 32,
1291 OMP_sch_static_chunked = 33,
1292 OMP_sch_static = 34,
1293 OMP_sch_dynamic_chunked = 35,
1294 OMP_sch_guided_chunked = 36,
1295 OMP_sch_runtime = 37,
1296 OMP_sch_auto = 38,
1297 /// \brief Lower bound for 'ordered' versions.
1298 OMP_ord_lower = 64,
1299 /// \brief Lower bound for 'nomerge' versions.
1300 OMP_nm_lower = 160,
1301};
1302
1303/// \brief Map the OpenMP loop schedule to the runtime enumeration.
1304static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
1305 bool Chunked) {
1306 switch (ScheduleKind) {
1307 case OMPC_SCHEDULE_static:
1308 return Chunked ? OMP_sch_static_chunked : OMP_sch_static;
1309 case OMPC_SCHEDULE_dynamic:
1310 return OMP_sch_dynamic_chunked;
1311 case OMPC_SCHEDULE_guided:
1312 return OMP_sch_guided_chunked;
1313 case OMPC_SCHEDULE_auto:
1314 return OMP_sch_auto;
1315 case OMPC_SCHEDULE_runtime:
1316 return OMP_sch_runtime;
1317 case OMPC_SCHEDULE_unknown:
1318 assert(!Chunked && "chunk was specified but schedule kind not known");
1319 return OMP_sch_static;
1320 }
1321 llvm_unreachable("Unexpected runtime schedule");
1322}
1323
1324bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
1325 bool Chunked) const {
1326 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
1327 return Schedule == OMP_sch_static;
1328}
1329
Alexander Musmandf7a8e22015-01-22 08:49:35 +00001330bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
1331 auto Schedule = getRuntimeSchedule(ScheduleKind, /* Chunked */ false);
1332 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
1333 return Schedule != OMP_sch_static;
1334}
1335
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001336void CGOpenMPRuntime::emitForInit(CodeGenFunction &CGF, SourceLocation Loc,
1337 OpenMPScheduleClauseKind ScheduleKind,
1338 unsigned IVSize, bool IVSigned,
1339 llvm::Value *IL, llvm::Value *LB,
1340 llvm::Value *UB, llvm::Value *ST,
1341 llvm::Value *Chunk) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001342 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunk != nullptr);
Alexander Musman92bdaab2015-03-12 13:37:50 +00001343 if (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked) {
1344 // Call __kmpc_dispatch_init(
1345 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
1346 // kmp_int[32|64] lower, kmp_int[32|64] upper,
1347 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00001348
Alexander Musman92bdaab2015-03-12 13:37:50 +00001349 // If the Chunk was not specified in the clause - use default value 1.
1350 if (Chunk == nullptr)
1351 Chunk = CGF.Builder.getIntN(IVSize, 1);
1352 llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1353 getThreadID(CGF, Loc),
1354 CGF.Builder.getInt32(Schedule), // Schedule type
1355 CGF.Builder.getIntN(IVSize, 0), // Lower
1356 UB, // Upper
1357 CGF.Builder.getIntN(IVSize, 1), // Stride
1358 Chunk // Chunk
1359 };
1360 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
1361 } else {
1362 // Call __kmpc_for_static_init(
1363 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
1364 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
1365 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
1366 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
1367 if (Chunk == nullptr) {
1368 assert(Schedule == OMP_sch_static &&
1369 "expected static non-chunked schedule");
1370 // If the Chunk was not specified in the clause - use default value 1.
1371 Chunk = CGF.Builder.getIntN(IVSize, 1);
1372 } else
1373 assert(Schedule == OMP_sch_static_chunked &&
1374 "expected static chunked schedule");
1375 llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1376 getThreadID(CGF, Loc),
1377 CGF.Builder.getInt32(Schedule), // Schedule type
1378 IL, // &isLastIter
1379 LB, // &LB
1380 UB, // &UB
1381 ST, // &Stride
1382 CGF.Builder.getIntN(IVSize, 1), // Incr
1383 Chunk // Chunk
1384 };
Alexander Musman21212e42015-03-13 10:38:23 +00001385 CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args);
Alexander Musman92bdaab2015-03-12 13:37:50 +00001386 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001387}
1388
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001389void CGOpenMPRuntime::emitForFinish(CodeGenFunction &CGF, SourceLocation Loc,
1390 OpenMPScheduleClauseKind ScheduleKind) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001391 assert((ScheduleKind == OMPC_SCHEDULE_static ||
1392 ScheduleKind == OMPC_SCHEDULE_unknown) &&
1393 "Non-static schedule kinds are not yet implemented");
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001394 (void)ScheduleKind;
Alexander Musmanc6388682014-12-15 07:07:06 +00001395 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001396 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1397 getThreadID(CGF, Loc)};
1398 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
1399 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00001400}
1401
Alexander Musman92bdaab2015-03-12 13:37:50 +00001402llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
1403 SourceLocation Loc, unsigned IVSize,
1404 bool IVSigned, llvm::Value *IL,
1405 llvm::Value *LB, llvm::Value *UB,
1406 llvm::Value *ST) {
1407 // Call __kmpc_dispatch_next(
1408 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
1409 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
1410 // kmp_int[32|64] *p_stride);
1411 llvm::Value *Args[] = {
1412 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc),
1413 IL, // &isLastIter
1414 LB, // &Lower
1415 UB, // &Upper
1416 ST // &Stride
1417 };
1418 llvm::Value *Call =
1419 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
1420 return CGF.EmitScalarConversion(
1421 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
1422 CGF.getContext().BoolTy);
1423}
1424
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001425void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
1426 llvm::Value *NumThreads,
1427 SourceLocation Loc) {
Alexey Bataevb2059782014-10-13 08:23:51 +00001428 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
1429 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001430 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00001431 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001432 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
1433 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00001434}
1435
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001436void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
1437 SourceLocation Loc) {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001438 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001439 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
1440 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001441}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001442
Alexey Bataev62b63b12015-03-10 07:28:44 +00001443namespace {
1444/// \brief Indexes of fields for type kmp_task_t.
1445enum KmpTaskTFields {
1446 /// \brief List of shared variables.
1447 KmpTaskTShareds,
1448 /// \brief Task routine.
1449 KmpTaskTRoutine,
1450 /// \brief Partition id for the untied tasks.
1451 KmpTaskTPartId,
1452 /// \brief Function with call of destructors for private variables.
1453 KmpTaskTDestructors,
1454};
1455} // namespace
1456
1457void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
1458 if (!KmpRoutineEntryPtrTy) {
1459 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
1460 auto &C = CGM.getContext();
1461 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
1462 FunctionProtoType::ExtProtoInfo EPI;
1463 KmpRoutineEntryPtrQTy = C.getPointerType(
1464 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
1465 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
1466 }
1467}
1468
1469static void addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1470 QualType FieldTy) {
1471 auto *Field = FieldDecl::Create(
1472 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1473 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1474 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1475 Field->setAccess(AS_public);
1476 DC->addDecl(Field);
1477}
1478
1479static QualType createKmpTaskTRecordDecl(CodeGenModule &CGM,
1480 QualType KmpInt32Ty,
1481 QualType KmpRoutineEntryPointerQTy) {
1482 auto &C = CGM.getContext();
1483 // Build struct kmp_task_t {
1484 // void * shareds;
1485 // kmp_routine_entry_t routine;
1486 // kmp_int32 part_id;
1487 // kmp_routine_entry_t destructors;
1488 // /* private vars */
1489 // };
1490 auto *RD = C.buildImplicitRecord("kmp_task_t");
1491 RD->startDefinition();
1492 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1493 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
1494 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1495 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
1496 // TODO: add private fields.
1497 RD->completeDefinition();
1498 return C.getRecordType(RD);
1499}
1500
1501/// \brief Emit a proxy function which accepts kmp_task_t as the second
1502/// argument.
1503/// \code
1504/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
1505/// TaskFunction(gtid, tt->part_id, tt->shareds);
1506/// return 0;
1507/// }
1508/// \endcode
1509static llvm::Value *
1510emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
1511 QualType KmpInt32Ty, QualType KmpTaskTPtrQTy,
David Blaikie2e804282015-04-05 22:47:07 +00001512 QualType SharedsPtrTy, llvm::Value *TaskFunction,
1513 llvm::Type *KmpTaskTTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001514 auto &C = CGM.getContext();
1515 FunctionArgList Args;
1516 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
1517 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
1518 /*Id=*/nullptr, KmpTaskTPtrQTy);
1519 Args.push_back(&GtidArg);
1520 Args.push_back(&TaskTypeArg);
1521 FunctionType::ExtInfo Info;
1522 auto &TaskEntryFnInfo =
1523 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info,
1524 /*isVariadic=*/false);
1525 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
1526 auto *TaskEntry =
1527 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
1528 ".omp_task_entry.", &CGM.getModule());
1529 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskEntryFnInfo, TaskEntry);
1530 CodeGenFunction CGF(CGM);
1531 CGF.disableDebugInfo();
1532 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
1533
1534 // TaskFunction(gtid, tt->part_id, tt->shareds);
1535 auto *GtidParam = CGF.EmitLoadOfScalar(
1536 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false,
1537 C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc);
1538 auto TaskTypeArgAddr = CGF.EmitLoadOfScalar(
1539 CGF.GetAddrOfLocalVar(&TaskTypeArg), /*Volatile=*/false,
1540 CGM.PointerAlignInBytes, KmpTaskTPtrQTy, Loc);
David Blaikie1ed728c2015-04-05 22:45:47 +00001541 auto *PartidPtr = CGF.Builder.CreateStructGEP(KmpTaskTTy, TaskTypeArgAddr,
Alexey Bataev62b63b12015-03-10 07:28:44 +00001542 /*Idx=*/KmpTaskTPartId);
1543 auto *PartidParam = CGF.EmitLoadOfScalar(
1544 PartidPtr, /*Volatile=*/false,
1545 C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc);
David Blaikie1ed728c2015-04-05 22:45:47 +00001546 auto *SharedsPtr = CGF.Builder.CreateStructGEP(KmpTaskTTy, TaskTypeArgAddr,
Alexey Bataev62b63b12015-03-10 07:28:44 +00001547 /*Idx=*/KmpTaskTShareds);
1548 auto *SharedsParam =
1549 CGF.EmitLoadOfScalar(SharedsPtr, /*Volatile=*/false,
1550 CGM.PointerAlignInBytes, C.VoidPtrTy, Loc);
1551 llvm::Value *CallArgs[] = {
1552 GtidParam, PartidParam,
1553 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1554 SharedsParam, CGF.ConvertTypeForMem(SharedsPtrTy))};
1555 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
1556 CGF.EmitStoreThroughLValue(
1557 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
1558 CGF.MakeNaturalAlignAddrLValue(CGF.ReturnValue, KmpInt32Ty));
1559 CGF.FinishFunction();
1560 return TaskEntry;
1561}
1562
1563void CGOpenMPRuntime::emitTaskCall(
1564 CodeGenFunction &CGF, SourceLocation Loc, bool Tied,
1565 llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
1566 llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds) {
1567 auto &C = CGM.getContext();
1568 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1569 // Build type kmp_routine_entry_t (if not built yet).
1570 emitKmpRoutineEntryT(KmpInt32Ty);
1571 // Build particular struct kmp_task_t for the given task.
1572 auto KmpTaskQTy =
1573 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy);
1574 QualType KmpTaskTPtrQTy = C.getPointerType(KmpTaskQTy);
David Blaikie1ed728c2015-04-05 22:45:47 +00001575 auto *KmpTaskTTy = CGF.ConvertType(KmpTaskQTy);
1576 auto *KmpTaskTPtrTy = KmpTaskTTy->getPointerTo();
Alexey Bataev62b63b12015-03-10 07:28:44 +00001577 auto KmpTaskTySize = CGM.getSize(C.getTypeSizeInChars(KmpTaskQTy));
1578 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
1579
1580 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
1581 // kmp_task_t *tt);
David Blaikie1ed728c2015-04-05 22:45:47 +00001582 auto *TaskEntry =
1583 emitProxyTaskFunction(CGM, Loc, KmpInt32Ty, KmpTaskTPtrQTy, SharedsPtrTy,
1584 TaskFunction, KmpTaskTTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001585
1586 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1587 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1588 // kmp_routine_entry_t *task_entry);
1589 // Task flags. Format is taken from
1590 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
1591 // description of kmp_tasking_flags struct.
1592 const unsigned TiedFlag = 0x1;
1593 const unsigned FinalFlag = 0x2;
1594 unsigned Flags = Tied ? TiedFlag : 0;
1595 auto *TaskFlags =
1596 Final.getPointer()
1597 ? CGF.Builder.CreateSelect(Final.getPointer(),
1598 CGF.Builder.getInt32(FinalFlag),
1599 CGF.Builder.getInt32(/*C=*/0))
1600 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
1601 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
1602 auto SharedsSize = C.getTypeSizeInChars(SharedsTy);
1603 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
1604 getThreadID(CGF, Loc), TaskFlags, KmpTaskTySize,
1605 CGM.getSize(SharedsSize),
1606 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1607 TaskEntry, KmpRoutineEntryPtrTy)};
1608 auto *NewTask = CGF.EmitRuntimeCall(
1609 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
1610 auto *NewTaskNewTaskTTy =
1611 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(NewTask, KmpTaskTPtrTy);
1612 // Fill the data in the resulting kmp_task_t record.
1613 // Copy shareds if there are any.
1614 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty())
1615 CGF.EmitAggregateCopy(
1616 CGF.EmitLoadOfScalar(
David Blaikie1ed728c2015-04-05 22:45:47 +00001617 CGF.Builder.CreateStructGEP(KmpTaskTTy, NewTaskNewTaskTTy,
Alexey Bataev62b63b12015-03-10 07:28:44 +00001618 /*Idx=*/KmpTaskTShareds),
1619 /*Volatile=*/false, CGM.PointerAlignInBytes, SharedsPtrTy, Loc),
1620 Shareds, SharedsTy);
1621 // TODO: generate function with destructors for privates.
1622 // Provide pointer to function with destructors for privates.
1623 CGF.Builder.CreateAlignedStore(
1624 llvm::ConstantPointerNull::get(
1625 cast<llvm::PointerType>(KmpRoutineEntryPtrTy)),
David Blaikie1ed728c2015-04-05 22:45:47 +00001626 CGF.Builder.CreateStructGEP(KmpTaskTTy, NewTaskNewTaskTTy,
Alexey Bataev62b63b12015-03-10 07:28:44 +00001627 /*Idx=*/KmpTaskTDestructors),
1628 CGM.PointerAlignInBytes);
1629
1630 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
1631 // libcall.
1632 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1633 // *new_task);
1634 llvm::Value *TaskArgs[] = {emitUpdateLocation(CGF, Loc),
1635 getThreadID(CGF, Loc), NewTask};
1636 // TODO: add check for untied tasks.
1637 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
1638}
1639
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001640static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
1641 llvm::Type *ArgsType,
1642 ArrayRef<const Expr *> LHSExprs,
1643 ArrayRef<const Expr *> RHSExprs,
1644 ArrayRef<const Expr *> ReductionOps) {
1645 auto &C = CGM.getContext();
1646
1647 // void reduction_func(void *LHSArg, void *RHSArg);
1648 FunctionArgList Args;
1649 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1650 C.VoidPtrTy);
1651 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
1652 C.VoidPtrTy);
1653 Args.push_back(&LHSArg);
1654 Args.push_back(&RHSArg);
1655 FunctionType::ExtInfo EI;
1656 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1657 C.VoidTy, Args, EI, /*isVariadic=*/false);
1658 auto *Fn = llvm::Function::Create(
1659 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
1660 ".omp.reduction.reduction_func", &CGM.getModule());
1661 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
1662 CodeGenFunction CGF(CGM);
1663 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
1664
1665 // Dst = (void*[n])(LHSArg);
1666 // Src = (void*[n])(RHSArg);
1667 auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1668 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
1669 CGF.PointerAlignInBytes),
1670 ArgsType);
1671 auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1672 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
1673 CGF.PointerAlignInBytes),
1674 ArgsType);
1675
1676 // ...
1677 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
1678 // ...
1679 CodeGenFunction::OMPPrivateScope Scope(CGF);
1680 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I) {
1681 Scope.addPrivate(
1682 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()),
1683 [&]() -> llvm::Value *{
1684 return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1685 CGF.Builder.CreateAlignedLoad(
1686 CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, RHS, I),
1687 CGM.PointerAlignInBytes),
1688 CGF.ConvertTypeForMem(C.getPointerType(RHSExprs[I]->getType())));
1689 });
1690 Scope.addPrivate(
1691 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()),
1692 [&]() -> llvm::Value *{
1693 return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1694 CGF.Builder.CreateAlignedLoad(
1695 CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, LHS, I),
1696 CGM.PointerAlignInBytes),
1697 CGF.ConvertTypeForMem(C.getPointerType(LHSExprs[I]->getType())));
1698 });
1699 }
1700 Scope.Privatize();
1701 for (auto *E : ReductionOps) {
1702 CGF.EmitIgnoredExpr(E);
1703 }
1704 Scope.ForceCleanup();
1705 CGF.FinishFunction();
1706 return Fn;
1707}
1708
1709void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
1710 ArrayRef<const Expr *> LHSExprs,
1711 ArrayRef<const Expr *> RHSExprs,
1712 ArrayRef<const Expr *> ReductionOps,
1713 bool WithNowait) {
1714 // Next code should be emitted for reduction:
1715 //
1716 // static kmp_critical_name lock = { 0 };
1717 //
1718 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
1719 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
1720 // ...
1721 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
1722 // *(Type<n>-1*)rhs[<n>-1]);
1723 // }
1724 //
1725 // ...
1726 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
1727 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
1728 // RedList, reduce_func, &<lock>)) {
1729 // case 1:
1730 // ...
1731 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
1732 // ...
1733 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
1734 // break;
1735 // case 2:
1736 // ...
1737 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
1738 // ...
1739 // break;
1740 // default:;
1741 // }
1742
1743 auto &C = CGM.getContext();
1744
1745 // 1. Build a list of reduction variables.
1746 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
1747 llvm::APInt ArraySize(/*unsigned int numBits=*/32, RHSExprs.size());
1748 QualType ReductionArrayTy =
1749 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
1750 /*IndexTypeQuals=*/0);
1751 auto *ReductionList =
1752 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
1753 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I) {
1754 auto *Elem = CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, ReductionList, I);
1755 CGF.Builder.CreateAlignedStore(
1756 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1757 CGF.EmitLValue(RHSExprs[I]).getAddress(), CGF.VoidPtrTy),
1758 Elem, CGM.PointerAlignInBytes);
1759 }
1760
1761 // 2. Emit reduce_func().
1762 auto *ReductionFn = emitReductionFunction(
1763 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), LHSExprs,
1764 RHSExprs, ReductionOps);
1765
1766 // 3. Create static kmp_critical_name lock = { 0 };
1767 auto *Lock = getCriticalRegionLock(".reduction");
1768
1769 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
1770 // RedList, reduce_func, &<lock>);
1771 auto *IdentTLoc = emitUpdateLocation(
1772 CGF, Loc,
1773 static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE));
1774 auto *ThreadId = getThreadID(CGF, Loc);
1775 auto *ReductionArrayTySize = llvm::ConstantInt::get(
1776 CGM.SizeTy, C.getTypeSizeInChars(ReductionArrayTy).getQuantity());
1777 auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList,
1778 CGF.VoidPtrTy);
1779 llvm::Value *Args[] = {
1780 IdentTLoc, // ident_t *<loc>
1781 ThreadId, // i32 <gtid>
1782 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
1783 ReductionArrayTySize, // size_type sizeof(RedList)
1784 RL, // void *RedList
1785 ReductionFn, // void (*) (void *, void *) <reduce_func>
1786 Lock // kmp_critical_name *&<lock>
1787 };
1788 auto Res = CGF.EmitRuntimeCall(
1789 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
1790 : OMPRTL__kmpc_reduce),
1791 Args);
1792
1793 // 5. Build switch(res)
1794 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
1795 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
1796
1797 // 6. Build case 1:
1798 // ...
1799 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
1800 // ...
1801 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
1802 // break;
1803 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
1804 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
1805 CGF.EmitBlock(Case1BB);
1806
1807 {
1808 CodeGenFunction::RunCleanupsScope Scope(CGF);
1809 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
1810 llvm::Value *EndArgs[] = {
1811 IdentTLoc, // ident_t *<loc>
1812 ThreadId, // i32 <gtid>
1813 Lock // kmp_critical_name *&<lock>
1814 };
1815 CGF.EHStack.pushCleanup<CallEndCleanup>(
1816 NormalAndEHCleanup,
1817 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
1818 : OMPRTL__kmpc_end_reduce),
1819 llvm::makeArrayRef(EndArgs));
1820 for (auto *E : ReductionOps) {
1821 CGF.EmitIgnoredExpr(E);
1822 }
1823 }
1824
1825 CGF.EmitBranch(DefaultBB);
1826
1827 // 7. Build case 2:
1828 // ...
1829 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
1830 // ...
1831 // break;
1832 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
1833 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
1834 CGF.EmitBlock(Case2BB);
1835
1836 {
1837 CodeGenFunction::RunCleanupsScope Scope(CGF);
1838 auto I = LHSExprs.begin();
1839 for (auto *E : ReductionOps) {
1840 const Expr *XExpr = nullptr;
1841 const Expr *EExpr = nullptr;
1842 const Expr *UpExpr = nullptr;
1843 BinaryOperatorKind BO = BO_Comma;
1844 // Try to emit update expression as a simple atomic.
1845 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(E)) {
1846 // If this is a conditional operator, analyze it's condition for
1847 // min/max reduction operator.
1848 E = ACO->getCond();
1849 }
1850 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
1851 if (BO->getOpcode() == BO_Assign) {
1852 XExpr = BO->getLHS();
1853 UpExpr = BO->getRHS();
1854 }
1855 }
1856 // Analyze RHS part of the whole expression.
1857 if (UpExpr) {
1858 if (auto *BORHS =
1859 dyn_cast<BinaryOperator>(UpExpr->IgnoreParenImpCasts())) {
1860 EExpr = BORHS->getRHS();
1861 BO = BORHS->getOpcode();
1862 }
1863 }
1864 if (XExpr) {
1865 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
1866 LValue X = CGF.EmitLValue(XExpr);
1867 RValue E;
1868 if (EExpr)
1869 E = CGF.EmitAnyExpr(EExpr);
1870 CGF.EmitOMPAtomicSimpleUpdateExpr(
1871 X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
1872 [&CGF, UpExpr, VD](RValue XRValue) {
1873 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
1874 PrivateScope.addPrivate(
1875 VD, [&CGF, VD, XRValue]() -> llvm::Value *{
1876 auto *LHSTemp = CGF.CreateMemTemp(VD->getType());
1877 CGF.EmitStoreThroughLValue(
1878 XRValue,
1879 CGF.MakeNaturalAlignAddrLValue(LHSTemp, VD->getType()));
1880 return LHSTemp;
1881 });
1882 (void)PrivateScope.Privatize();
1883 return CGF.EmitAnyExpr(UpExpr);
1884 });
1885 } else {
1886 // Emit as a critical region.
1887 emitCriticalRegion(CGF, ".atomic_reduction", [E](CodeGenFunction &CGF) {
1888 CGF.EmitIgnoredExpr(E);
1889 }, Loc);
1890 }
1891 ++I;
1892 }
1893 }
1894
1895 CGF.EmitBranch(DefaultBB);
1896 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
1897}
1898
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001899void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
1900 const RegionCodeGenTy &CodeGen) {
1901 InlinedOpenMPRegionRAII Region(CGF, CodeGen);
1902 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001903}
1904