blob: bfb7f99740a280965aa58195da13393cd8850cd6 [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
Samuel Antaoee8fb302016-01-06 13:42:12 +000014#include "CGCXXABI.h"
15#include "CGCleanup.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000016#include "CGOpenMPRuntime.h"
17#include "CodeGenFunction.h"
18#include "clang/AST/Decl.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000019#include "clang/AST/StmtOpenMP.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000020#include "llvm/ADT/ArrayRef.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000021#include "llvm/Bitcode/ReaderWriter.h"
Alexey Bataevd74d0602014-10-13 06:02:40 +000022#include "llvm/IR/CallSite.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000023#include "llvm/IR/DerivedTypes.h"
24#include "llvm/IR/GlobalValue.h"
25#include "llvm/IR/Value.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000026#include "llvm/Support/Format.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000027#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000028#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000029
30using namespace clang;
31using namespace CodeGen;
32
Benjamin Kramerc52193f2014-10-10 13:57:57 +000033namespace {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000034/// \brief Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000035class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
36public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000037 /// \brief Kinds of OpenMP regions used in codegen.
38 enum CGOpenMPRegionKind {
39 /// \brief Region with outlined function for standalone 'parallel'
40 /// directive.
41 ParallelOutlinedRegion,
42 /// \brief Region with outlined function for standalone 'task' directive.
43 TaskOutlinedRegion,
44 /// \brief Region for constructs that do not require function outlining,
45 /// like 'for', 'sections', 'atomic' etc. directives.
46 InlinedRegion,
Samuel Antaobed3c462015-10-02 16:14:20 +000047 /// \brief Region with outlined function for standalone 'target' directive.
48 TargetRegion,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000049 };
Alexey Bataev18095712014-10-10 12:19:54 +000050
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000051 CGOpenMPRegionInfo(const CapturedStmt &CS,
52 const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000053 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
54 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000055 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000056 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000057
58 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000059 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
60 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000061 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000062 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000063
64 /// \brief Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000065 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000066 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000067
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000068 /// \brief Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000069 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000070
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000071 /// \brief Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000072 /// \return LValue for thread id variable. This LValue always has type int32*.
73 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000074
Alexey Bataev48591dd2016-04-20 04:01:36 +000075 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
76
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000077 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000078
Alexey Bataev81c7ea02015-07-03 09:56:58 +000079 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
80
Alexey Bataev25e5b442015-09-15 12:52:43 +000081 bool hasCancel() const { return HasCancel; }
82
Alexey Bataev18095712014-10-10 12:19:54 +000083 static bool classof(const CGCapturedStmtInfo *Info) {
84 return Info->getKind() == CR_OpenMP;
85 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000086
Alexey Bataev48591dd2016-04-20 04:01:36 +000087 ~CGOpenMPRegionInfo() override = default;
88
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000089protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000090 CGOpenMPRegionKind RegionKind;
Hans Wennborg45c74392016-01-12 20:54:36 +000091 RegionCodeGenTy CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000092 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +000093 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000094};
Alexey Bataev18095712014-10-10 12:19:54 +000095
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000096/// \brief API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +000097class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000098public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000099 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000100 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000101 OpenMPDirectiveKind Kind, bool HasCancel)
102 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
103 HasCancel),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000104 ThreadIDVar(ThreadIDVar) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000105 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
106 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000107
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000108 /// \brief Get a variable or parameter for storing global thread id
109 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000110 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000111
Alexey Bataev18095712014-10-10 12:19:54 +0000112 /// \brief Get the name of the capture helper.
Benjamin Kramerc52193f2014-10-10 13:57:57 +0000113 StringRef getHelperName() const override { return ".omp_outlined."; }
Alexey Bataev18095712014-10-10 12:19:54 +0000114
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000115 static bool classof(const CGCapturedStmtInfo *Info) {
116 return CGOpenMPRegionInfo::classof(Info) &&
117 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
118 ParallelOutlinedRegion;
119 }
120
Alexey Bataev18095712014-10-10 12:19:54 +0000121private:
122 /// \brief A variable or parameter storing global thread id for OpenMP
123 /// constructs.
124 const VarDecl *ThreadIDVar;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000125};
126
Alexey Bataev62b63b12015-03-10 07:28:44 +0000127/// \brief API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000128class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000129public:
Alexey Bataev48591dd2016-04-20 04:01:36 +0000130 class UntiedTaskActionTy final : public PrePostActionTy {
131 bool Untied;
132 const VarDecl *PartIDVar;
133 const RegionCodeGenTy UntiedCodeGen;
134 llvm::SwitchInst *UntiedSwitch = nullptr;
135
136 public:
137 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
138 const RegionCodeGenTy &UntiedCodeGen)
139 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
140 void Enter(CodeGenFunction &CGF) override {
141 if (Untied) {
142 // Emit task switching point.
143 auto PartIdLVal = CGF.EmitLoadOfPointerLValue(
144 CGF.GetAddrOfLocalVar(PartIDVar),
145 PartIDVar->getType()->castAs<PointerType>());
146 auto *Res = CGF.EmitLoadOfScalar(PartIdLVal, SourceLocation());
147 auto *DoneBB = CGF.createBasicBlock(".untied.done.");
148 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
149 CGF.EmitBlock(DoneBB);
150 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
151 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
152 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
153 CGF.Builder.GetInsertBlock());
154 emitUntiedSwitch(CGF);
155 }
156 }
157 void emitUntiedSwitch(CodeGenFunction &CGF) const {
158 if (Untied) {
159 auto PartIdLVal = CGF.EmitLoadOfPointerLValue(
160 CGF.GetAddrOfLocalVar(PartIDVar),
161 PartIDVar->getType()->castAs<PointerType>());
162 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
163 PartIdLVal);
164 UntiedCodeGen(CGF);
165 CodeGenFunction::JumpDest CurPoint =
166 CGF.getJumpDestInCurrentScope(".untied.next.");
167 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
168 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
169 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
170 CGF.Builder.GetInsertBlock());
171 CGF.EmitBranchThroughCleanup(CurPoint);
172 CGF.EmitBlock(CurPoint.getBlock());
173 }
174 }
175 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
176 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000177 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000178 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000179 const RegionCodeGenTy &CodeGen,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000180 OpenMPDirectiveKind Kind, bool HasCancel,
181 const UntiedTaskActionTy &Action)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000182 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev48591dd2016-04-20 04:01:36 +0000183 ThreadIDVar(ThreadIDVar), Action(Action) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000184 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
185 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000186
Alexey Bataev62b63b12015-03-10 07:28:44 +0000187 /// \brief Get a variable or parameter for storing global thread id
188 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000189 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000190
191 /// \brief Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000192 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000193
Alexey Bataev62b63b12015-03-10 07:28:44 +0000194 /// \brief Get the name of the capture helper.
195 StringRef getHelperName() const override { return ".omp_outlined."; }
196
Alexey Bataev48591dd2016-04-20 04:01:36 +0000197 void emitUntiedSwitch(CodeGenFunction &CGF) override {
198 Action.emitUntiedSwitch(CGF);
199 }
200
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000201 static bool classof(const CGCapturedStmtInfo *Info) {
202 return CGOpenMPRegionInfo::classof(Info) &&
203 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
204 TaskOutlinedRegion;
205 }
206
Alexey Bataev62b63b12015-03-10 07:28:44 +0000207private:
208 /// \brief A variable or parameter storing global thread id for OpenMP
209 /// constructs.
210 const VarDecl *ThreadIDVar;
Alexey Bataev48591dd2016-04-20 04:01:36 +0000211 /// Action for emitting code for untied tasks.
212 const UntiedTaskActionTy &Action;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000213};
214
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000215/// \brief API for inlined captured statement code generation in OpenMP
216/// constructs.
217class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
218public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000219 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000220 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000221 OpenMPDirectiveKind Kind, bool HasCancel)
222 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
223 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000224 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000225
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000226 // \brief Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000227 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000228 if (OuterRegionInfo)
229 return OuterRegionInfo->getContextValue();
230 llvm_unreachable("No context value for inlined OpenMP region");
231 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000232
Hans Wennborg7eb54642015-09-10 17:07:54 +0000233 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000234 if (OuterRegionInfo) {
235 OuterRegionInfo->setContextValue(V);
236 return;
237 }
238 llvm_unreachable("No context value for inlined OpenMP region");
239 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000240
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000241 /// \brief Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000242 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000243 if (OuterRegionInfo)
244 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000245 // If there is no outer outlined region,no need to lookup in a list of
246 // captured variables, we can use the original one.
247 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000248 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000249
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000250 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000251 if (OuterRegionInfo)
252 return OuterRegionInfo->getThisFieldDecl();
253 return nullptr;
254 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000255
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000256 /// \brief Get a variable or parameter for storing global thread id
257 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000258 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000259 if (OuterRegionInfo)
260 return OuterRegionInfo->getThreadIDVariable();
261 return nullptr;
262 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000263
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000264 /// \brief Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000265 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000266 if (auto *OuterRegionInfo = getOldCSI())
267 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000268 llvm_unreachable("No helper name for inlined OpenMP construct");
269 }
270
Alexey Bataev48591dd2016-04-20 04:01:36 +0000271 void emitUntiedSwitch(CodeGenFunction &CGF) override {
272 if (OuterRegionInfo)
273 OuterRegionInfo->emitUntiedSwitch(CGF);
274 }
275
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000276 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
277
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000278 static bool classof(const CGCapturedStmtInfo *Info) {
279 return CGOpenMPRegionInfo::classof(Info) &&
280 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
281 }
282
Alexey Bataev48591dd2016-04-20 04:01:36 +0000283 ~CGOpenMPInlinedRegionInfo() override = default;
284
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000285private:
286 /// \brief CodeGen info about outer OpenMP region.
287 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
288 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000289};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000290
Samuel Antaobed3c462015-10-02 16:14:20 +0000291/// \brief API for captured statement code generation in OpenMP target
292/// constructs. For this captures, implicit parameters are used instead of the
Samuel Antaoee8fb302016-01-06 13:42:12 +0000293/// captured fields. The name of the target region has to be unique in a given
294/// application so it is provided by the client, because only the client has
295/// the information to generate that.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000296class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
Samuel Antaobed3c462015-10-02 16:14:20 +0000297public:
298 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000299 const RegionCodeGenTy &CodeGen, StringRef HelperName)
Samuel Antaobed3c462015-10-02 16:14:20 +0000300 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000301 /*HasCancel=*/false),
302 HelperName(HelperName) {}
Samuel Antaobed3c462015-10-02 16:14:20 +0000303
304 /// \brief This is unused for target regions because each starts executing
305 /// with a single thread.
306 const VarDecl *getThreadIDVariable() const override { return nullptr; }
307
308 /// \brief Get the name of the capture helper.
Samuel Antaoee8fb302016-01-06 13:42:12 +0000309 StringRef getHelperName() const override { return HelperName; }
Samuel Antaobed3c462015-10-02 16:14:20 +0000310
311 static bool classof(const CGCapturedStmtInfo *Info) {
312 return CGOpenMPRegionInfo::classof(Info) &&
313 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
314 }
Samuel Antaoee8fb302016-01-06 13:42:12 +0000315
316private:
317 StringRef HelperName;
Samuel Antaobed3c462015-10-02 16:14:20 +0000318};
319
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000320static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000321 llvm_unreachable("No codegen for expressions");
322}
323/// \brief API for generation of expressions captured in a innermost OpenMP
324/// region.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000325class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000326public:
327 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
328 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
329 OMPD_unknown,
330 /*HasCancel=*/false),
331 PrivScope(CGF) {
332 // Make sure the globals captured in the provided statement are local by
333 // using the privatization logic. We assume the same variable is not
334 // captured more than once.
335 for (auto &C : CS.captures()) {
336 if (!C.capturesVariable() && !C.capturesVariableByCopy())
337 continue;
338
339 const VarDecl *VD = C.getCapturedVar();
340 if (VD->isLocalVarDeclOrParm())
341 continue;
342
343 DeclRefExpr DRE(const_cast<VarDecl *>(VD),
344 /*RefersToEnclosingVariableOrCapture=*/false,
345 VD->getType().getNonReferenceType(), VK_LValue,
346 SourceLocation());
347 PrivScope.addPrivate(VD, [&CGF, &DRE]() -> Address {
348 return CGF.EmitLValue(&DRE).getAddress();
349 });
350 }
351 (void)PrivScope.Privatize();
352 }
353
354 /// \brief Lookup the captured field decl for a variable.
355 const FieldDecl *lookup(const VarDecl *VD) const override {
356 if (auto *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
357 return FD;
358 return nullptr;
359 }
360
361 /// \brief Emit the captured statement body.
362 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
363 llvm_unreachable("No body for expressions");
364 }
365
366 /// \brief Get a variable or parameter for storing global thread id
367 /// inside OpenMP construct.
368 const VarDecl *getThreadIDVariable() const override {
369 llvm_unreachable("No thread id for expressions");
370 }
371
372 /// \brief Get the name of the capture helper.
373 StringRef getHelperName() const override {
374 llvm_unreachable("No helper name for expressions");
375 }
376
377 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
378
379private:
380 /// Private scope to capture global variables.
381 CodeGenFunction::OMPPrivateScope PrivScope;
382};
383
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000384/// \brief RAII for emitting code of OpenMP constructs.
385class InlinedOpenMPRegionRAII {
386 CodeGenFunction &CGF;
387
388public:
389 /// \brief Constructs region for combined constructs.
390 /// \param CodeGen Code generation sequence for combined directives. Includes
391 /// a list of functions used for code generation of implicitly inlined
392 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000393 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000394 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000395 : CGF(CGF) {
396 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000397 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
398 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000399 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000400
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000401 ~InlinedOpenMPRegionRAII() {
402 // Restore original CapturedStmtInfo only if we're done with code emission.
403 auto *OldCSI =
404 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
405 delete CGF.CapturedStmtInfo;
406 CGF.CapturedStmtInfo = OldCSI;
407 }
408};
409
Alexey Bataev50b3c952016-02-19 10:38:26 +0000410/// \brief Values for bit flags used in the ident_t to describe the fields.
411/// All enumeric elements are named and described in accordance with the code
412/// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
413enum OpenMPLocationFlags {
414 /// \brief Use trampoline for internal microtask.
415 OMP_IDENT_IMD = 0x01,
416 /// \brief Use c-style ident structure.
417 OMP_IDENT_KMPC = 0x02,
418 /// \brief Atomic reduction option for kmpc_reduce.
419 OMP_ATOMIC_REDUCE = 0x10,
420 /// \brief Explicit 'barrier' directive.
421 OMP_IDENT_BARRIER_EXPL = 0x20,
422 /// \brief Implicit barrier in code.
423 OMP_IDENT_BARRIER_IMPL = 0x40,
424 /// \brief Implicit barrier in 'for' directive.
425 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
426 /// \brief Implicit barrier in 'sections' directive.
427 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
428 /// \brief Implicit barrier in 'single' directive.
429 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140
430};
431
432/// \brief Describes ident structure that describes a source location.
433/// All descriptions are taken from
434/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
435/// Original structure:
436/// typedef struct ident {
437/// kmp_int32 reserved_1; /**< might be used in Fortran;
438/// see above */
439/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
440/// KMP_IDENT_KMPC identifies this union
441/// member */
442/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
443/// see above */
444///#if USE_ITT_BUILD
445/// /* but currently used for storing
446/// region-specific ITT */
447/// /* contextual information. */
448///#endif /* USE_ITT_BUILD */
449/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
450/// C++ */
451/// char const *psource; /**< String describing the source location.
452/// The string is composed of semi-colon separated
453// fields which describe the source file,
454/// the function and a pair of line numbers that
455/// delimit the construct.
456/// */
457/// } ident_t;
458enum IdentFieldIndex {
459 /// \brief might be used in Fortran
460 IdentField_Reserved_1,
461 /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
462 IdentField_Flags,
463 /// \brief Not really used in Fortran any more
464 IdentField_Reserved_2,
465 /// \brief Source[4] in Fortran, do not use for C++
466 IdentField_Reserved_3,
467 /// \brief String describing the source location. The string is composed of
468 /// semi-colon separated fields which describe the source file, the function
469 /// and a pair of line numbers that delimit the construct.
470 IdentField_PSource
471};
472
473/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
474/// the enum sched_type in kmp.h).
475enum OpenMPSchedType {
476 /// \brief Lower bound for default (unordered) versions.
477 OMP_sch_lower = 32,
478 OMP_sch_static_chunked = 33,
479 OMP_sch_static = 34,
480 OMP_sch_dynamic_chunked = 35,
481 OMP_sch_guided_chunked = 36,
482 OMP_sch_runtime = 37,
483 OMP_sch_auto = 38,
484 /// \brief Lower bound for 'ordered' versions.
485 OMP_ord_lower = 64,
486 OMP_ord_static_chunked = 65,
487 OMP_ord_static = 66,
488 OMP_ord_dynamic_chunked = 67,
489 OMP_ord_guided_chunked = 68,
490 OMP_ord_runtime = 69,
491 OMP_ord_auto = 70,
492 OMP_sch_default = OMP_sch_static,
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000493 /// \brief dist_schedule types
494 OMP_dist_sch_static_chunked = 91,
495 OMP_dist_sch_static = 92,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000496};
497
498enum OpenMPRTLFunction {
499 /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
500 /// kmpc_micro microtask, ...);
501 OMPRTL__kmpc_fork_call,
502 /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc,
503 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
504 OMPRTL__kmpc_threadprivate_cached,
505 /// \brief Call to void __kmpc_threadprivate_register( ident_t *,
506 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
507 OMPRTL__kmpc_threadprivate_register,
508 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
509 OMPRTL__kmpc_global_thread_num,
510 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
511 // kmp_critical_name *crit);
512 OMPRTL__kmpc_critical,
513 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
514 // global_tid, kmp_critical_name *crit, uintptr_t hint);
515 OMPRTL__kmpc_critical_with_hint,
516 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
517 // kmp_critical_name *crit);
518 OMPRTL__kmpc_end_critical,
519 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
520 // global_tid);
521 OMPRTL__kmpc_cancel_barrier,
522 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
523 OMPRTL__kmpc_barrier,
524 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
525 OMPRTL__kmpc_for_static_fini,
526 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
527 // global_tid);
528 OMPRTL__kmpc_serialized_parallel,
529 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
530 // global_tid);
531 OMPRTL__kmpc_end_serialized_parallel,
532 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
533 // kmp_int32 num_threads);
534 OMPRTL__kmpc_push_num_threads,
535 // Call to void __kmpc_flush(ident_t *loc);
536 OMPRTL__kmpc_flush,
537 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
538 OMPRTL__kmpc_master,
539 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
540 OMPRTL__kmpc_end_master,
541 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
542 // int end_part);
543 OMPRTL__kmpc_omp_taskyield,
544 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
545 OMPRTL__kmpc_single,
546 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
547 OMPRTL__kmpc_end_single,
548 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
549 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
550 // kmp_routine_entry_t *task_entry);
551 OMPRTL__kmpc_omp_task_alloc,
552 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
553 // new_task);
554 OMPRTL__kmpc_omp_task,
555 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
556 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
557 // kmp_int32 didit);
558 OMPRTL__kmpc_copyprivate,
559 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
560 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
561 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
562 OMPRTL__kmpc_reduce,
563 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
564 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
565 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
566 // *lck);
567 OMPRTL__kmpc_reduce_nowait,
568 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
569 // kmp_critical_name *lck);
570 OMPRTL__kmpc_end_reduce,
571 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
572 // kmp_critical_name *lck);
573 OMPRTL__kmpc_end_reduce_nowait,
574 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
575 // kmp_task_t * new_task);
576 OMPRTL__kmpc_omp_task_begin_if0,
577 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
578 // kmp_task_t * new_task);
579 OMPRTL__kmpc_omp_task_complete_if0,
580 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
581 OMPRTL__kmpc_ordered,
582 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
583 OMPRTL__kmpc_end_ordered,
584 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
585 // global_tid);
586 OMPRTL__kmpc_omp_taskwait,
587 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
588 OMPRTL__kmpc_taskgroup,
589 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
590 OMPRTL__kmpc_end_taskgroup,
591 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
592 // int proc_bind);
593 OMPRTL__kmpc_push_proc_bind,
594 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
595 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
596 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
597 OMPRTL__kmpc_omp_task_with_deps,
598 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
599 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
600 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
601 OMPRTL__kmpc_omp_wait_deps,
602 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
603 // global_tid, kmp_int32 cncl_kind);
604 OMPRTL__kmpc_cancellationpoint,
605 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
606 // kmp_int32 cncl_kind);
607 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000608 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
609 // kmp_int32 num_teams, kmp_int32 thread_limit);
610 OMPRTL__kmpc_push_num_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000611 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
612 // microtask, ...);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000613 OMPRTL__kmpc_fork_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000614 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
615 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
616 // sched, kmp_uint64 grainsize, void *task_dup);
617 OMPRTL__kmpc_taskloop,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000618
619 //
620 // Offloading related calls
621 //
622 // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
623 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
624 // *arg_types);
625 OMPRTL__tgt_target,
Samuel Antaob68e2db2016-03-03 16:20:23 +0000626 // Call to int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
627 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
628 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
629 OMPRTL__tgt_target_teams,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000630 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
631 OMPRTL__tgt_register_lib,
632 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
633 OMPRTL__tgt_unregister_lib,
634};
635
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000636/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
637/// region.
638class CleanupTy final : public EHScopeStack::Cleanup {
639 PrePostActionTy *Action;
640
641public:
642 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
643 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
644 if (!CGF.HaveInsertPoint())
645 return;
646 Action->Exit(CGF);
647 }
648};
649
Hans Wennborg7eb54642015-09-10 17:07:54 +0000650} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000651
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000652void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
653 CodeGenFunction::RunCleanupsScope Scope(CGF);
654 if (PrePostAction) {
655 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
656 Callback(CodeGen, CGF, *PrePostAction);
657 } else {
658 PrePostActionTy Action;
659 Callback(CodeGen, CGF, Action);
660 }
661}
662
Alexey Bataev18095712014-10-10 12:19:54 +0000663LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +0000664 return CGF.EmitLoadOfPointerLValue(
665 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
666 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +0000667}
668
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000669void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000670 if (!CGF.HaveInsertPoint())
671 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000672 // 1.2.2 OpenMP Language Terminology
673 // Structured block - An executable statement with a single entry at the
674 // top and a single exit at the bottom.
675 // The point of exit cannot be a branch out of the structured block.
676 // longjmp() and throw() must not violate the entry/exit criteria.
677 CGF.EHStack.pushTerminate();
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000678 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000679 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000680}
681
Alexey Bataev62b63b12015-03-10 07:28:44 +0000682LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
683 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000684 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
685 getThreadIDVariable()->getType(),
686 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000687}
688
Alexey Bataev9959db52014-05-06 10:08:46 +0000689CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000690 : CGM(CGM), OffloadEntriesInfoManager(CGM) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000691 IdentTy = llvm::StructType::create(
692 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
693 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000694 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000695 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +0000696
697 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +0000698}
699
Alexey Bataev91797552015-03-18 04:13:55 +0000700void CGOpenMPRuntime::clear() {
701 InternalVars.clear();
702}
703
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000704static llvm::Function *
705emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
706 const Expr *CombinerInitializer, const VarDecl *In,
707 const VarDecl *Out, bool IsCombiner) {
708 // void .omp_combiner.(Ty *in, Ty *out);
709 auto &C = CGM.getContext();
710 QualType PtrTy = C.getPointerType(Ty).withRestrict();
711 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000712 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
713 /*Id=*/nullptr, PtrTy);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000714 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
715 /*Id=*/nullptr, PtrTy);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000716 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000717 Args.push_back(&OmpInParm);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000718 auto &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +0000719 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000720 auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
721 auto *Fn = llvm::Function::Create(
722 FnTy, llvm::GlobalValue::InternalLinkage,
723 IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
724 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000725 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000726 CodeGenFunction CGF(CGM);
727 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
728 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
729 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args);
730 CodeGenFunction::OMPPrivateScope Scope(CGF);
731 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
732 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() -> Address {
733 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
734 .getAddress();
735 });
736 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
737 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() -> Address {
738 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
739 .getAddress();
740 });
741 (void)Scope.Privatize();
742 CGF.EmitIgnoredExpr(CombinerInitializer);
743 Scope.ForceCleanup();
744 CGF.FinishFunction();
745 return Fn;
746}
747
748void CGOpenMPRuntime::emitUserDefinedReduction(
749 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
750 if (UDRMap.count(D) > 0)
751 return;
752 auto &C = CGM.getContext();
753 if (!In || !Out) {
754 In = &C.Idents.get("omp_in");
755 Out = &C.Idents.get("omp_out");
756 }
757 llvm::Function *Combiner = emitCombinerOrInitializer(
758 CGM, D->getType(), D->getCombiner(), cast<VarDecl>(D->lookup(In).front()),
759 cast<VarDecl>(D->lookup(Out).front()),
760 /*IsCombiner=*/true);
761 llvm::Function *Initializer = nullptr;
762 if (auto *Init = D->getInitializer()) {
763 if (!Priv || !Orig) {
764 Priv = &C.Idents.get("omp_priv");
765 Orig = &C.Idents.get("omp_orig");
766 }
767 Initializer = emitCombinerOrInitializer(
768 CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()),
769 cast<VarDecl>(D->lookup(Priv).front()),
770 /*IsCombiner=*/false);
771 }
772 UDRMap.insert(std::make_pair(D, std::make_pair(Combiner, Initializer)));
773 if (CGF) {
774 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
775 Decls.second.push_back(D);
776 }
777}
778
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000779std::pair<llvm::Function *, llvm::Function *>
780CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
781 auto I = UDRMap.find(D);
782 if (I != UDRMap.end())
783 return I->second;
784 emitUserDefinedReduction(/*CGF=*/nullptr, D);
785 return UDRMap.lookup(D);
786}
787
John McCall7f416cc2015-09-08 08:05:57 +0000788// Layout information for ident_t.
789static CharUnits getIdentAlign(CodeGenModule &CGM) {
790 return CGM.getPointerAlign();
791}
792static CharUnits getIdentSize(CodeGenModule &CGM) {
793 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign()));
794 return CharUnits::fromQuantity(16) + CGM.getPointerSize();
795}
Alexey Bataev50b3c952016-02-19 10:38:26 +0000796static CharUnits getOffsetOfIdentField(IdentFieldIndex Field) {
John McCall7f416cc2015-09-08 08:05:57 +0000797 // All the fields except the last are i32, so this works beautifully.
798 return unsigned(Field) * CharUnits::fromQuantity(4);
799}
800static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000801 IdentFieldIndex Field,
John McCall7f416cc2015-09-08 08:05:57 +0000802 const llvm::Twine &Name = "") {
803 auto Offset = getOffsetOfIdentField(Field);
804 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
805}
806
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000807llvm::Value *CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000808 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
809 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000810 assert(ThreadIDVar->getType()->isPointerType() &&
811 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +0000812 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
813 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +0000814 bool HasCancel = false;
815 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
816 HasCancel = OPD->hasCancel();
817 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
818 HasCancel = OPSD->hasCancel();
819 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
820 HasCancel = OPFD->hasCancel();
821 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
822 HasCancel);
Alexey Bataevd157d472015-06-24 03:35:38 +0000823 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000824 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +0000825}
826
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000827llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
828 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000829 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
830 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
831 bool Tied, unsigned &NumberOfParts) {
832 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
833 PrePostActionTy &) {
834 auto *ThreadID = getThreadID(CGF, D.getLocStart());
835 auto *UpLoc = emitUpdateLocation(CGF, D.getLocStart());
836 llvm::Value *TaskArgs[] = {
837 UpLoc, ThreadID,
838 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
839 TaskTVar->getType()->castAs<PointerType>())
840 .getPointer()};
841 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
842 };
843 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
844 UntiedCodeGen);
845 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000846 assert(!ThreadIDVar->getType()->isPointerType() &&
847 "thread id variable must be of type kmp_int32 for tasks");
848 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
Alexey Bataev7292c292016-04-25 12:22:29 +0000849 auto *TD = dyn_cast<OMPTaskDirective>(&D);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000850 CodeGenFunction CGF(CGM, true);
Alexey Bataev7292c292016-04-25 12:22:29 +0000851 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
852 InnermostKind,
853 TD ? TD->hasCancel() : false, Action);
Alexey Bataevd157d472015-06-24 03:35:38 +0000854 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev48591dd2016-04-20 04:01:36 +0000855 auto *Res = CGF.GenerateCapturedStmtFunction(*CS);
856 if (!Tied)
857 NumberOfParts = Action.getNumberOfParts();
858 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000859}
860
Alexey Bataev50b3c952016-02-19 10:38:26 +0000861Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
John McCall7f416cc2015-09-08 08:05:57 +0000862 CharUnits Align = getIdentAlign(CGM);
Alexey Bataev15007ba2014-05-07 06:18:01 +0000863 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000864 if (!Entry) {
865 if (!DefaultOpenMPPSource) {
866 // Initialize default location for psource field of ident_t structure of
867 // all ident_t objects. Format is ";file;function;line;column;;".
868 // Taken from
869 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
870 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +0000871 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000872 DefaultOpenMPPSource =
873 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
874 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000875 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
876 CGM.getModule(), IdentTy, /*isConstant*/ true,
877 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000878 DefaultOpenMPLocation->setUnnamedAddr(true);
John McCall7f416cc2015-09-08 08:05:57 +0000879 DefaultOpenMPLocation->setAlignment(Align.getQuantity());
Alexey Bataev9959db52014-05-06 10:08:46 +0000880
881 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000882 llvm::Constant *Values[] = {Zero,
883 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
884 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000885 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
886 DefaultOpenMPLocation->setInitializer(Init);
John McCall7f416cc2015-09-08 08:05:57 +0000887 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000888 }
John McCall7f416cc2015-09-08 08:05:57 +0000889 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +0000890}
891
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000892llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
893 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000894 unsigned Flags) {
895 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +0000896 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +0000897 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +0000898 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +0000899 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000900
901 assert(CGF.CurFn && "No function in current CodeGenFunction.");
902
John McCall7f416cc2015-09-08 08:05:57 +0000903 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000904 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
905 if (I != OpenMPLocThreadIDMap.end())
John McCall7f416cc2015-09-08 08:05:57 +0000906 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
907
Alexander Musmanc6388682014-12-15 07:07:06 +0000908 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
909 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +0000910 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000911 // Generate "ident_t .kmpc_loc.addr;"
John McCall7f416cc2015-09-08 08:05:57 +0000912 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
913 ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +0000914 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +0000915 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000916 LocValue = AI;
917
918 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
919 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000920 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
John McCall7f416cc2015-09-08 08:05:57 +0000921 CGM.getSize(getIdentSize(CGF.CGM)));
Alexey Bataev9959db52014-05-06 10:08:46 +0000922 }
923
924 // char **psource = &.kmpc_loc_<flags>.addr.psource;
John McCall7f416cc2015-09-08 08:05:57 +0000925 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000926
Alexey Bataevf002aca2014-05-30 05:48:40 +0000927 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
928 if (OMPDebugLoc == nullptr) {
929 SmallString<128> Buffer2;
930 llvm::raw_svector_ostream OS2(Buffer2);
931 // Build debug location
932 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
933 OS2 << ";" << PLoc.getFilename() << ";";
934 if (const FunctionDecl *FD =
935 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
936 OS2 << FD->getQualifiedNameAsString();
937 }
938 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
939 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
940 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000941 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000942 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000943 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
944
John McCall7f416cc2015-09-08 08:05:57 +0000945 // Our callers always pass this to a runtime function, so for
946 // convenience, go ahead and return a naked pointer.
947 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000948}
949
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000950llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
951 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000952 assert(CGF.CurFn && "No function in current CodeGenFunction.");
953
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000954 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000955 // Check whether we've already cached a load of the thread id in this
956 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000957 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000958 if (I != OpenMPLocThreadIDMap.end()) {
959 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000960 if (ThreadID != nullptr)
961 return ThreadID;
962 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +0000963 if (auto *OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000964 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000965 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000966 // Check if this an outlined function with thread id passed as argument.
967 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000968 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
969 // If value loaded in entry block, cache it and use it everywhere in
970 // function.
971 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
972 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
973 Elem.second.ThreadID = ThreadID;
974 }
975 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000976 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000977 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000978
979 // This is not an outlined function region - need to call __kmpc_int32
980 // kmpc_global_thread_num(ident_t *loc).
981 // Generate thread id value and cache this value for use across the
982 // function.
983 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
984 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
985 ThreadID =
986 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
987 emitUpdateLocation(CGF, Loc));
988 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
989 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000990 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000991}
992
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000993void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000994 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000995 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
996 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000997 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
998 for(auto *D : FunctionUDRMap[CGF.CurFn]) {
999 UDRMap.erase(D);
1000 }
1001 FunctionUDRMap.erase(CGF.CurFn);
1002 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001003}
1004
1005llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001006 if (!IdentTy) {
1007 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001008 return llvm::PointerType::getUnqual(IdentTy);
1009}
1010
1011llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001012 if (!Kmpc_MicroTy) {
1013 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1014 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1015 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1016 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1017 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001018 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1019}
1020
1021llvm::Constant *
Alexey Bataev50b3c952016-02-19 10:38:26 +00001022CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001023 llvm::Constant *RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001024 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001025 case OMPRTL__kmpc_fork_call: {
1026 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1027 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001028 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1029 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +00001030 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001031 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001032 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
1033 break;
1034 }
1035 case OMPRTL__kmpc_global_thread_num: {
1036 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001037 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +00001038 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001039 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001040 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1041 break;
1042 }
Alexey Bataev97720002014-11-11 04:05:39 +00001043 case OMPRTL__kmpc_threadprivate_cached: {
1044 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1045 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1046 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1047 CGM.VoidPtrTy, CGM.SizeTy,
1048 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
1049 llvm::FunctionType *FnTy =
1050 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1051 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1052 break;
1053 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001054 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001055 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1056 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001057 llvm::Type *TypeParams[] = {
1058 getIdentTyPointerTy(), CGM.Int32Ty,
1059 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1060 llvm::FunctionType *FnTy =
1061 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1062 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1063 break;
1064 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001065 case OMPRTL__kmpc_critical_with_hint: {
1066 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1067 // kmp_critical_name *crit, uintptr_t hint);
1068 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1069 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1070 CGM.IntPtrTy};
1071 llvm::FunctionType *FnTy =
1072 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1073 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1074 break;
1075 }
Alexey Bataev97720002014-11-11 04:05:39 +00001076 case OMPRTL__kmpc_threadprivate_register: {
1077 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1078 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1079 // typedef void *(*kmpc_ctor)(void *);
1080 auto KmpcCtorTy =
1081 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1082 /*isVarArg*/ false)->getPointerTo();
1083 // typedef void *(*kmpc_cctor)(void *, void *);
1084 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1085 auto KmpcCopyCtorTy =
1086 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
1087 /*isVarArg*/ false)->getPointerTo();
1088 // typedef void (*kmpc_dtor)(void *);
1089 auto KmpcDtorTy =
1090 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1091 ->getPointerTo();
1092 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1093 KmpcCopyCtorTy, KmpcDtorTy};
1094 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
1095 /*isVarArg*/ false);
1096 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1097 break;
1098 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001099 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001100 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1101 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001102 llvm::Type *TypeParams[] = {
1103 getIdentTyPointerTy(), CGM.Int32Ty,
1104 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1105 llvm::FunctionType *FnTy =
1106 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1107 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1108 break;
1109 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001110 case OMPRTL__kmpc_cancel_barrier: {
1111 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1112 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001113 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1114 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001115 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1116 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001117 break;
1118 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001119 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001120 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001121 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1122 llvm::FunctionType *FnTy =
1123 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1124 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1125 break;
1126 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001127 case OMPRTL__kmpc_for_static_fini: {
1128 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1129 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1130 llvm::FunctionType *FnTy =
1131 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1132 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1133 break;
1134 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001135 case OMPRTL__kmpc_push_num_threads: {
1136 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1137 // kmp_int32 num_threads)
1138 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1139 CGM.Int32Ty};
1140 llvm::FunctionType *FnTy =
1141 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1142 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1143 break;
1144 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001145 case OMPRTL__kmpc_serialized_parallel: {
1146 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1147 // global_tid);
1148 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1149 llvm::FunctionType *FnTy =
1150 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1151 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1152 break;
1153 }
1154 case OMPRTL__kmpc_end_serialized_parallel: {
1155 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1156 // global_tid);
1157 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1158 llvm::FunctionType *FnTy =
1159 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1160 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1161 break;
1162 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001163 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001164 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001165 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
1166 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001167 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001168 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1169 break;
1170 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001171 case OMPRTL__kmpc_master: {
1172 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1173 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1174 llvm::FunctionType *FnTy =
1175 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1176 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1177 break;
1178 }
1179 case OMPRTL__kmpc_end_master: {
1180 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1181 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1182 llvm::FunctionType *FnTy =
1183 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1184 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1185 break;
1186 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001187 case OMPRTL__kmpc_omp_taskyield: {
1188 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1189 // int end_part);
1190 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1191 llvm::FunctionType *FnTy =
1192 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1193 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1194 break;
1195 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001196 case OMPRTL__kmpc_single: {
1197 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1198 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1199 llvm::FunctionType *FnTy =
1200 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1201 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1202 break;
1203 }
1204 case OMPRTL__kmpc_end_single: {
1205 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1206 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1207 llvm::FunctionType *FnTy =
1208 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1209 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1210 break;
1211 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001212 case OMPRTL__kmpc_omp_task_alloc: {
1213 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1214 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1215 // kmp_routine_entry_t *task_entry);
1216 assert(KmpRoutineEntryPtrTy != nullptr &&
1217 "Type kmp_routine_entry_t must be created.");
1218 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1219 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1220 // Return void * and then cast to particular kmp_task_t type.
1221 llvm::FunctionType *FnTy =
1222 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1223 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1224 break;
1225 }
1226 case OMPRTL__kmpc_omp_task: {
1227 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1228 // *new_task);
1229 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1230 CGM.VoidPtrTy};
1231 llvm::FunctionType *FnTy =
1232 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1233 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
1234 break;
1235 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001236 case OMPRTL__kmpc_copyprivate: {
1237 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00001238 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001239 // kmp_int32 didit);
1240 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1241 auto *CpyFnTy =
1242 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001243 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001244 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
1245 CGM.Int32Ty};
1246 llvm::FunctionType *FnTy =
1247 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1248 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
1249 break;
1250 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001251 case OMPRTL__kmpc_reduce: {
1252 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
1253 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
1254 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
1255 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1256 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1257 /*isVarArg=*/false);
1258 llvm::Type *TypeParams[] = {
1259 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1260 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1261 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1262 llvm::FunctionType *FnTy =
1263 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1264 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
1265 break;
1266 }
1267 case OMPRTL__kmpc_reduce_nowait: {
1268 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
1269 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
1270 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
1271 // *lck);
1272 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1273 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1274 /*isVarArg=*/false);
1275 llvm::Type *TypeParams[] = {
1276 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1277 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1278 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1279 llvm::FunctionType *FnTy =
1280 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1281 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
1282 break;
1283 }
1284 case OMPRTL__kmpc_end_reduce: {
1285 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
1286 // kmp_critical_name *lck);
1287 llvm::Type *TypeParams[] = {
1288 getIdentTyPointerTy(), CGM.Int32Ty,
1289 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1290 llvm::FunctionType *FnTy =
1291 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1292 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
1293 break;
1294 }
1295 case OMPRTL__kmpc_end_reduce_nowait: {
1296 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
1297 // kmp_critical_name *lck);
1298 llvm::Type *TypeParams[] = {
1299 getIdentTyPointerTy(), CGM.Int32Ty,
1300 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1301 llvm::FunctionType *FnTy =
1302 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1303 RTLFn =
1304 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
1305 break;
1306 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001307 case OMPRTL__kmpc_omp_task_begin_if0: {
1308 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1309 // *new_task);
1310 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1311 CGM.VoidPtrTy};
1312 llvm::FunctionType *FnTy =
1313 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1314 RTLFn =
1315 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
1316 break;
1317 }
1318 case OMPRTL__kmpc_omp_task_complete_if0: {
1319 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1320 // *new_task);
1321 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1322 CGM.VoidPtrTy};
1323 llvm::FunctionType *FnTy =
1324 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1325 RTLFn = CGM.CreateRuntimeFunction(FnTy,
1326 /*Name=*/"__kmpc_omp_task_complete_if0");
1327 break;
1328 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001329 case OMPRTL__kmpc_ordered: {
1330 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
1331 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1332 llvm::FunctionType *FnTy =
1333 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1334 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
1335 break;
1336 }
1337 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001338 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001339 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1340 llvm::FunctionType *FnTy =
1341 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1342 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
1343 break;
1344 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00001345 case OMPRTL__kmpc_omp_taskwait: {
1346 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
1347 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1348 llvm::FunctionType *FnTy =
1349 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1350 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
1351 break;
1352 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001353 case OMPRTL__kmpc_taskgroup: {
1354 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
1355 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1356 llvm::FunctionType *FnTy =
1357 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1358 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
1359 break;
1360 }
1361 case OMPRTL__kmpc_end_taskgroup: {
1362 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
1363 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1364 llvm::FunctionType *FnTy =
1365 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1366 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
1367 break;
1368 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00001369 case OMPRTL__kmpc_push_proc_bind: {
1370 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
1371 // int proc_bind)
1372 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1373 llvm::FunctionType *FnTy =
1374 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1375 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
1376 break;
1377 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00001378 case OMPRTL__kmpc_omp_task_with_deps: {
1379 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
1380 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
1381 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
1382 llvm::Type *TypeParams[] = {
1383 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
1384 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
1385 llvm::FunctionType *FnTy =
1386 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1387 RTLFn =
1388 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
1389 break;
1390 }
1391 case OMPRTL__kmpc_omp_wait_deps: {
1392 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
1393 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
1394 // kmp_depend_info_t *noalias_dep_list);
1395 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1396 CGM.Int32Ty, CGM.VoidPtrTy,
1397 CGM.Int32Ty, CGM.VoidPtrTy};
1398 llvm::FunctionType *FnTy =
1399 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1400 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
1401 break;
1402 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00001403 case OMPRTL__kmpc_cancellationpoint: {
1404 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
1405 // global_tid, kmp_int32 cncl_kind)
1406 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1407 llvm::FunctionType *FnTy =
1408 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1409 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
1410 break;
1411 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001412 case OMPRTL__kmpc_cancel: {
1413 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
1414 // kmp_int32 cncl_kind)
1415 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1416 llvm::FunctionType *FnTy =
1417 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1418 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
1419 break;
1420 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00001421 case OMPRTL__kmpc_push_num_teams: {
1422 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
1423 // kmp_int32 num_teams, kmp_int32 num_threads)
1424 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1425 CGM.Int32Ty};
1426 llvm::FunctionType *FnTy =
1427 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1428 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
1429 break;
1430 }
1431 case OMPRTL__kmpc_fork_teams: {
1432 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
1433 // microtask, ...);
1434 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1435 getKmpc_MicroPointerTy()};
1436 llvm::FunctionType *FnTy =
1437 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
1438 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
1439 break;
1440 }
Alexey Bataev7292c292016-04-25 12:22:29 +00001441 case OMPRTL__kmpc_taskloop: {
1442 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
1443 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
1444 // sched, kmp_uint64 grainsize, void *task_dup);
1445 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
1446 CGM.IntTy,
1447 CGM.VoidPtrTy,
1448 CGM.IntTy,
1449 CGM.Int64Ty->getPointerTo(),
1450 CGM.Int64Ty->getPointerTo(),
1451 CGM.Int64Ty,
1452 CGM.IntTy,
1453 CGM.IntTy,
1454 CGM.Int64Ty,
1455 CGM.VoidPtrTy};
1456 llvm::FunctionType *FnTy =
1457 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1458 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
1459 break;
1460 }
Samuel Antaobed3c462015-10-02 16:14:20 +00001461 case OMPRTL__tgt_target: {
1462 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
1463 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
1464 // *arg_types);
1465 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1466 CGM.VoidPtrTy,
1467 CGM.Int32Ty,
1468 CGM.VoidPtrPtrTy,
1469 CGM.VoidPtrPtrTy,
1470 CGM.SizeTy->getPointerTo(),
1471 CGM.Int32Ty->getPointerTo()};
1472 llvm::FunctionType *FnTy =
1473 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1474 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
1475 break;
1476 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00001477 case OMPRTL__tgt_target_teams: {
1478 // Build int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
1479 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
1480 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
1481 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1482 CGM.VoidPtrTy,
1483 CGM.Int32Ty,
1484 CGM.VoidPtrPtrTy,
1485 CGM.VoidPtrPtrTy,
1486 CGM.SizeTy->getPointerTo(),
1487 CGM.Int32Ty->getPointerTo(),
1488 CGM.Int32Ty,
1489 CGM.Int32Ty};
1490 llvm::FunctionType *FnTy =
1491 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1492 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
1493 break;
1494 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00001495 case OMPRTL__tgt_register_lib: {
1496 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
1497 QualType ParamTy =
1498 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1499 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1500 llvm::FunctionType *FnTy =
1501 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1502 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
1503 break;
1504 }
1505 case OMPRTL__tgt_unregister_lib: {
1506 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
1507 QualType ParamTy =
1508 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1509 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1510 llvm::FunctionType *FnTy =
1511 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1512 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
1513 break;
1514 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001515 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00001516 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00001517 return RTLFn;
1518}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001519
Alexander Musman21212e42015-03-13 10:38:23 +00001520llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
1521 bool IVSigned) {
1522 assert((IVSize == 32 || IVSize == 64) &&
1523 "IV size is not compatible with the omp runtime");
1524 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
1525 : "__kmpc_for_static_init_4u")
1526 : (IVSigned ? "__kmpc_for_static_init_8"
1527 : "__kmpc_for_static_init_8u");
1528 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1529 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1530 llvm::Type *TypeParams[] = {
1531 getIdentTyPointerTy(), // loc
1532 CGM.Int32Ty, // tid
1533 CGM.Int32Ty, // schedtype
1534 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1535 PtrTy, // p_lower
1536 PtrTy, // p_upper
1537 PtrTy, // p_stride
1538 ITy, // incr
1539 ITy // chunk
1540 };
1541 llvm::FunctionType *FnTy =
1542 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1543 return CGM.CreateRuntimeFunction(FnTy, Name);
1544}
1545
Alexander Musman92bdaab2015-03-12 13:37:50 +00001546llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
1547 bool IVSigned) {
1548 assert((IVSize == 32 || IVSize == 64) &&
1549 "IV size is not compatible with the omp runtime");
1550 auto Name =
1551 IVSize == 32
1552 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
1553 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
1554 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1555 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
1556 CGM.Int32Ty, // tid
1557 CGM.Int32Ty, // schedtype
1558 ITy, // lower
1559 ITy, // upper
1560 ITy, // stride
1561 ITy // chunk
1562 };
1563 llvm::FunctionType *FnTy =
1564 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1565 return CGM.CreateRuntimeFunction(FnTy, Name);
1566}
1567
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001568llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
1569 bool IVSigned) {
1570 assert((IVSize == 32 || IVSize == 64) &&
1571 "IV size is not compatible with the omp runtime");
1572 auto Name =
1573 IVSize == 32
1574 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1575 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1576 llvm::Type *TypeParams[] = {
1577 getIdentTyPointerTy(), // loc
1578 CGM.Int32Ty, // tid
1579 };
1580 llvm::FunctionType *FnTy =
1581 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1582 return CGM.CreateRuntimeFunction(FnTy, Name);
1583}
1584
Alexander Musman92bdaab2015-03-12 13:37:50 +00001585llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
1586 bool IVSigned) {
1587 assert((IVSize == 32 || IVSize == 64) &&
1588 "IV size is not compatible with the omp runtime");
1589 auto Name =
1590 IVSize == 32
1591 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1592 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1593 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1594 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1595 llvm::Type *TypeParams[] = {
1596 getIdentTyPointerTy(), // loc
1597 CGM.Int32Ty, // tid
1598 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1599 PtrTy, // p_lower
1600 PtrTy, // p_upper
1601 PtrTy // p_stride
1602 };
1603 llvm::FunctionType *FnTy =
1604 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1605 return CGM.CreateRuntimeFunction(FnTy, Name);
1606}
1607
Alexey Bataev97720002014-11-11 04:05:39 +00001608llvm::Constant *
1609CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001610 assert(!CGM.getLangOpts().OpenMPUseTLS ||
1611 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00001612 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001613 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001614 Twine(CGM.getMangledName(VD)) + ".cache.");
1615}
1616
John McCall7f416cc2015-09-08 08:05:57 +00001617Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1618 const VarDecl *VD,
1619 Address VDAddr,
1620 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001621 if (CGM.getLangOpts().OpenMPUseTLS &&
1622 CGM.getContext().getTargetInfo().isTLSSupported())
1623 return VDAddr;
1624
John McCall7f416cc2015-09-08 08:05:57 +00001625 auto VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001626 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001627 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1628 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001629 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1630 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00001631 return Address(CGF.EmitRuntimeCall(
1632 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
1633 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00001634}
1635
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001636void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00001637 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00001638 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1639 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1640 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001641 auto OMPLoc = emitUpdateLocation(CGF, Loc);
1642 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00001643 OMPLoc);
1644 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1645 // to register constructor/destructor for variable.
1646 llvm::Value *Args[] = {OMPLoc,
John McCall7f416cc2015-09-08 08:05:57 +00001647 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1648 CGM.VoidPtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001649 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001650 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001651 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001652}
1653
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001654llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00001655 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00001656 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001657 if (CGM.getLangOpts().OpenMPUseTLS &&
1658 CGM.getContext().getTargetInfo().isTLSSupported())
1659 return nullptr;
1660
Alexey Bataev97720002014-11-11 04:05:39 +00001661 VD = VD->getDefinition(CGM.getContext());
1662 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
1663 ThreadPrivateWithDefinition.insert(VD);
1664 QualType ASTTy = VD->getType();
1665
1666 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1667 auto Init = VD->getAnyInitializer();
1668 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1669 // Generate function that re-emits the declaration's initializer into the
1670 // threadprivate copy of the variable VD
1671 CodeGenFunction CtorCGF(CGM);
1672 FunctionArgList Args;
1673 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1674 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1675 Args.push_back(&Dst);
1676
John McCallc56a8b32016-03-11 04:30:31 +00001677 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1678 CGM.getContext().VoidPtrTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001679 auto FTy = CGM.getTypes().GetFunctionType(FI);
1680 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001681 FTy, ".__kmpc_global_ctor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001682 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1683 Args, SourceLocation());
1684 auto ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001685 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001686 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00001687 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1688 Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
1689 CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00001690 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1691 /*IsInitializer=*/true);
1692 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001693 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001694 CGM.getContext().VoidPtrTy, Dst.getLocation());
1695 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1696 CtorCGF.FinishFunction();
1697 Ctor = Fn;
1698 }
1699 if (VD->getType().isDestructedType() != QualType::DK_none) {
1700 // Generate function that emits destructor call for the threadprivate copy
1701 // of the variable VD
1702 CodeGenFunction DtorCGF(CGM);
1703 FunctionArgList Args;
1704 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1705 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1706 Args.push_back(&Dst);
1707
John McCallc56a8b32016-03-11 04:30:31 +00001708 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1709 CGM.getContext().VoidTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001710 auto FTy = CGM.getTypes().GetFunctionType(FI);
1711 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001712 FTy, ".__kmpc_global_dtor_.", FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00001713 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00001714 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1715 SourceLocation());
Adrian Prantl1858c662016-04-24 22:22:29 +00001716 // Create a scope with an artificial location for the body of this function.
1717 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00001718 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1719 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00001720 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1721 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001722 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1723 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1724 DtorCGF.FinishFunction();
1725 Dtor = Fn;
1726 }
1727 // Do not emit init function if it is not required.
1728 if (!Ctor && !Dtor)
1729 return nullptr;
1730
1731 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1732 auto CopyCtorTy =
1733 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1734 /*isVarArg=*/false)->getPointerTo();
1735 // Copying constructor for the threadprivate variable.
1736 // Must be NULL - reserved by runtime, but currently it requires that this
1737 // parameter is always NULL. Otherwise it fires assertion.
1738 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1739 if (Ctor == nullptr) {
1740 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1741 /*isVarArg=*/false)->getPointerTo();
1742 Ctor = llvm::Constant::getNullValue(CtorTy);
1743 }
1744 if (Dtor == nullptr) {
1745 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1746 /*isVarArg=*/false)->getPointerTo();
1747 Dtor = llvm::Constant::getNullValue(DtorTy);
1748 }
1749 if (!CGF) {
1750 auto InitFunctionTy =
1751 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1752 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001753 InitFunctionTy, ".__omp_threadprivate_init_.",
1754 CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00001755 CodeGenFunction InitCGF(CGM);
1756 FunctionArgList ArgList;
1757 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1758 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1759 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001760 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001761 InitCGF.FinishFunction();
1762 return InitFunction;
1763 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001764 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001765 }
1766 return nullptr;
1767}
1768
Alexey Bataev1d677132015-04-22 13:57:31 +00001769/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1770/// function. Here is the logic:
1771/// if (Cond) {
1772/// ThenGen();
1773/// } else {
1774/// ElseGen();
1775/// }
1776static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1777 const RegionCodeGenTy &ThenGen,
1778 const RegionCodeGenTy &ElseGen) {
1779 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1780
1781 // If the condition constant folds and can be elided, try to avoid emitting
1782 // the condition and the dead arm of the if/else.
1783 bool CondConstant;
1784 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001785 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00001786 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001787 else
Alexey Bataev1d677132015-04-22 13:57:31 +00001788 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001789 return;
1790 }
1791
1792 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1793 // emit the conditional branch.
1794 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1795 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1796 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1797 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1798
1799 // Emit the 'then' code.
1800 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001801 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001802 CGF.EmitBranch(ContBlock);
1803 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001804 // There is no need to emit line number for unconditional branch.
1805 (void)ApplyDebugLocation::CreateEmpty(CGF);
1806 CGF.EmitBlock(ElseBlock);
1807 ElseGen(CGF);
1808 // There is no need to emit line number for unconditional branch.
1809 (void)ApplyDebugLocation::CreateEmpty(CGF);
1810 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00001811 // Emit the continuation block for code after the if.
1812 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001813}
1814
Alexey Bataev1d677132015-04-22 13:57:31 +00001815void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1816 llvm::Value *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001817 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00001818 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001819 if (!CGF.HaveInsertPoint())
1820 return;
Alexey Bataev1d677132015-04-22 13:57:31 +00001821 auto *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001822 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
1823 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001824 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001825 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00001826 llvm::Value *Args[] = {
1827 RTLoc,
1828 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001829 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00001830 llvm::SmallVector<llvm::Value *, 16> RealArgs;
1831 RealArgs.append(std::begin(Args), std::end(Args));
1832 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1833
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001834 auto RTLFn = RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001835 CGF.EmitRuntimeCall(RTLFn, RealArgs);
1836 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001837 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
1838 PrePostActionTy &) {
1839 auto &RT = CGF.CGM.getOpenMPRuntime();
1840 auto ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00001841 // Build calls:
1842 // __kmpc_serialized_parallel(&Loc, GTid);
1843 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001844 CGF.EmitRuntimeCall(
1845 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001846
Alexey Bataev1d677132015-04-22 13:57:31 +00001847 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001848 auto ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00001849 Address ZeroAddr =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001850 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
1851 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00001852 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00001853 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
1854 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
1855 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1856 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev1d677132015-04-22 13:57:31 +00001857 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001858
Alexey Bataev1d677132015-04-22 13:57:31 +00001859 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001860 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00001861 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001862 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
1863 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00001864 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001865 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00001866 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001867 else {
1868 RegionCodeGenTy ThenRCG(ThenGen);
1869 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00001870 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001871}
1872
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001873// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001874// thread-ID variable (it is passed in a first argument of the outlined function
1875// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1876// regular serial code region, get thread ID by calling kmp_int32
1877// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1878// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00001879Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
1880 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00001881 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001882 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001883 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001884 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001885
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001886 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001887 auto Int32Ty =
1888 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1889 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1890 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00001891 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00001892
1893 return ThreadIDTemp;
1894}
1895
Alexey Bataev97720002014-11-11 04:05:39 +00001896llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001897CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001898 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001899 SmallString<256> Buffer;
1900 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001901 Out << Name;
1902 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001903 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1904 if (Elem.second) {
1905 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001906 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001907 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001908 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001909
David Blaikie13156b62014-11-19 03:06:06 +00001910 return Elem.second = new llvm::GlobalVariable(
1911 CGM.getModule(), Ty, /*IsConstant*/ false,
1912 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1913 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001914}
1915
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001916llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001917 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001918 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001919}
1920
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001921namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001922/// Common pre(post)-action for different OpenMP constructs.
1923class CommonActionTy final : public PrePostActionTy {
1924 llvm::Value *EnterCallee;
1925 ArrayRef<llvm::Value *> EnterArgs;
1926 llvm::Value *ExitCallee;
1927 ArrayRef<llvm::Value *> ExitArgs;
1928 bool Conditional;
1929 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001930
1931public:
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001932 CommonActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs,
1933 llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs,
1934 bool Conditional = false)
1935 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1936 ExitArgs(ExitArgs), Conditional(Conditional) {}
1937 void Enter(CodeGenFunction &CGF) override {
1938 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
1939 if (Conditional) {
1940 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
1941 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1942 ContBlock = CGF.createBasicBlock("omp_if.end");
1943 // Generate the branch (If-stmt)
1944 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1945 CGF.EmitBlock(ThenBlock);
1946 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00001947 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001948 void Done(CodeGenFunction &CGF) {
1949 // Emit the rest of blocks/branches
1950 CGF.EmitBranch(ContBlock);
1951 CGF.EmitBlock(ContBlock, true);
1952 }
1953 void Exit(CodeGenFunction &CGF) override {
1954 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001955 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001956};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001957} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001958
1959void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1960 StringRef CriticalName,
1961 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00001962 SourceLocation Loc, const Expr *Hint) {
1963 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001964 // CriticalOpGen();
1965 // __kmpc_end_critical(ident_t *, gtid, Lock);
1966 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00001967 if (!CGF.HaveInsertPoint())
1968 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00001969 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1970 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001971 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
1972 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00001973 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001974 EnterArgs.push_back(CGF.Builder.CreateIntCast(
1975 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
1976 }
1977 CommonActionTy Action(
1978 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
1979 : OMPRTL__kmpc_critical),
1980 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
1981 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00001982 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001983}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001984
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001985void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001986 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001987 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001988 if (!CGF.HaveInsertPoint())
1989 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00001990 // if(__kmpc_master(ident_t *, gtid)) {
1991 // MasterOpGen();
1992 // __kmpc_end_master(ident_t *, gtid);
1993 // }
1994 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001995 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001996 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
1997 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
1998 /*Conditional=*/true);
1999 MasterOpGen.setAction(Action);
2000 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
2001 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00002002}
2003
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002004void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
2005 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002006 if (!CGF.HaveInsertPoint())
2007 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00002008 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
2009 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002010 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00002011 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002012 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00002013 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
2014 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00002015}
2016
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002017void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
2018 const RegionCodeGenTy &TaskgroupOpGen,
2019 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002020 if (!CGF.HaveInsertPoint())
2021 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002022 // __kmpc_taskgroup(ident_t *, gtid);
2023 // TaskgroupOpGen();
2024 // __kmpc_end_taskgroup(ident_t *, gtid);
2025 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002026 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2027 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
2028 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
2029 Args);
2030 TaskgroupOpGen.setAction(Action);
2031 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002032}
2033
John McCall7f416cc2015-09-08 08:05:57 +00002034/// Given an array of pointers to variables, project the address of a
2035/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002036static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
2037 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00002038 // Pull out the pointer to the variable.
2039 Address PtrAddr =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002040 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00002041 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
2042
2043 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002044 Addr = CGF.Builder.CreateElementBitCast(
2045 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00002046 return Addr;
2047}
2048
Alexey Bataeva63048e2015-03-23 06:18:07 +00002049static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00002050 CodeGenModule &CGM, llvm::Type *ArgsType,
2051 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
2052 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002053 auto &C = CGM.getContext();
2054 // void copy_func(void *LHSArg, void *RHSArg);
2055 FunctionArgList Args;
2056 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2057 C.VoidPtrTy);
2058 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2059 C.VoidPtrTy);
2060 Args.push_back(&LHSArg);
2061 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00002062 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002063 auto *Fn = llvm::Function::Create(
2064 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
2065 ".omp.copyprivate.copy_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002066 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002067 CodeGenFunction CGF(CGM);
2068 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00002069 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002070 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00002071 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2072 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2073 ArgsType), CGF.getPointerAlign());
2074 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2075 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2076 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00002077 // *(Type0*)Dst[0] = *(Type0*)Src[0];
2078 // *(Type1*)Dst[1] = *(Type1*)Src[1];
2079 // ...
2080 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00002081 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002082 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2083 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
2084
2085 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2086 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
2087
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002088 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2089 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00002090 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002091 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002092 CGF.FinishFunction();
2093 return Fn;
2094}
2095
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002096void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002097 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002098 SourceLocation Loc,
2099 ArrayRef<const Expr *> CopyprivateVars,
2100 ArrayRef<const Expr *> SrcExprs,
2101 ArrayRef<const Expr *> DstExprs,
2102 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002103 if (!CGF.HaveInsertPoint())
2104 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00002105 assert(CopyprivateVars.size() == SrcExprs.size() &&
2106 CopyprivateVars.size() == DstExprs.size() &&
2107 CopyprivateVars.size() == AssignmentOps.size());
2108 auto &C = CGM.getContext();
2109 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002110 // if(__kmpc_single(ident_t *, gtid)) {
2111 // SingleOpGen();
2112 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002113 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002114 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002115 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2116 // <copy_func>, did_it);
2117
John McCall7f416cc2015-09-08 08:05:57 +00002118 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00002119 if (!CopyprivateVars.empty()) {
2120 // int32 did_it = 0;
2121 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2122 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00002123 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002124 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002125 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00002126 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002127 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
2128 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
2129 /*Conditional=*/true);
2130 SingleOpGen.setAction(Action);
2131 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
2132 if (DidIt.isValid()) {
2133 // did_it = 1;
2134 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
2135 }
2136 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002137 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2138 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00002139 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002140 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
2141 auto CopyprivateArrayTy =
2142 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2143 /*IndexTypeQuals=*/0);
2144 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00002145 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002146 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
2147 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002148 Address Elem = CGF.Builder.CreateConstArrayGEP(
2149 CopyprivateList, I, CGF.getPointerSize());
2150 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00002151 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002152 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
2153 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002154 }
2155 // Build function that copies private values from single region to all other
2156 // threads in the corresponding parallel region.
2157 auto *CpyFn = emitCopyprivateCopyFunction(
2158 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00002159 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataev1189bd02016-01-26 12:20:39 +00002160 auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00002161 Address CL =
2162 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
2163 CGF.VoidPtrTy);
2164 auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002165 llvm::Value *Args[] = {
2166 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
2167 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00002168 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00002169 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00002170 CpyFn, // void (*) (void *, void *) <copy_func>
2171 DidItVal // i32 did_it
2172 };
2173 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
2174 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002175}
2176
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002177void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
2178 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00002179 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002180 if (!CGF.HaveInsertPoint())
2181 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002182 // __kmpc_ordered(ident_t *, gtid);
2183 // OrderedOpGen();
2184 // __kmpc_end_ordered(ident_t *, gtid);
2185 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00002186 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002187 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002188 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
2189 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
2190 Args);
2191 OrderedOpGen.setAction(Action);
2192 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2193 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002194 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00002195 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002196}
2197
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002198void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev25e5b442015-09-15 12:52:43 +00002199 OpenMPDirectiveKind Kind, bool EmitChecks,
2200 bool ForceSimpleCall) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002201 if (!CGF.HaveInsertPoint())
2202 return;
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00002203 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002204 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002205 unsigned Flags;
2206 if (Kind == OMPD_for)
2207 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2208 else if (Kind == OMPD_sections)
2209 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2210 else if (Kind == OMPD_single)
2211 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2212 else if (Kind == OMPD_barrier)
2213 Flags = OMP_IDENT_BARRIER_EXPL;
2214 else
2215 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002216 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
2217 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002218 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
2219 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002220 if (auto *OMPRegionInfo =
2221 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00002222 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002223 auto *Result = CGF.EmitRuntimeCall(
2224 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00002225 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002226 // if (__kmpc_cancel_barrier()) {
2227 // exit from construct;
2228 // }
2229 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
2230 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
2231 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
2232 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2233 CGF.EmitBlock(ExitBB);
2234 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00002235 auto CancelDestination =
2236 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002237 CGF.EmitBranchThroughCleanup(CancelDestination);
2238 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2239 }
2240 return;
2241 }
2242 }
2243 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002244}
2245
Alexander Musmanc6388682014-12-15 07:07:06 +00002246/// \brief Map the OpenMP loop schedule to the runtime enumeration.
2247static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002248 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002249 switch (ScheduleKind) {
2250 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002251 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2252 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00002253 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002254 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002255 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002256 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002257 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002258 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2259 case OMPC_SCHEDULE_auto:
2260 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00002261 case OMPC_SCHEDULE_unknown:
2262 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002263 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00002264 }
2265 llvm_unreachable("Unexpected runtime schedule");
2266}
2267
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002268/// \brief Map the OpenMP distribute schedule to the runtime enumeration.
2269static OpenMPSchedType
2270getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
2271 // only static is allowed for dist_schedule
2272 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2273}
2274
Alexander Musmanc6388682014-12-15 07:07:06 +00002275bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
2276 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002277 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00002278 return Schedule == OMP_sch_static;
2279}
2280
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002281bool CGOpenMPRuntime::isStaticNonchunked(
2282 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2283 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2284 return Schedule == OMP_dist_sch_static;
2285}
2286
2287
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002288bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002289 auto Schedule =
2290 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002291 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
2292 return Schedule != OMP_sch_static;
2293}
2294
John McCall7f416cc2015-09-08 08:05:57 +00002295void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
2296 SourceLocation Loc,
2297 OpenMPScheduleClauseKind ScheduleKind,
2298 unsigned IVSize, bool IVSigned,
2299 bool Ordered, llvm::Value *UB,
2300 llvm::Value *Chunk) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002301 if (!CGF.HaveInsertPoint())
2302 return;
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002303 OpenMPSchedType Schedule =
2304 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00002305 assert(Ordered ||
2306 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2307 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
2308 // Call __kmpc_dispatch_init(
2309 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
2310 // kmp_int[32|64] lower, kmp_int[32|64] upper,
2311 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002312
John McCall7f416cc2015-09-08 08:05:57 +00002313 // If the Chunk was not specified in the clause - use default value 1.
2314 if (Chunk == nullptr)
2315 Chunk = CGF.Builder.getIntN(IVSize, 1);
2316 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002317 emitUpdateLocation(CGF, Loc),
2318 getThreadID(CGF, Loc),
2319 CGF.Builder.getInt32(Schedule), // Schedule type
2320 CGF.Builder.getIntN(IVSize, 0), // Lower
2321 UB, // Upper
2322 CGF.Builder.getIntN(IVSize, 1), // Stride
2323 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00002324 };
2325 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
2326}
2327
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002328static void emitForStaticInitCall(CodeGenFunction &CGF,
2329 SourceLocation Loc,
2330 llvm::Value * UpdateLocation,
2331 llvm::Value * ThreadId,
2332 llvm::Constant * ForStaticInitFunction,
2333 OpenMPSchedType Schedule,
2334 unsigned IVSize, bool IVSigned, bool Ordered,
2335 Address IL, Address LB, Address UB,
2336 Address ST, llvm::Value *Chunk) {
2337 if (!CGF.HaveInsertPoint())
2338 return;
2339
2340 assert(!Ordered);
2341 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2342 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2343 Schedule == OMP_dist_sch_static ||
2344 Schedule == OMP_dist_sch_static_chunked);
2345
2346 // Call __kmpc_for_static_init(
2347 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
2348 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
2349 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
2350 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
2351 if (Chunk == nullptr) {
2352 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2353 Schedule == OMP_dist_sch_static) &&
2354 "expected static non-chunked schedule");
2355 // If the Chunk was not specified in the clause - use default value 1.
2356 Chunk = CGF.Builder.getIntN(IVSize, 1);
2357 } else {
2358 assert((Schedule == OMP_sch_static_chunked ||
2359 Schedule == OMP_ord_static_chunked ||
2360 Schedule == OMP_dist_sch_static_chunked) &&
2361 "expected static chunked schedule");
2362 }
2363 llvm::Value *Args[] = {
2364 UpdateLocation,
2365 ThreadId,
2366 CGF.Builder.getInt32(Schedule), // Schedule type
2367 IL.getPointer(), // &isLastIter
2368 LB.getPointer(), // &LB
2369 UB.getPointer(), // &UB
2370 ST.getPointer(), // &Stride
2371 CGF.Builder.getIntN(IVSize, 1), // Incr
2372 Chunk // Chunk
2373 };
2374 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
2375}
2376
John McCall7f416cc2015-09-08 08:05:57 +00002377void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
2378 SourceLocation Loc,
2379 OpenMPScheduleClauseKind ScheduleKind,
2380 unsigned IVSize, bool IVSigned,
2381 bool Ordered, Address IL, Address LB,
2382 Address UB, Address ST,
2383 llvm::Value *Chunk) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002384 OpenMPSchedType ScheduleNum = getRuntimeSchedule(ScheduleKind, Chunk != nullptr,
2385 Ordered);
2386 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2387 auto *ThreadId = getThreadID(CGF, Loc);
2388 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
2389 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction,
2390 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
2391}
John McCall7f416cc2015-09-08 08:05:57 +00002392
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002393void CGOpenMPRuntime::emitDistributeStaticInit(CodeGenFunction &CGF,
2394 SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind,
2395 unsigned IVSize, bool IVSigned,
2396 bool Ordered, Address IL, Address LB,
2397 Address UB, Address ST,
2398 llvm::Value *Chunk) {
2399 OpenMPSchedType ScheduleNum = getRuntimeSchedule(SchedKind, Chunk != nullptr);
2400 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2401 auto *ThreadId = getThreadID(CGF, Loc);
2402 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
2403 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction,
2404 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002405}
2406
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002407void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
2408 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002409 if (!CGF.HaveInsertPoint())
2410 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00002411 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002412 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002413 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
2414 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00002415}
2416
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002417void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
2418 SourceLocation Loc,
2419 unsigned IVSize,
2420 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002421 if (!CGF.HaveInsertPoint())
2422 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002423 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002424 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002425 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
2426}
2427
Alexander Musman92bdaab2015-03-12 13:37:50 +00002428llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
2429 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00002430 bool IVSigned, Address IL,
2431 Address LB, Address UB,
2432 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002433 // Call __kmpc_dispatch_next(
2434 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2435 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2436 // kmp_int[32|64] *p_stride);
2437 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002438 emitUpdateLocation(CGF, Loc),
2439 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002440 IL.getPointer(), // &isLastIter
2441 LB.getPointer(), // &Lower
2442 UB.getPointer(), // &Upper
2443 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00002444 };
2445 llvm::Value *Call =
2446 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
2447 return CGF.EmitScalarConversion(
2448 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00002449 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002450}
2451
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002452void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
2453 llvm::Value *NumThreads,
2454 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002455 if (!CGF.HaveInsertPoint())
2456 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00002457 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
2458 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002459 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00002460 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002461 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
2462 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00002463}
2464
Alexey Bataev7f210c62015-06-18 13:40:03 +00002465void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
2466 OpenMPProcBindClauseKind ProcBind,
2467 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002468 if (!CGF.HaveInsertPoint())
2469 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00002470 // Constants for proc bind value accepted by the runtime.
2471 enum ProcBindTy {
2472 ProcBindFalse = 0,
2473 ProcBindTrue,
2474 ProcBindMaster,
2475 ProcBindClose,
2476 ProcBindSpread,
2477 ProcBindIntel,
2478 ProcBindDefault
2479 } RuntimeProcBind;
2480 switch (ProcBind) {
2481 case OMPC_PROC_BIND_master:
2482 RuntimeProcBind = ProcBindMaster;
2483 break;
2484 case OMPC_PROC_BIND_close:
2485 RuntimeProcBind = ProcBindClose;
2486 break;
2487 case OMPC_PROC_BIND_spread:
2488 RuntimeProcBind = ProcBindSpread;
2489 break;
2490 case OMPC_PROC_BIND_unknown:
2491 llvm_unreachable("Unsupported proc_bind value.");
2492 }
2493 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
2494 llvm::Value *Args[] = {
2495 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2496 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
2497 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
2498}
2499
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002500void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
2501 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002502 if (!CGF.HaveInsertPoint())
2503 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00002504 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002505 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
2506 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00002507}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002508
Alexey Bataev62b63b12015-03-10 07:28:44 +00002509namespace {
2510/// \brief Indexes of fields for type kmp_task_t.
2511enum KmpTaskTFields {
2512 /// \brief List of shared variables.
2513 KmpTaskTShareds,
2514 /// \brief Task routine.
2515 KmpTaskTRoutine,
2516 /// \brief Partition id for the untied tasks.
2517 KmpTaskTPartId,
2518 /// \brief Function with call of destructors for private variables.
2519 KmpTaskTDestructors,
Alexey Bataev7292c292016-04-25 12:22:29 +00002520 /// (Taskloops only) Lower bound.
2521 KmpTaskTLowerBound,
2522 /// (Taskloops only) Upper bound.
2523 KmpTaskTUpperBound,
2524 /// (Taskloops only) Stride.
2525 KmpTaskTStride,
2526 /// (Taskloops only) Is last iteration flag.
2527 KmpTaskTLastIter,
Alexey Bataev62b63b12015-03-10 07:28:44 +00002528};
Hans Wennborg7eb54642015-09-10 17:07:54 +00002529} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00002530
Samuel Antaoee8fb302016-01-06 13:42:12 +00002531bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
2532 // FIXME: Add other entries type when they become supported.
2533 return OffloadEntriesTargetRegion.empty();
2534}
2535
2536/// \brief Initialize target region entry.
2537void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2538 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2539 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002540 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002541 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
2542 "only required for the device "
2543 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002544 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002545 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr);
2546 ++OffloadingEntriesNum;
2547}
2548
2549void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2550 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2551 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002552 llvm::Constant *Addr, llvm::Constant *ID) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002553 // If we are emitting code for a target, the entry is already initialized,
2554 // only has to be registered.
2555 if (CGM.getLangOpts().OpenMPIsDevice) {
Samuel Antao2de62b02016-02-13 23:35:10 +00002556 assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) &&
Samuel Antaoee8fb302016-01-06 13:42:12 +00002557 "Entry must exist.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002558 auto &Entry =
2559 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00002560 assert(Entry.isValid() && "Entry not initialized!");
2561 Entry.setAddress(Addr);
2562 Entry.setID(ID);
2563 return;
2564 } else {
2565 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID);
Samuel Antao2de62b02016-02-13 23:35:10 +00002566 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002567 }
2568}
2569
2570bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00002571 unsigned DeviceID, unsigned FileID, StringRef ParentName,
2572 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002573 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
2574 if (PerDevice == OffloadEntriesTargetRegion.end())
2575 return false;
2576 auto PerFile = PerDevice->second.find(FileID);
2577 if (PerFile == PerDevice->second.end())
2578 return false;
2579 auto PerParentName = PerFile->second.find(ParentName);
2580 if (PerParentName == PerFile->second.end())
2581 return false;
2582 auto PerLine = PerParentName->second.find(LineNum);
2583 if (PerLine == PerParentName->second.end())
2584 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002585 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00002586 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00002587 return false;
2588 return true;
2589}
2590
2591void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
2592 const OffloadTargetRegionEntryInfoActTy &Action) {
2593 // Scan all target region entries and perform the provided action.
2594 for (auto &D : OffloadEntriesTargetRegion)
2595 for (auto &F : D.second)
2596 for (auto &P : F.second)
2597 for (auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00002598 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002599}
2600
2601/// \brief Create a Ctor/Dtor-like function whose body is emitted through
2602/// \a Codegen. This is used to emit the two functions that register and
2603/// unregister the descriptor of the current compilation unit.
2604static llvm::Function *
2605createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
2606 const RegionCodeGenTy &Codegen) {
2607 auto &C = CGM.getContext();
2608 FunctionArgList Args;
2609 ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(),
2610 /*Id=*/nullptr, C.VoidPtrTy);
2611 Args.push_back(&DummyPtr);
2612
2613 CodeGenFunction CGF(CGM);
2614 GlobalDecl();
John McCallc56a8b32016-03-11 04:30:31 +00002615 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002616 auto FTy = CGM.getTypes().GetFunctionType(FI);
2617 auto *Fn =
2618 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation());
2619 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation());
2620 Codegen(CGF);
2621 CGF.FinishFunction();
2622 return Fn;
2623}
2624
2625llvm::Function *
2626CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
2627
2628 // If we don't have entries or if we are emitting code for the device, we
2629 // don't need to do anything.
2630 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
2631 return nullptr;
2632
2633 auto &M = CGM.getModule();
2634 auto &C = CGM.getContext();
2635
2636 // Get list of devices we care about
2637 auto &Devices = CGM.getLangOpts().OMPTargetTriples;
2638
2639 // We should be creating an offloading descriptor only if there are devices
2640 // specified.
2641 assert(!Devices.empty() && "No OpenMP offloading devices??");
2642
2643 // Create the external variables that will point to the begin and end of the
2644 // host entries section. These will be defined by the linker.
2645 auto *OffloadEntryTy =
2646 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
2647 llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable(
2648 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002649 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002650 ".omp_offloading.entries_begin");
2651 llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable(
2652 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002653 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002654 ".omp_offloading.entries_end");
2655
2656 // Create all device images
2657 llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires;
2658 auto *DeviceImageTy = cast<llvm::StructType>(
2659 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
2660
2661 for (unsigned i = 0; i < Devices.size(); ++i) {
2662 StringRef T = Devices[i].getTriple();
2663 auto *ImgBegin = new llvm::GlobalVariable(
2664 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002665 /*Initializer=*/nullptr,
2666 Twine(".omp_offloading.img_start.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002667 auto *ImgEnd = new llvm::GlobalVariable(
2668 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002669 /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002670
2671 llvm::Constant *Dev =
2672 llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd,
2673 HostEntriesBegin, HostEntriesEnd, nullptr);
2674 DeviceImagesEntires.push_back(Dev);
2675 }
2676
2677 // Create device images global array.
2678 llvm::ArrayType *DeviceImagesInitTy =
2679 llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size());
2680 llvm::Constant *DeviceImagesInit =
2681 llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires);
2682
2683 llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable(
2684 M, DeviceImagesInitTy, /*isConstant=*/true,
2685 llvm::GlobalValue::InternalLinkage, DeviceImagesInit,
2686 ".omp_offloading.device_images");
2687 DeviceImages->setUnnamedAddr(true);
2688
2689 // This is a Zero array to be used in the creation of the constant expressions
2690 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
2691 llvm::Constant::getNullValue(CGM.Int32Ty)};
2692
2693 // Create the target region descriptor.
2694 auto *BinaryDescriptorTy = cast<llvm::StructType>(
2695 CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
2696 llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get(
2697 BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
2698 llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages,
2699 Index),
2700 HostEntriesBegin, HostEntriesEnd, nullptr);
2701
2702 auto *Desc = new llvm::GlobalVariable(
2703 M, BinaryDescriptorTy, /*isConstant=*/true,
2704 llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit,
2705 ".omp_offloading.descriptor");
2706
2707 // Emit code to register or unregister the descriptor at execution
2708 // startup or closing, respectively.
2709
2710 // Create a variable to drive the registration and unregistration of the
2711 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
2712 auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var");
2713 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(),
2714 IdentInfo, C.CharTy);
2715
2716 auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002717 CGM, ".omp_offloading.descriptor_unreg",
2718 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002719 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
2720 Desc);
2721 });
2722 auto *RegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002723 CGM, ".omp_offloading.descriptor_reg",
2724 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002725 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib),
2726 Desc);
2727 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
2728 });
2729 return RegFn;
2730}
2731
Samuel Antao2de62b02016-02-13 23:35:10 +00002732void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID,
2733 llvm::Constant *Addr, uint64_t Size) {
2734 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00002735 auto *TgtOffloadEntryType = cast<llvm::StructType>(
2736 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()));
2737 llvm::LLVMContext &C = CGM.getModule().getContext();
2738 llvm::Module &M = CGM.getModule();
2739
2740 // Make sure the address has the right type.
Samuel Antao2de62b02016-02-13 23:35:10 +00002741 llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002742
2743 // Create constant string with the name.
2744 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
2745
2746 llvm::GlobalVariable *Str =
2747 new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true,
2748 llvm::GlobalValue::InternalLinkage, StrPtrInit,
2749 ".omp_offloading.entry_name");
2750 Str->setUnnamedAddr(true);
2751 llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy);
2752
2753 // Create the entry struct.
2754 llvm::Constant *EntryInit = llvm::ConstantStruct::get(
2755 TgtOffloadEntryType, AddrPtr, StrPtr,
2756 llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr);
2757 llvm::GlobalVariable *Entry = new llvm::GlobalVariable(
2758 M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage,
2759 EntryInit, ".omp_offloading.entry");
2760
2761 // The entry has to be created in the section the linker expects it to be.
2762 Entry->setSection(".omp_offloading.entries");
2763 // We can't have any padding between symbols, so we need to have 1-byte
2764 // alignment.
2765 Entry->setAlignment(1);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002766}
2767
2768void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
2769 // Emit the offloading entries and metadata so that the device codegen side
2770 // can
2771 // easily figure out what to emit. The produced metadata looks like this:
2772 //
2773 // !omp_offload.info = !{!1, ...}
2774 //
2775 // Right now we only generate metadata for function that contain target
2776 // regions.
2777
2778 // If we do not have entries, we dont need to do anything.
2779 if (OffloadEntriesInfoManager.empty())
2780 return;
2781
2782 llvm::Module &M = CGM.getModule();
2783 llvm::LLVMContext &C = M.getContext();
2784 SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
2785 OrderedEntries(OffloadEntriesInfoManager.size());
2786
2787 // Create the offloading info metadata node.
2788 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
2789
2790 // Auxiliar methods to create metadata values and strings.
2791 auto getMDInt = [&](unsigned v) {
2792 return llvm::ConstantAsMetadata::get(
2793 llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v));
2794 };
2795
2796 auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); };
2797
2798 // Create function that emits metadata for each target region entry;
2799 auto &&TargetRegionMetadataEmitter = [&](
2800 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002801 OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
2802 llvm::SmallVector<llvm::Metadata *, 32> Ops;
2803 // Generate metadata for target regions. Each entry of this metadata
2804 // contains:
2805 // - Entry 0 -> Kind of this type of metadata (0).
2806 // - Entry 1 -> Device ID of the file where the entry was identified.
2807 // - Entry 2 -> File ID of the file where the entry was identified.
2808 // - Entry 3 -> Mangled name of the function where the entry was identified.
2809 // - Entry 4 -> Line in the file where the entry was identified.
Samuel Antao2de62b02016-02-13 23:35:10 +00002810 // - Entry 5 -> Order the entry was created.
Samuel Antaoee8fb302016-01-06 13:42:12 +00002811 // The first element of the metadata node is the kind.
2812 Ops.push_back(getMDInt(E.getKind()));
2813 Ops.push_back(getMDInt(DeviceID));
2814 Ops.push_back(getMDInt(FileID));
2815 Ops.push_back(getMDString(ParentName));
2816 Ops.push_back(getMDInt(Line));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002817 Ops.push_back(getMDInt(E.getOrder()));
2818
2819 // Save this entry in the right position of the ordered entries array.
2820 OrderedEntries[E.getOrder()] = &E;
2821
2822 // Add metadata to the named metadata node.
2823 MD->addOperand(llvm::MDNode::get(C, Ops));
2824 };
2825
2826 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
2827 TargetRegionMetadataEmitter);
2828
2829 for (auto *E : OrderedEntries) {
2830 assert(E && "All ordered entries must exist!");
2831 if (auto *CE =
2832 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
2833 E)) {
2834 assert(CE->getID() && CE->getAddress() &&
2835 "Entry ID and Addr are invalid!");
Samuel Antao2de62b02016-02-13 23:35:10 +00002836 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002837 } else
2838 llvm_unreachable("Unsupported entry kind.");
2839 }
2840}
2841
2842/// \brief Loads all the offload entries information from the host IR
2843/// metadata.
2844void CGOpenMPRuntime::loadOffloadInfoMetadata() {
2845 // If we are in target mode, load the metadata from the host IR. This code has
2846 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
2847
2848 if (!CGM.getLangOpts().OpenMPIsDevice)
2849 return;
2850
2851 if (CGM.getLangOpts().OMPHostIRFile.empty())
2852 return;
2853
2854 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
2855 if (Buf.getError())
2856 return;
2857
2858 llvm::LLVMContext C;
2859 auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C);
2860
2861 if (ME.getError())
2862 return;
2863
2864 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
2865 if (!MD)
2866 return;
2867
2868 for (auto I : MD->operands()) {
2869 llvm::MDNode *MN = cast<llvm::MDNode>(I);
2870
2871 auto getMDInt = [&](unsigned Idx) {
2872 llvm::ConstantAsMetadata *V =
2873 cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
2874 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
2875 };
2876
2877 auto getMDString = [&](unsigned Idx) {
2878 llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx));
2879 return V->getString();
2880 };
2881
2882 switch (getMDInt(0)) {
2883 default:
2884 llvm_unreachable("Unexpected metadata!");
2885 break;
2886 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
2887 OFFLOAD_ENTRY_INFO_TARGET_REGION:
2888 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
2889 /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2),
2890 /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4),
Samuel Antao2de62b02016-02-13 23:35:10 +00002891 /*Order=*/getMDInt(5));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002892 break;
2893 }
2894 }
2895}
2896
Alexey Bataev62b63b12015-03-10 07:28:44 +00002897void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
2898 if (!KmpRoutineEntryPtrTy) {
2899 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
2900 auto &C = CGM.getContext();
2901 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
2902 FunctionProtoType::ExtProtoInfo EPI;
2903 KmpRoutineEntryPtrQTy = C.getPointerType(
2904 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2905 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
2906 }
2907}
2908
Alexey Bataevc71a4092015-09-11 10:29:41 +00002909static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
2910 QualType FieldTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002911 auto *Field = FieldDecl::Create(
2912 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
2913 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
2914 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
2915 Field->setAccess(AS_public);
2916 DC->addDecl(Field);
Alexey Bataevc71a4092015-09-11 10:29:41 +00002917 return Field;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002918}
2919
Samuel Antaoee8fb302016-01-06 13:42:12 +00002920QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
2921
2922 // Make sure the type of the entry is already created. This is the type we
2923 // have to create:
2924 // struct __tgt_offload_entry{
2925 // void *addr; // Pointer to the offload entry info.
2926 // // (function or global)
2927 // char *name; // Name of the function or global.
2928 // size_t size; // Size of the entry info (0 if it a function).
2929 // };
2930 if (TgtOffloadEntryQTy.isNull()) {
2931 ASTContext &C = CGM.getContext();
2932 auto *RD = C.buildImplicitRecord("__tgt_offload_entry");
2933 RD->startDefinition();
2934 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2935 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
2936 addFieldToRecordDecl(C, RD, C.getSizeType());
2937 RD->completeDefinition();
2938 TgtOffloadEntryQTy = C.getRecordType(RD);
2939 }
2940 return TgtOffloadEntryQTy;
2941}
2942
2943QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
2944 // These are the types we need to build:
2945 // struct __tgt_device_image{
2946 // void *ImageStart; // Pointer to the target code start.
2947 // void *ImageEnd; // Pointer to the target code end.
2948 // // We also add the host entries to the device image, as it may be useful
2949 // // for the target runtime to have access to that information.
2950 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
2951 // // the entries.
2952 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2953 // // entries (non inclusive).
2954 // };
2955 if (TgtDeviceImageQTy.isNull()) {
2956 ASTContext &C = CGM.getContext();
2957 auto *RD = C.buildImplicitRecord("__tgt_device_image");
2958 RD->startDefinition();
2959 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2960 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2961 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2962 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2963 RD->completeDefinition();
2964 TgtDeviceImageQTy = C.getRecordType(RD);
2965 }
2966 return TgtDeviceImageQTy;
2967}
2968
2969QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
2970 // struct __tgt_bin_desc{
2971 // int32_t NumDevices; // Number of devices supported.
2972 // __tgt_device_image *DeviceImages; // Arrays of device images
2973 // // (one per device).
2974 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
2975 // // entries.
2976 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2977 // // entries (non inclusive).
2978 // };
2979 if (TgtBinaryDescriptorQTy.isNull()) {
2980 ASTContext &C = CGM.getContext();
2981 auto *RD = C.buildImplicitRecord("__tgt_bin_desc");
2982 RD->startDefinition();
2983 addFieldToRecordDecl(
2984 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
2985 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
2986 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2987 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2988 RD->completeDefinition();
2989 TgtBinaryDescriptorQTy = C.getRecordType(RD);
2990 }
2991 return TgtBinaryDescriptorQTy;
2992}
2993
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002994namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00002995struct PrivateHelpersTy {
2996 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
2997 const VarDecl *PrivateElemInit)
2998 : Original(Original), PrivateCopy(PrivateCopy),
2999 PrivateElemInit(PrivateElemInit) {}
3000 const VarDecl *Original;
3001 const VarDecl *PrivateCopy;
3002 const VarDecl *PrivateElemInit;
3003};
3004typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00003005} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003006
Alexey Bataev9e034042015-05-05 04:05:12 +00003007static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00003008createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003009 if (!Privates.empty()) {
3010 auto &C = CGM.getContext();
3011 // Build struct .kmp_privates_t. {
3012 // /* private vars */
3013 // };
3014 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
3015 RD->startDefinition();
3016 for (auto &&Pair : Privates) {
Alexey Bataevc71a4092015-09-11 10:29:41 +00003017 auto *VD = Pair.second.Original;
3018 auto Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003019 Type = Type.getNonReferenceType();
Alexey Bataevc71a4092015-09-11 10:29:41 +00003020 auto *FD = addFieldToRecordDecl(C, RD, Type);
3021 if (VD->hasAttrs()) {
3022 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
3023 E(VD->getAttrs().end());
3024 I != E; ++I)
3025 FD->addAttr(*I);
3026 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003027 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003028 RD->completeDefinition();
3029 return RD;
3030 }
3031 return nullptr;
3032}
3033
Alexey Bataev9e034042015-05-05 04:05:12 +00003034static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00003035createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
3036 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003037 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003038 auto &C = CGM.getContext();
3039 // Build struct kmp_task_t {
3040 // void * shareds;
3041 // kmp_routine_entry_t routine;
3042 // kmp_int32 part_id;
3043 // kmp_routine_entry_t destructors;
Alexey Bataev7292c292016-04-25 12:22:29 +00003044 // For taskloops additional fields:
3045 // kmp_uint64 lb;
3046 // kmp_uint64 ub;
3047 // kmp_int64 st;
3048 // kmp_int32 liter;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003049 // };
3050 auto *RD = C.buildImplicitRecord("kmp_task_t");
3051 RD->startDefinition();
3052 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3053 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
3054 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3055 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00003056 if (isOpenMPTaskLoopDirective(Kind)) {
3057 QualType KmpUInt64Ty =
3058 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
3059 QualType KmpInt64Ty =
3060 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
3061 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
3062 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
3063 addFieldToRecordDecl(C, RD, KmpInt64Ty);
3064 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3065 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003066 RD->completeDefinition();
3067 return RD;
3068}
3069
3070static RecordDecl *
3071createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003072 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003073 auto &C = CGM.getContext();
3074 // Build struct kmp_task_t_with_privates {
3075 // kmp_task_t task_data;
3076 // .kmp_privates_t. privates;
3077 // };
3078 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
3079 RD->startDefinition();
3080 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003081 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
3082 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
3083 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003084 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003085 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003086}
3087
3088/// \brief Emit a proxy function which accepts kmp_task_t as the second
3089/// argument.
3090/// \code
3091/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003092/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00003093/// For taskloops:
3094/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003095/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003096/// return 0;
3097/// }
3098/// \endcode
3099static llvm::Value *
3100emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00003101 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
3102 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003103 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003104 QualType SharedsPtrTy, llvm::Value *TaskFunction,
3105 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003106 auto &C = CGM.getContext();
3107 FunctionArgList Args;
3108 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3109 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003110 /*Id=*/nullptr,
3111 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003112 Args.push_back(&GtidArg);
3113 Args.push_back(&TaskTypeArg);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003114 auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003115 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003116 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
3117 auto *TaskEntry =
3118 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
3119 ".omp_task_entry.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003120 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003121 CodeGenFunction CGF(CGM);
3122 CGF.disableDebugInfo();
3123 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
3124
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003125 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00003126 // tt,
3127 // For taskloops:
3128 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
3129 // tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003130 auto *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00003131 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00003132 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3133 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3134 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003135 auto *KmpTaskTWithPrivatesQTyRD =
3136 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003137 LValue Base =
3138 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003139 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
3140 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3141 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003142 auto *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003143
3144 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3145 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003146 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003147 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003148 CGF.ConvertTypeForMem(SharedsPtrTy));
3149
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003150 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3151 llvm::Value *PrivatesParam;
3152 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3153 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
3154 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003155 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00003156 } else
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003157 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003158
Alexey Bataev7292c292016-04-25 12:22:29 +00003159 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
3160 TaskPrivatesMap,
3161 CGF.Builder
3162 .CreatePointerBitCastOrAddrSpaceCast(
3163 TDBase.getAddress(), CGF.VoidPtrTy)
3164 .getPointer()};
3165 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
3166 std::end(CommonArgs));
3167 if (isOpenMPTaskLoopDirective(Kind)) {
3168 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3169 auto LBLVal = CGF.EmitLValueForField(Base, *LBFI);
3170 auto *LBParam = CGF.EmitLoadOfLValue(LBLVal, Loc).getScalarVal();
3171 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3172 auto UBLVal = CGF.EmitLValueForField(Base, *UBFI);
3173 auto *UBParam = CGF.EmitLoadOfLValue(UBLVal, Loc).getScalarVal();
3174 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3175 auto StLVal = CGF.EmitLValueForField(Base, *StFI);
3176 auto *StParam = CGF.EmitLoadOfLValue(StLVal, Loc).getScalarVal();
3177 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3178 auto LILVal = CGF.EmitLValueForField(Base, *LIFI);
3179 auto *LIParam = CGF.EmitLoadOfLValue(LILVal, Loc).getScalarVal();
3180 CallArgs.push_back(LBParam);
3181 CallArgs.push_back(UBParam);
3182 CallArgs.push_back(StParam);
3183 CallArgs.push_back(LIParam);
3184 }
3185 CallArgs.push_back(SharedsParam);
3186
Alexey Bataev62b63b12015-03-10 07:28:44 +00003187 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
3188 CGF.EmitStoreThroughLValue(
3189 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
John McCall7f416cc2015-09-08 08:05:57 +00003190 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00003191 CGF.FinishFunction();
3192 return TaskEntry;
3193}
3194
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003195static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
3196 SourceLocation Loc,
3197 QualType KmpInt32Ty,
3198 QualType KmpTaskTWithPrivatesPtrQTy,
3199 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003200 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003201 FunctionArgList Args;
3202 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3203 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003204 /*Id=*/nullptr,
3205 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003206 Args.push_back(&GtidArg);
3207 Args.push_back(&TaskTypeArg);
3208 FunctionType::ExtInfo Info;
3209 auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003210 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003211 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
3212 auto *DestructorFn =
3213 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3214 ".omp_task_destructor.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003215 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
3216 DestructorFnInfo);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003217 CodeGenFunction CGF(CGM);
3218 CGF.disableDebugInfo();
3219 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
3220 Args);
3221
Alexey Bataev31300ed2016-02-04 11:27:03 +00003222 LValue Base = CGF.EmitLoadOfPointerLValue(
3223 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3224 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003225 auto *KmpTaskTWithPrivatesQTyRD =
3226 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3227 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003228 Base = CGF.EmitLValueForField(Base, *FI);
3229 for (auto *Field :
3230 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3231 if (auto DtorKind = Field->getType().isDestructedType()) {
3232 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
3233 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3234 }
3235 }
3236 CGF.FinishFunction();
3237 return DestructorFn;
3238}
3239
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003240/// \brief Emit a privates mapping function for correct handling of private and
3241/// firstprivate variables.
3242/// \code
3243/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
3244/// **noalias priv1,..., <tyn> **noalias privn) {
3245/// *priv1 = &.privates.priv1;
3246/// ...;
3247/// *privn = &.privates.privn;
3248/// }
3249/// \endcode
3250static llvm::Value *
3251emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00003252 ArrayRef<const Expr *> PrivateVars,
3253 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003254 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003255 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003256 auto &C = CGM.getContext();
3257 FunctionArgList Args;
3258 ImplicitParamDecl TaskPrivatesArg(
3259 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3260 C.getPointerType(PrivatesQTy).withConst().withRestrict());
3261 Args.push_back(&TaskPrivatesArg);
3262 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
3263 unsigned Counter = 1;
3264 for (auto *E: PrivateVars) {
3265 Args.push_back(ImplicitParamDecl::Create(
3266 C, /*DC=*/nullptr, Loc,
3267 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3268 .withConst()
3269 .withRestrict()));
3270 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3271 PrivateVarsPos[VD] = Counter;
3272 ++Counter;
3273 }
3274 for (auto *E : FirstprivateVars) {
3275 Args.push_back(ImplicitParamDecl::Create(
3276 C, /*DC=*/nullptr, Loc,
3277 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3278 .withConst()
3279 .withRestrict()));
3280 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3281 PrivateVarsPos[VD] = Counter;
3282 ++Counter;
3283 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003284 auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003285 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003286 auto *TaskPrivatesMapTy =
3287 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
3288 auto *TaskPrivatesMap = llvm::Function::Create(
3289 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
3290 ".omp_task_privates_map.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003291 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
3292 TaskPrivatesMapFnInfo);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00003293 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003294 CodeGenFunction CGF(CGM);
3295 CGF.disableDebugInfo();
3296 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
3297 TaskPrivatesMapFnInfo, Args);
3298
3299 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00003300 LValue Base = CGF.EmitLoadOfPointerLValue(
3301 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
3302 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003303 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
3304 Counter = 0;
3305 for (auto *Field : PrivatesQTyRD->fields()) {
3306 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
3307 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
John McCall7f416cc2015-09-08 08:05:57 +00003308 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
Alexey Bataev31300ed2016-02-04 11:27:03 +00003309 auto RefLoadLVal = CGF.EmitLoadOfPointerLValue(
3310 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003311 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003312 ++Counter;
3313 }
3314 CGF.FinishFunction();
3315 return TaskPrivatesMap;
3316}
3317
Alexey Bataev9e034042015-05-05 04:05:12 +00003318static int array_pod_sort_comparator(const PrivateDataTy *P1,
3319 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003320 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
3321}
3322
Alexey Bataev7292c292016-04-25 12:22:29 +00003323CGOpenMPRuntime::TaskDataTy CGOpenMPRuntime::emitTaskInit(
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003324 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
3325 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
Alexey Bataev48591dd2016-04-20 04:01:36 +00003326 unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy,
Alexey Bataev7292c292016-04-25 12:22:29 +00003327 Address Shareds, ArrayRef<const Expr *> PrivateVars,
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003328 ArrayRef<const Expr *> PrivateCopies,
3329 ArrayRef<const Expr *> FirstprivateVars,
3330 ArrayRef<const Expr *> FirstprivateCopies,
Alexey Bataev7292c292016-04-25 12:22:29 +00003331 ArrayRef<const Expr *> FirstprivateInits) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003332 auto &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00003333 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003334 // Aggregate privates and sort them by the alignment.
Alexey Bataev9e034042015-05-05 04:05:12 +00003335 auto I = PrivateCopies.begin();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003336 for (auto *E : PrivateVars) {
3337 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3338 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003339 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003340 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3341 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003342 ++I;
3343 }
Alexey Bataev9e034042015-05-05 04:05:12 +00003344 I = FirstprivateCopies.begin();
3345 auto IElemInitRef = FirstprivateInits.begin();
3346 for (auto *E : FirstprivateVars) {
3347 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3348 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003349 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003350 PrivateHelpersTy(
3351 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3352 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
Richard Trieucc3949d2016-02-18 22:34:54 +00003353 ++I;
3354 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00003355 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003356 llvm::array_pod_sort(Privates.begin(), Privates.end(),
3357 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003358 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
3359 // Build type kmp_routine_entry_t (if not built yet).
3360 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003361 // Build type kmp_task_t (if not built yet).
3362 if (KmpTaskTQTy.isNull()) {
Alexey Bataev7292c292016-04-25 12:22:29 +00003363 KmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
3364 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003365 }
3366 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003367 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003368 auto *KmpTaskTWithPrivatesQTyRD =
3369 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
3370 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
3371 QualType KmpTaskTWithPrivatesPtrQTy =
3372 C.getPointerType(KmpTaskTWithPrivatesQTy);
3373 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
3374 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003375 auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003376 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
3377
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003378 // Emit initial values for private copies (if any).
3379 llvm::Value *TaskPrivatesMap = nullptr;
3380 auto *TaskPrivatesMapTy =
3381 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
3382 3)
3383 ->getType();
3384 if (!Privates.empty()) {
3385 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3386 TaskPrivatesMap = emitTaskPrivateMappingFunction(
3387 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
3388 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3389 TaskPrivatesMap, TaskPrivatesMapTy);
3390 } else {
3391 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3392 cast<llvm::PointerType>(TaskPrivatesMapTy));
3393 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003394 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
3395 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003396 auto *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00003397 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3398 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3399 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003400
3401 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
3402 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
3403 // kmp_routine_entry_t *task_entry);
3404 // Task flags. Format is taken from
3405 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
3406 // description of kmp_tasking_flags struct.
3407 const unsigned TiedFlag = 0x1;
3408 const unsigned FinalFlag = 0x2;
3409 unsigned Flags = Tied ? TiedFlag : 0;
3410 auto *TaskFlags =
3411 Final.getPointer()
3412 ? CGF.Builder.CreateSelect(Final.getPointer(),
3413 CGF.Builder.getInt32(FinalFlag),
3414 CGF.Builder.getInt32(/*C=*/0))
3415 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
3416 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataev40e36f12015-11-24 13:01:44 +00003417 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003418 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
3419 getThreadID(CGF, Loc), TaskFlags,
3420 KmpTaskTWithPrivatesTySize, SharedsSize,
3421 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3422 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003423 auto *NewTask = CGF.EmitRuntimeCall(
3424 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003425 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3426 NewTask, KmpTaskTWithPrivatesPtrTy);
3427 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
3428 KmpTaskTWithPrivatesQTy);
3429 LValue TDBase =
3430 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003431 // Fill the data in the resulting kmp_task_t record.
3432 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00003433 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003434 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003435 KmpTaskSharedsPtr =
3436 Address(CGF.EmitLoadOfScalar(
3437 CGF.EmitLValueForField(
3438 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
3439 KmpTaskTShareds)),
3440 Loc),
3441 CGF.getNaturalTypeAlignment(SharedsTy));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003442 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003443 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003444 // Emit initial values for private copies (if any).
3445 bool NeedsCleanup = false;
3446 if (!Privates.empty()) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003447 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3448 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003449 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003450 LValue SharedsBase;
3451 if (!FirstprivateVars.empty()) {
John McCall7f416cc2015-09-08 08:05:57 +00003452 SharedsBase = CGF.MakeAddrLValue(
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003453 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3454 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
3455 SharedsTy);
3456 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003457 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
3458 cast<CapturedStmt>(*D.getAssociatedStmt()));
3459 for (auto &&Pair : Privates) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003460 auto *VD = Pair.second.PrivateCopy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003461 auto *Init = VD->getAnyInitializer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003462 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003463 if (Init) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003464 if (auto *Elem = Pair.second.PrivateElemInit) {
3465 auto *OriginalVD = Pair.second.Original;
3466 auto *SharedField = CapturesInfo.lookup(OriginalVD);
3467 auto SharedRefLValue =
3468 CGF.EmitLValueForField(SharedsBase, SharedField);
Alexey Bataevc71a4092015-09-11 10:29:41 +00003469 SharedRefLValue = CGF.MakeAddrLValue(
3470 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
3471 SharedRefLValue.getType(), AlignmentSource::Decl);
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003472 QualType Type = OriginalVD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003473 if (Type->isArrayType()) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003474 // Initialize firstprivate array.
3475 if (!isa<CXXConstructExpr>(Init) ||
3476 CGF.isTrivialInitializer(Init)) {
3477 // Perform simple memcpy.
3478 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003479 SharedRefLValue.getAddress(), Type);
Alexey Bataev9e034042015-05-05 04:05:12 +00003480 } else {
3481 // Initialize firstprivate array using element-by-element
3482 // intialization.
3483 CGF.EmitOMPAggregateAssign(
3484 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003485 Type, [&CGF, Elem, Init, &CapturesInfo](
John McCall7f416cc2015-09-08 08:05:57 +00003486 Address DestElement, Address SrcElement) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003487 // Clean up any temporaries needed by the initialization.
3488 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003489 InitScope.addPrivate(Elem, [SrcElement]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003490 return SrcElement;
3491 });
3492 (void)InitScope.Privatize();
3493 // Emit initialization for single element.
Alexey Bataevd157d472015-06-24 03:35:38 +00003494 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3495 CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003496 CGF.EmitAnyExprToMem(Init, DestElement,
3497 Init->getType().getQualifiers(),
3498 /*IsInitializer=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003499 });
3500 }
3501 } else {
3502 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003503 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003504 return SharedRefLValue.getAddress();
3505 });
3506 (void)InitScope.Privatize();
Alexey Bataevd157d472015-06-24 03:35:38 +00003507 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003508 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
3509 /*capturedByInit=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003510 }
3511 } else {
3512 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
3513 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003514 }
3515 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003516 ++FI;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003517 }
3518 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003519 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003520 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003521 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
3522 KmpTaskTWithPrivatesPtrQTy,
3523 KmpTaskTWithPrivatesQTy)
3524 : llvm::ConstantPointerNull::get(
3525 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
3526 LValue Destructor = CGF.EmitLValueForField(
3527 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
3528 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3529 DestructorFn, KmpRoutineEntryPtrTy),
3530 Destructor);
Alexey Bataev7292c292016-04-25 12:22:29 +00003531 TaskDataTy Data;
3532 Data.NewTask = NewTask;
3533 Data.TaskEntry = TaskEntry;
3534 Data.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
3535 Data.TDBase = TDBase;
3536 Data.KmpTaskTQTyRD = KmpTaskTQTyRD;
3537 return Data;
3538}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003539
Alexey Bataev7292c292016-04-25 12:22:29 +00003540void CGOpenMPRuntime::emitTaskCall(
3541 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
3542 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
3543 unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy,
3544 Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
3545 ArrayRef<const Expr *> PrivateCopies,
3546 ArrayRef<const Expr *> FirstprivateVars,
3547 ArrayRef<const Expr *> FirstprivateCopies,
3548 ArrayRef<const Expr *> FirstprivateInits,
3549 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
3550 if (!CGF.HaveInsertPoint())
3551 return;
3552
3553 TaskDataTy Data =
3554 emitTaskInit(CGF, Loc, D, Tied, Final, NumberOfParts, TaskFunction,
3555 SharedsTy, Shareds, PrivateVars, PrivateCopies,
3556 FirstprivateVars, FirstprivateCopies, FirstprivateInits);
3557 llvm::Value *NewTask = Data.NewTask;
3558 llvm::Value *TaskEntry = Data.TaskEntry;
3559 llvm::Value *NewTaskNewTaskTTy = Data.NewTaskNewTaskTTy;
3560 LValue TDBase = Data.TDBase;
3561 RecordDecl *KmpTaskTQTyRD = Data.KmpTaskTQTyRD;
3562 auto &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003563 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00003564 Address DependenciesArray = Address::invalid();
3565 unsigned NumDependencies = Dependences.size();
3566 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003567 // Dependence kind for RTL.
Alexey Bataev92e82f92015-11-23 13:33:42 +00003568 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003569 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
3570 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003571 QualType FlagsTy =
3572 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003573 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
3574 if (KmpDependInfoTy.isNull()) {
3575 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
3576 KmpDependInfoRD->startDefinition();
3577 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
3578 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
3579 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
3580 KmpDependInfoRD->completeDefinition();
3581 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
3582 } else {
3583 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
3584 }
John McCall7f416cc2015-09-08 08:05:57 +00003585 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003586 // Define type kmp_depend_info[<Dependences.size()>];
3587 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00003588 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003589 ArrayType::Normal, /*IndexTypeQuals=*/0);
3590 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00003591 DependenciesArray =
3592 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
John McCall7f416cc2015-09-08 08:05:57 +00003593 for (unsigned i = 0; i < NumDependencies; ++i) {
3594 const Expr *E = Dependences[i].second;
3595 auto Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003596 llvm::Value *Size;
3597 QualType Ty = E->getType();
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003598 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
3599 LValue UpAddrLVal =
3600 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
3601 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00003602 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003603 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00003604 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003605 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
3606 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003607 } else
Alexey Bataev1189bd02016-01-26 12:20:39 +00003608 Size = CGF.getTypeSize(Ty);
John McCall7f416cc2015-09-08 08:05:57 +00003609 auto Base = CGF.MakeAddrLValue(
3610 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003611 KmpDependInfoTy);
3612 // deps[i].base_addr = &<Dependences[i].second>;
3613 auto BaseAddrLVal = CGF.EmitLValueForField(
3614 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00003615 CGF.EmitStoreOfScalar(
3616 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
3617 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003618 // deps[i].len = sizeof(<Dependences[i].second>);
3619 auto LenLVal = CGF.EmitLValueForField(
3620 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
3621 CGF.EmitStoreOfScalar(Size, LenLVal);
3622 // deps[i].flags = <Dependences[i].first>;
3623 RTLDependenceKindTy DepKind;
3624 switch (Dependences[i].first) {
3625 case OMPC_DEPEND_in:
3626 DepKind = DepIn;
3627 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00003628 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003629 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003630 case OMPC_DEPEND_inout:
3631 DepKind = DepInOut;
3632 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00003633 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00003634 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003635 case OMPC_DEPEND_unknown:
3636 llvm_unreachable("Unknown task dependence type");
3637 }
3638 auto FlagsLVal = CGF.EmitLValueForField(
3639 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
3640 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
3641 FlagsLVal);
3642 }
John McCall7f416cc2015-09-08 08:05:57 +00003643 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3644 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003645 CGF.VoidPtrTy);
3646 }
3647
Alexey Bataev62b63b12015-03-10 07:28:44 +00003648 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
3649 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003650 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
3651 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
3652 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
3653 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00003654 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003655 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00003656 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
3657 llvm::Value *DepTaskArgs[7];
3658 if (NumDependencies) {
3659 DepTaskArgs[0] = UpLoc;
3660 DepTaskArgs[1] = ThreadID;
3661 DepTaskArgs[2] = NewTask;
3662 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
3663 DepTaskArgs[4] = DependenciesArray.getPointer();
3664 DepTaskArgs[5] = CGF.Builder.getInt32(0);
3665 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3666 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00003667 auto &&ThenCodeGen = [this, Tied, Loc, NumberOfParts, TDBase, KmpTaskTQTyRD,
3668 NumDependencies, &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003669 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003670 if (!Tied) {
3671 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3672 auto PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
3673 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
3674 }
John McCall7f416cc2015-09-08 08:05:57 +00003675 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003676 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00003677 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00003678 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003679 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00003680 TaskArgs);
3681 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00003682 // Check if parent region is untied and build return for untied task;
3683 if (auto *Region =
3684 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3685 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003686 };
John McCall7f416cc2015-09-08 08:05:57 +00003687
3688 llvm::Value *DepWaitTaskArgs[6];
3689 if (NumDependencies) {
3690 DepWaitTaskArgs[0] = UpLoc;
3691 DepWaitTaskArgs[1] = ThreadID;
3692 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
3693 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
3694 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
3695 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3696 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003697 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
3698 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF,
3699 PrePostActionTy &) {
3700 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003701 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
3702 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
3703 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
3704 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
3705 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00003706 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003707 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003708 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003709 // Call proxy_task_entry(gtid, new_task);
3710 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy](
3711 CodeGenFunction &CGF, PrePostActionTy &Action) {
3712 Action.Enter(CGF);
3713 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
3714 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
3715 };
3716
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003717 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
3718 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003719 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
3720 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003721 RegionCodeGenTy RCG(CodeGen);
3722 CommonActionTy Action(
3723 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
3724 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
3725 RCG.setAction(Action);
3726 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003727 };
John McCall7f416cc2015-09-08 08:05:57 +00003728
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003729 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00003730 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003731 else {
3732 RegionCodeGenTy ThenRCG(ThenCodeGen);
3733 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003734 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003735}
3736
Alexey Bataev7292c292016-04-25 12:22:29 +00003737void CGOpenMPRuntime::emitTaskLoopCall(
3738 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
3739 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, bool Nogroup,
3740 unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy,
3741 Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
3742 ArrayRef<const Expr *> PrivateCopies,
3743 ArrayRef<const Expr *> FirstprivateVars,
3744 ArrayRef<const Expr *> FirstprivateCopies,
3745 ArrayRef<const Expr *> FirstprivateInits) {
3746 if (!CGF.HaveInsertPoint())
3747 return;
3748 TaskDataTy Data =
3749 emitTaskInit(CGF, Loc, D, Tied, Final, NumberOfParts, TaskFunction,
3750 SharedsTy, Shareds, PrivateVars, PrivateCopies,
3751 FirstprivateVars, FirstprivateCopies, FirstprivateInits);
3752 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
3753 // libcall.
3754 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
3755 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
3756 // sched, kmp_uint64 grainsize, void *task_dup);
3757 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3758 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
3759 llvm::Value *IfVal;
3760 if (IfCond) {
3761 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
3762 /*isSigned=*/true);
3763 } else
3764 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
3765
3766 LValue LBLVal = CGF.EmitLValueForField(
3767 Data.TDBase,
3768 *std::next(Data.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
3769 auto *LBVar =
3770 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
3771 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
3772 /*IsInitializer=*/true);
3773 LValue UBLVal = CGF.EmitLValueForField(
3774 Data.TDBase,
3775 *std::next(Data.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
3776 auto *UBVar =
3777 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
3778 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
3779 /*IsInitializer=*/true);
3780 LValue StLVal = CGF.EmitLValueForField(
3781 Data.TDBase,
3782 *std::next(Data.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
3783 auto *StVar =
3784 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
3785 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
3786 /*IsInitializer=*/true);
3787 llvm::Value *TaskArgs[] = {
3788 UpLoc,
3789 ThreadID,
3790 Data.NewTask,
3791 IfVal,
3792 LBLVal.getPointer(),
3793 UBLVal.getPointer(),
3794 CGF.EmitLoadOfScalar(StLVal, SourceLocation()),
3795 llvm::ConstantInt::getSigned(CGF.IntTy, Nogroup ? 1 : 0),
3796 llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/0),
3797 llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
3798 llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
3799 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
3800}
3801
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003802/// \brief Emit reduction operation for each element of array (required for
3803/// array sections) LHS op = RHS.
3804/// \param Type Type of array.
3805/// \param LHSVar Variable on the left side of the reduction operation
3806/// (references element of array in original variable).
3807/// \param RHSVar Variable on the right side of the reduction operation
3808/// (references element of array in original variable).
3809/// \param RedOpGen Generator of reduction operation with use of LHSVar and
3810/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00003811static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003812 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
3813 const VarDecl *RHSVar,
3814 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
3815 const Expr *, const Expr *)> &RedOpGen,
3816 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
3817 const Expr *UpExpr = nullptr) {
3818 // Perform element-by-element initialization.
3819 QualType ElementTy;
3820 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
3821 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
3822
3823 // Drill down to the base element type on both arrays.
3824 auto ArrayTy = Type->getAsArrayTypeUnsafe();
3825 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
3826
3827 auto RHSBegin = RHSAddr.getPointer();
3828 auto LHSBegin = LHSAddr.getPointer();
3829 // Cast from pointer to array type to pointer to single element.
3830 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
3831 // The basic structure here is a while-do loop.
3832 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
3833 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
3834 auto IsEmpty =
3835 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
3836 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
3837
3838 // Enter the loop body, making that address the current address.
3839 auto EntryBB = CGF.Builder.GetInsertBlock();
3840 CGF.EmitBlock(BodyBB);
3841
3842 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
3843
3844 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
3845 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
3846 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
3847 Address RHSElementCurrent =
3848 Address(RHSElementPHI,
3849 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3850
3851 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
3852 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
3853 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
3854 Address LHSElementCurrent =
3855 Address(LHSElementPHI,
3856 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3857
3858 // Emit copy.
3859 CodeGenFunction::OMPPrivateScope Scope(CGF);
3860 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
3861 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
3862 Scope.Privatize();
3863 RedOpGen(CGF, XExpr, EExpr, UpExpr);
3864 Scope.ForceCleanup();
3865
3866 // Shift the address forward by one element.
3867 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
3868 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
3869 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
3870 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
3871 // Check whether we've reached the end.
3872 auto Done =
3873 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
3874 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
3875 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
3876 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
3877
3878 // Done.
3879 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
3880}
3881
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003882/// Emit reduction combiner. If the combiner is a simple expression emit it as
3883/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
3884/// UDR combiner function.
3885static void emitReductionCombiner(CodeGenFunction &CGF,
3886 const Expr *ReductionOp) {
3887 if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
3888 if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
3889 if (auto *DRE =
3890 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
3891 if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
3892 std::pair<llvm::Function *, llvm::Function *> Reduction =
3893 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
3894 RValue Func = RValue::get(Reduction.first);
3895 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
3896 CGF.EmitIgnoredExpr(ReductionOp);
3897 return;
3898 }
3899 CGF.EmitIgnoredExpr(ReductionOp);
3900}
3901
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003902static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
3903 llvm::Type *ArgsType,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003904 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003905 ArrayRef<const Expr *> LHSExprs,
3906 ArrayRef<const Expr *> RHSExprs,
3907 ArrayRef<const Expr *> ReductionOps) {
3908 auto &C = CGM.getContext();
3909
3910 // void reduction_func(void *LHSArg, void *RHSArg);
3911 FunctionArgList Args;
3912 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3913 C.VoidPtrTy);
3914 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3915 C.VoidPtrTy);
3916 Args.push_back(&LHSArg);
3917 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00003918 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003919 auto *Fn = llvm::Function::Create(
3920 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
3921 ".omp.reduction.reduction_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003922 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003923 CodeGenFunction CGF(CGM);
3924 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
3925
3926 // Dst = (void*[n])(LHSArg);
3927 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003928 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3929 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3930 ArgsType), CGF.getPointerAlign());
3931 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3932 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3933 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003934
3935 // ...
3936 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
3937 // ...
3938 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003939 auto IPriv = Privates.begin();
3940 unsigned Idx = 0;
3941 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003942 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
3943 Scope.addPrivate(RHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003944 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003945 });
3946 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
3947 Scope.addPrivate(LHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003948 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003949 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003950 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003951 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003952 // Get array size and emit VLA type.
3953 ++Idx;
3954 Address Elem =
3955 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
3956 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003957 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy);
3958 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003959 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00003960 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003961 CGF.EmitVariablyModifiedType(PrivTy);
3962 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003963 }
3964 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003965 IPriv = Privates.begin();
3966 auto ILHS = LHSExprs.begin();
3967 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003968 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003969 if ((*IPriv)->getType()->isArrayType()) {
3970 // Emit reduction for array section.
3971 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3972 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003973 EmitOMPAggregateReduction(
3974 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3975 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
3976 emitReductionCombiner(CGF, E);
3977 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003978 } else
3979 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003980 emitReductionCombiner(CGF, E);
Richard Trieucc3949d2016-02-18 22:34:54 +00003981 ++IPriv;
3982 ++ILHS;
3983 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003984 }
3985 Scope.ForceCleanup();
3986 CGF.FinishFunction();
3987 return Fn;
3988}
3989
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003990static void emitSingleReductionCombiner(CodeGenFunction &CGF,
3991 const Expr *ReductionOp,
3992 const Expr *PrivateRef,
3993 const DeclRefExpr *LHS,
3994 const DeclRefExpr *RHS) {
3995 if (PrivateRef->getType()->isArrayType()) {
3996 // Emit reduction for array section.
3997 auto *LHSVar = cast<VarDecl>(LHS->getDecl());
3998 auto *RHSVar = cast<VarDecl>(RHS->getDecl());
3999 EmitOMPAggregateReduction(
4000 CGF, PrivateRef->getType(), LHSVar, RHSVar,
4001 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
4002 emitReductionCombiner(CGF, ReductionOp);
4003 });
4004 } else
4005 // Emit reduction for array subscript or single variable.
4006 emitReductionCombiner(CGF, ReductionOp);
4007}
4008
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004009void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004010 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004011 ArrayRef<const Expr *> LHSExprs,
4012 ArrayRef<const Expr *> RHSExprs,
4013 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00004014 bool WithNowait, bool SimpleReduction) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004015 if (!CGF.HaveInsertPoint())
4016 return;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004017 // Next code should be emitted for reduction:
4018 //
4019 // static kmp_critical_name lock = { 0 };
4020 //
4021 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
4022 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
4023 // ...
4024 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
4025 // *(Type<n>-1*)rhs[<n>-1]);
4026 // }
4027 //
4028 // ...
4029 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
4030 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
4031 // RedList, reduce_func, &<lock>)) {
4032 // case 1:
4033 // ...
4034 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
4035 // ...
4036 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
4037 // break;
4038 // case 2:
4039 // ...
4040 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
4041 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00004042 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004043 // break;
4044 // default:;
4045 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00004046 //
4047 // if SimpleReduction is true, only the next code is generated:
4048 // ...
4049 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
4050 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004051
4052 auto &C = CGM.getContext();
4053
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00004054 if (SimpleReduction) {
4055 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004056 auto IPriv = Privates.begin();
4057 auto ILHS = LHSExprs.begin();
4058 auto IRHS = RHSExprs.begin();
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00004059 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004060 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
4061 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00004062 ++IPriv;
4063 ++ILHS;
4064 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00004065 }
4066 return;
4067 }
4068
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004069 // 1. Build a list of reduction variables.
4070 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004071 auto Size = RHSExprs.size();
4072 for (auto *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00004073 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004074 // Reserve place for array size.
4075 ++Size;
4076 }
4077 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004078 QualType ReductionArrayTy =
4079 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
4080 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00004081 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004082 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004083 auto IPriv = Privates.begin();
4084 unsigned Idx = 0;
4085 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00004086 Address Elem =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004087 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00004088 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004089 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00004090 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
4091 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00004092 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004093 // Store array size.
4094 ++Idx;
4095 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
4096 CGF.getPointerSize());
Alexey Bataev1189bd02016-01-26 12:20:39 +00004097 llvm::Value *Size = CGF.Builder.CreateIntCast(
4098 CGF.getVLASize(
4099 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
4100 .first,
4101 CGF.SizeTy, /*isSigned=*/false);
4102 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
4103 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004104 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004105 }
4106
4107 // 2. Emit reduce_func().
4108 auto *ReductionFn = emitReductionFunction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004109 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
4110 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004111
4112 // 3. Create static kmp_critical_name lock = { 0 };
4113 auto *Lock = getCriticalRegionLock(".reduction");
4114
4115 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
4116 // RedList, reduce_func, &<lock>);
Alexey Bataev50b3c952016-02-19 10:38:26 +00004117 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004118 auto *ThreadId = getThreadID(CGF, Loc);
Alexey Bataev1189bd02016-01-26 12:20:39 +00004119 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00004120 auto *RL =
4121 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
4122 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004123 llvm::Value *Args[] = {
4124 IdentTLoc, // ident_t *<loc>
4125 ThreadId, // i32 <gtid>
4126 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
4127 ReductionArrayTySize, // size_type sizeof(RedList)
4128 RL, // void *RedList
4129 ReductionFn, // void (*) (void *, void *) <reduce_func>
4130 Lock // kmp_critical_name *&<lock>
4131 };
4132 auto Res = CGF.EmitRuntimeCall(
4133 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
4134 : OMPRTL__kmpc_reduce),
4135 Args);
4136
4137 // 5. Build switch(res)
4138 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
4139 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
4140
4141 // 6. Build case 1:
4142 // ...
4143 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
4144 // ...
4145 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
4146 // break;
4147 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
4148 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
4149 CGF.EmitBlock(Case1BB);
4150
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004151 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
4152 llvm::Value *EndArgs[] = {
4153 IdentTLoc, // ident_t *<loc>
4154 ThreadId, // i32 <gtid>
4155 Lock // kmp_critical_name *&<lock>
4156 };
4157 auto &&CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps](
4158 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004159 auto IPriv = Privates.begin();
4160 auto ILHS = LHSExprs.begin();
4161 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004162 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004163 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
4164 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00004165 ++IPriv;
4166 ++ILHS;
4167 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004168 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004169 };
4170 RegionCodeGenTy RCG(CodeGen);
4171 CommonActionTy Action(
4172 nullptr, llvm::None,
4173 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
4174 : OMPRTL__kmpc_end_reduce),
4175 EndArgs);
4176 RCG.setAction(Action);
4177 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004178
4179 CGF.EmitBranch(DefaultBB);
4180
4181 // 7. Build case 2:
4182 // ...
4183 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
4184 // ...
4185 // break;
4186 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
4187 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
4188 CGF.EmitBlock(Case2BB);
4189
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004190 auto &&AtomicCodeGen = [Loc, &Privates, &LHSExprs, &RHSExprs, &ReductionOps](
4191 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004192 auto ILHS = LHSExprs.begin();
4193 auto IRHS = RHSExprs.begin();
4194 auto IPriv = Privates.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004195 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004196 const Expr *XExpr = nullptr;
4197 const Expr *EExpr = nullptr;
4198 const Expr *UpExpr = nullptr;
4199 BinaryOperatorKind BO = BO_Comma;
4200 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
4201 if (BO->getOpcode() == BO_Assign) {
4202 XExpr = BO->getLHS();
4203 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004204 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004205 }
4206 // Try to emit update expression as a simple atomic.
4207 auto *RHSExpr = UpExpr;
4208 if (RHSExpr) {
4209 // Analyze RHS part of the whole expression.
4210 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
4211 RHSExpr->IgnoreParenImpCasts())) {
4212 // If this is a conditional operator, analyze its condition for
4213 // min/max reduction operator.
4214 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00004215 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004216 if (auto *BORHS =
4217 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
4218 EExpr = BORHS->getRHS();
4219 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004220 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004221 }
4222 if (XExpr) {
4223 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4224 auto &&AtomicRedGen = [BO, VD, IPriv,
4225 Loc](CodeGenFunction &CGF, const Expr *XExpr,
4226 const Expr *EExpr, const Expr *UpExpr) {
4227 LValue X = CGF.EmitLValue(XExpr);
4228 RValue E;
4229 if (EExpr)
4230 E = CGF.EmitAnyExpr(EExpr);
4231 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00004232 X, E, BO, /*IsXLHSInRHSPart=*/true,
4233 llvm::AtomicOrdering::Monotonic, Loc,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004234 [&CGF, UpExpr, VD, IPriv, Loc](RValue XRValue) {
4235 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4236 PrivateScope.addPrivate(
4237 VD, [&CGF, VD, XRValue, Loc]() -> Address {
4238 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
4239 CGF.emitOMPSimpleStore(
4240 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
4241 VD->getType().getNonReferenceType(), Loc);
4242 return LHSTemp;
4243 });
4244 (void)PrivateScope.Privatize();
4245 return CGF.EmitAnyExpr(UpExpr);
4246 });
4247 };
4248 if ((*IPriv)->getType()->isArrayType()) {
4249 // Emit atomic reduction for array section.
4250 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4251 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
4252 AtomicRedGen, XExpr, EExpr, UpExpr);
4253 } else
4254 // Emit atomic reduction for array subscript or single variable.
4255 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
4256 } else {
4257 // Emit as a critical region.
4258 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
4259 const Expr *, const Expr *) {
4260 auto &RT = CGF.CGM.getOpenMPRuntime();
4261 RT.emitCriticalRegion(
4262 CGF, ".atomic_reduction",
4263 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
4264 Action.Enter(CGF);
4265 emitReductionCombiner(CGF, E);
4266 },
4267 Loc);
4268 };
4269 if ((*IPriv)->getType()->isArrayType()) {
4270 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4271 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4272 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4273 CritRedGen);
4274 } else
4275 CritRedGen(CGF, nullptr, nullptr, nullptr);
4276 }
Richard Trieucc3949d2016-02-18 22:34:54 +00004277 ++ILHS;
4278 ++IRHS;
4279 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004280 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004281 };
4282 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
4283 if (!WithNowait) {
4284 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
4285 llvm::Value *EndArgs[] = {
4286 IdentTLoc, // ident_t *<loc>
4287 ThreadId, // i32 <gtid>
4288 Lock // kmp_critical_name *&<lock>
4289 };
4290 CommonActionTy Action(nullptr, llvm::None,
4291 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
4292 EndArgs);
4293 AtomicRCG.setAction(Action);
4294 AtomicRCG(CGF);
4295 } else
4296 AtomicRCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004297
4298 CGF.EmitBranch(DefaultBB);
4299 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
4300}
4301
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004302void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
4303 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004304 if (!CGF.HaveInsertPoint())
4305 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004306 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
4307 // global_tid);
4308 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
4309 // Ignore return result until untied tasks are supported.
4310 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00004311 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
4312 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004313}
4314
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004315void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004316 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00004317 const RegionCodeGenTy &CodeGen,
4318 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004319 if (!CGF.HaveInsertPoint())
4320 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004321 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004322 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00004323}
4324
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004325namespace {
4326enum RTCancelKind {
4327 CancelNoreq = 0,
4328 CancelParallel = 1,
4329 CancelLoop = 2,
4330 CancelSections = 3,
4331 CancelTaskgroup = 4
4332};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004333} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004334
4335static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
4336 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00004337 if (CancelRegion == OMPD_parallel)
4338 CancelKind = CancelParallel;
4339 else if (CancelRegion == OMPD_for)
4340 CancelKind = CancelLoop;
4341 else if (CancelRegion == OMPD_sections)
4342 CancelKind = CancelSections;
4343 else {
4344 assert(CancelRegion == OMPD_taskgroup);
4345 CancelKind = CancelTaskgroup;
4346 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004347 return CancelKind;
4348}
4349
4350void CGOpenMPRuntime::emitCancellationPointCall(
4351 CodeGenFunction &CGF, SourceLocation Loc,
4352 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004353 if (!CGF.HaveInsertPoint())
4354 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004355 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
4356 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004357 if (auto *OMPRegionInfo =
4358 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00004359 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004360 llvm::Value *Args[] = {
4361 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
4362 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004363 // Ignore return result until untied tasks are supported.
4364 auto *Result = CGF.EmitRuntimeCall(
4365 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
4366 // if (__kmpc_cancellationpoint()) {
4367 // __kmpc_cancel_barrier();
4368 // exit from construct;
4369 // }
4370 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4371 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4372 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4373 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4374 CGF.EmitBlock(ExitBB);
4375 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00004376 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004377 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004378 auto CancelDest =
4379 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004380 CGF.EmitBranchThroughCleanup(CancelDest);
4381 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4382 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004383 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004384}
4385
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004386void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00004387 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004388 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004389 if (!CGF.HaveInsertPoint())
4390 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004391 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
4392 // kmp_int32 cncl_kind);
4393 if (auto *OMPRegionInfo =
4394 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004395 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
4396 PrePostActionTy &) {
4397 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00004398 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004399 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00004400 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
4401 // Ignore return result until untied tasks are supported.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004402 auto *Result = CGF.EmitRuntimeCall(
4403 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00004404 // if (__kmpc_cancel()) {
4405 // __kmpc_cancel_barrier();
4406 // exit from construct;
4407 // }
4408 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4409 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4410 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4411 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4412 CGF.EmitBlock(ExitBB);
4413 // __kmpc_cancel_barrier();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004414 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev87933c72015-09-18 08:07:34 +00004415 // exit from construct;
4416 auto CancelDest =
4417 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
4418 CGF.EmitBranchThroughCleanup(CancelDest);
4419 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4420 };
4421 if (IfCond)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004422 emitOMPIfClause(CGF, IfCond, ThenGen,
4423 [](CodeGenFunction &, PrePostActionTy &) {});
4424 else {
4425 RegionCodeGenTy ThenRCG(ThenGen);
4426 ThenRCG(CGF);
4427 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004428 }
4429}
Samuel Antaobed3c462015-10-02 16:14:20 +00004430
Samuel Antaoee8fb302016-01-06 13:42:12 +00004431/// \brief Obtain information that uniquely identifies a target entry. This
Samuel Antao2de62b02016-02-13 23:35:10 +00004432/// consists of the file and device IDs as well as line number associated with
4433/// the relevant entry source location.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004434static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
4435 unsigned &DeviceID, unsigned &FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004436 unsigned &LineNum) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004437
4438 auto &SM = C.getSourceManager();
4439
4440 // The loc should be always valid and have a file ID (the user cannot use
4441 // #pragma directives in macros)
4442
4443 assert(Loc.isValid() && "Source location is expected to be always valid.");
4444 assert(Loc.isFileID() && "Source location is expected to refer to a file.");
4445
4446 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
4447 assert(PLoc.isValid() && "Source location is expected to be always valid.");
4448
4449 llvm::sys::fs::UniqueID ID;
4450 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
4451 llvm_unreachable("Source file with target region no longer exists!");
4452
4453 DeviceID = ID.getDevice();
4454 FileID = ID.getFile();
4455 LineNum = PLoc.getLine();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004456}
4457
4458void CGOpenMPRuntime::emitTargetOutlinedFunction(
4459 const OMPExecutableDirective &D, StringRef ParentName,
4460 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004461 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004462 assert(!ParentName.empty() && "Invalid target region parent name!");
4463
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004464 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
4465 IsOffloadEntry, CodeGen);
4466}
4467
4468void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
4469 const OMPExecutableDirective &D, StringRef ParentName,
4470 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
4471 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004472 // Create a unique name for the entry function using the source location
4473 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004474 //
Samuel Antao2de62b02016-02-13 23:35:10 +00004475 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00004476 //
4477 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00004478 // mangled name of the function that encloses the target region and BB is the
4479 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004480
4481 unsigned DeviceID;
4482 unsigned FileID;
4483 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004484 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004485 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004486 SmallString<64> EntryFnName;
4487 {
4488 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00004489 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
4490 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004491 }
4492
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004493 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4494
Samuel Antaobed3c462015-10-02 16:14:20 +00004495 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004496 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00004497 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004498
4499 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
4500
4501 // If this target outline function is not an offload entry, we don't need to
4502 // register it.
4503 if (!IsOffloadEntry)
4504 return;
4505
4506 // The target region ID is used by the runtime library to identify the current
4507 // target region, so it only has to be unique and not necessarily point to
4508 // anything. It could be the pointer to the outlined function that implements
4509 // the target region, but we aren't using that so that the compiler doesn't
4510 // need to keep that, and could therefore inline the host function if proven
4511 // worthwhile during optimization. In the other hand, if emitting code for the
4512 // device, the ID has to be the function address so that it can retrieved from
4513 // the offloading entry and launched by the runtime library. We also mark the
4514 // outlined function to have external linkage in case we are emitting code for
4515 // the device, because these functions will be entry points to the device.
4516
4517 if (CGM.getLangOpts().OpenMPIsDevice) {
4518 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
4519 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage);
4520 } else
4521 OutlinedFnID = new llvm::GlobalVariable(
4522 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
4523 llvm::GlobalValue::PrivateLinkage,
4524 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id");
4525
4526 // Register the information for the entry associated with this target region.
4527 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00004528 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID);
Samuel Antaobed3c462015-10-02 16:14:20 +00004529}
4530
Samuel Antaob68e2db2016-03-03 16:20:23 +00004531/// \brief Emit the num_teams clause of an enclosed teams directive at the
4532/// target region scope. If there is no teams directive associated with the
4533/// target directive, or if there is no num_teams clause associated with the
4534/// enclosed teams directive, return nullptr.
4535static llvm::Value *
4536emitNumTeamsClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4537 CodeGenFunction &CGF,
4538 const OMPExecutableDirective &D) {
4539
4540 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4541 "teams directive expected to be "
4542 "emitted only for the host!");
4543
4544 // FIXME: For the moment we do not support combined directives with target and
4545 // teams, so we do not expect to get any num_teams clause in the provided
4546 // directive. Once we support that, this assertion can be replaced by the
4547 // actual emission of the clause expression.
4548 assert(D.getSingleClause<OMPNumTeamsClause>() == nullptr &&
4549 "Not expecting clause in directive.");
4550
4551 // If the current target region has a teams region enclosed, we need to get
4552 // the number of teams to pass to the runtime function call. This is done
4553 // by generating the expression in a inlined region. This is required because
4554 // the expression is captured in the enclosing target environment when the
4555 // teams directive is not combined with target.
4556
4557 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4558
4559 // FIXME: Accommodate other combined directives with teams when they become
4560 // available.
4561 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) {
4562 if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) {
4563 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4564 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4565 llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams());
4566 return CGF.Builder.CreateIntCast(NumTeams, CGF.Int32Ty,
4567 /*IsSigned=*/true);
4568 }
4569
4570 // If we have an enclosed teams directive but no num_teams clause we use
4571 // the default value 0.
4572 return CGF.Builder.getInt32(0);
4573 }
4574
4575 // No teams associated with the directive.
4576 return nullptr;
4577}
4578
4579/// \brief Emit the thread_limit clause of an enclosed teams directive at the
4580/// target region scope. If there is no teams directive associated with the
4581/// target directive, or if there is no thread_limit clause associated with the
4582/// enclosed teams directive, return nullptr.
4583static llvm::Value *
4584emitThreadLimitClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4585 CodeGenFunction &CGF,
4586 const OMPExecutableDirective &D) {
4587
4588 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4589 "teams directive expected to be "
4590 "emitted only for the host!");
4591
4592 // FIXME: For the moment we do not support combined directives with target and
4593 // teams, so we do not expect to get any thread_limit clause in the provided
4594 // directive. Once we support that, this assertion can be replaced by the
4595 // actual emission of the clause expression.
4596 assert(D.getSingleClause<OMPThreadLimitClause>() == nullptr &&
4597 "Not expecting clause in directive.");
4598
4599 // If the current target region has a teams region enclosed, we need to get
4600 // the thread limit to pass to the runtime function call. This is done
4601 // by generating the expression in a inlined region. This is required because
4602 // the expression is captured in the enclosing target environment when the
4603 // teams directive is not combined with target.
4604
4605 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4606
4607 // FIXME: Accommodate other combined directives with teams when they become
4608 // available.
4609 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) {
4610 if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) {
4611 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4612 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4613 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit());
4614 return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty,
4615 /*IsSigned=*/true);
4616 }
4617
4618 // If we have an enclosed teams directive but no thread_limit clause we use
4619 // the default value 0.
4620 return CGF.Builder.getInt32(0);
4621 }
4622
4623 // No teams associated with the directive.
4624 return nullptr;
4625}
4626
Samuel Antaobed3c462015-10-02 16:14:20 +00004627void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
4628 const OMPExecutableDirective &D,
4629 llvm::Value *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00004630 llvm::Value *OutlinedFnID,
Samuel Antaobed3c462015-10-02 16:14:20 +00004631 const Expr *IfCond, const Expr *Device,
4632 ArrayRef<llvm::Value *> CapturedVars) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004633 if (!CGF.HaveInsertPoint())
4634 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00004635 /// \brief Values for bit flags used to specify the mapping type for
4636 /// offloading.
4637 enum OpenMPOffloadMappingFlags {
4638 /// \brief Allocate memory on the device and move data from host to device.
4639 OMP_MAP_TO = 0x01,
4640 /// \brief Allocate memory on the device and move data from device to host.
4641 OMP_MAP_FROM = 0x02,
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004642 /// \brief The element passed to the device is a pointer.
4643 OMP_MAP_PTR = 0x20,
4644 /// \brief Pass the element to the device by value.
4645 OMP_MAP_BYCOPY = 0x80,
Samuel Antaobed3c462015-10-02 16:14:20 +00004646 };
4647
4648 enum OpenMPOffloadingReservedDeviceIDs {
4649 /// \brief Device ID if the device was not defined, runtime should get it
4650 /// from environment variables in the spec.
4651 OMP_DEVICEID_UNDEF = -1,
4652 };
4653
Samuel Antaoee8fb302016-01-06 13:42:12 +00004654 assert(OutlinedFn && "Invalid outlined function!");
4655
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004656 auto &Ctx = CGF.getContext();
4657
Samuel Antaobed3c462015-10-02 16:14:20 +00004658 // Fill up the arrays with the all the captured variables.
4659 SmallVector<llvm::Value *, 16> BasePointers;
4660 SmallVector<llvm::Value *, 16> Pointers;
4661 SmallVector<llvm::Value *, 16> Sizes;
4662 SmallVector<unsigned, 16> MapTypes;
4663
4664 bool hasVLACaptures = false;
4665
4666 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4667 auto RI = CS.getCapturedRecordDecl()->field_begin();
4668 // auto II = CS.capture_init_begin();
4669 auto CV = CapturedVars.begin();
4670 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
4671 CE = CS.capture_end();
4672 CI != CE; ++CI, ++RI, ++CV) {
4673 StringRef Name;
4674 QualType Ty;
4675 llvm::Value *BasePointer;
4676 llvm::Value *Pointer;
4677 llvm::Value *Size;
4678 unsigned MapType;
4679
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004680 // VLA sizes are passed to the outlined region by copy.
Samuel Antaobed3c462015-10-02 16:14:20 +00004681 if (CI->capturesVariableArrayType()) {
4682 BasePointer = Pointer = *CV;
Alexey Bataev1189bd02016-01-26 12:20:39 +00004683 Size = CGF.getTypeSize(RI->getType());
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004684 // Copy to the device as an argument. No need to retrieve it.
4685 MapType = OMP_MAP_BYCOPY;
Samuel Antaobed3c462015-10-02 16:14:20 +00004686 hasVLACaptures = true;
Samuel Antaobed3c462015-10-02 16:14:20 +00004687 } else if (CI->capturesThis()) {
4688 BasePointer = Pointer = *CV;
4689 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr());
Alexey Bataev1189bd02016-01-26 12:20:39 +00004690 Size = CGF.getTypeSize(PtrTy->getPointeeType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004691 // Default map type.
4692 MapType = OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004693 } else if (CI->capturesVariableByCopy()) {
4694 MapType = OMP_MAP_BYCOPY;
4695 if (!RI->getType()->isAnyPointerType()) {
4696 // If the field is not a pointer, we need to save the actual value and
4697 // load it as a void pointer.
4698 auto DstAddr = CGF.CreateMemTemp(
4699 Ctx.getUIntPtrType(),
4700 Twine(CI->getCapturedVar()->getName()) + ".casted");
4701 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
4702
4703 auto *SrcAddrVal = CGF.EmitScalarConversion(
4704 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
4705 Ctx.getPointerType(RI->getType()), SourceLocation());
4706 LValue SrcLV =
4707 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType());
4708
4709 // Store the value using the source type pointer.
4710 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV);
4711
4712 // Load the value using the destination type pointer.
4713 BasePointer = Pointer =
4714 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
4715 } else {
4716 MapType |= OMP_MAP_PTR;
4717 BasePointer = Pointer = *CV;
4718 }
Alexey Bataev1189bd02016-01-26 12:20:39 +00004719 Size = CGF.getTypeSize(RI->getType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004720 } else {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004721 assert(CI->capturesVariable() && "Expected captured reference.");
Samuel Antaobed3c462015-10-02 16:14:20 +00004722 BasePointer = Pointer = *CV;
4723
4724 const ReferenceType *PtrTy =
4725 cast<ReferenceType>(RI->getType().getTypePtr());
4726 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00004727 Size = CGF.getTypeSize(ElementType);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004728 // The default map type for a scalar/complex type is 'to' because by
4729 // default the value doesn't have to be retrieved. For an aggregate type,
4730 // the default is 'tofrom'.
4731 MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
4732 : OMP_MAP_TO;
4733 if (ElementType->isAnyPointerType())
4734 MapType |= OMP_MAP_PTR;
Samuel Antaobed3c462015-10-02 16:14:20 +00004735 }
4736
4737 BasePointers.push_back(BasePointer);
4738 Pointers.push_back(Pointer);
4739 Sizes.push_back(Size);
4740 MapTypes.push_back(MapType);
4741 }
4742
4743 // Keep track on whether the host function has to be executed.
4744 auto OffloadErrorQType =
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004745 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004746 auto OffloadError = CGF.MakeAddrLValue(
4747 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
4748 OffloadErrorQType);
4749 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
4750 OffloadError);
4751
4752 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004753 auto &&ThenGen = [&Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes,
Alexey Bataevf539faa2016-03-28 12:58:34 +00004754 hasVLACaptures, Device, OutlinedFnID, OffloadError,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004755 OffloadErrorQType,
4756 &D](CodeGenFunction &CGF, PrePostActionTy &) {
4757 auto &RT = CGF.CGM.getOpenMPRuntime();
Samuel Antaobed3c462015-10-02 16:14:20 +00004758 unsigned PointerNumVal = BasePointers.size();
4759 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal);
4760 llvm::Value *BasePointersArray;
4761 llvm::Value *PointersArray;
4762 llvm::Value *SizesArray;
4763 llvm::Value *MapTypesArray;
4764
4765 if (PointerNumVal) {
4766 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004767 QualType PointerArrayType = Ctx.getConstantArrayType(
4768 Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004769 /*IndexTypeQuals=*/0);
4770
4771 BasePointersArray =
4772 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
4773 PointersArray =
4774 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
4775
4776 // If we don't have any VLA types, we can use a constant array for the map
4777 // sizes, otherwise we need to fill up the arrays as we do for the
4778 // pointers.
4779 if (hasVLACaptures) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004780 QualType SizeArrayType = Ctx.getConstantArrayType(
4781 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004782 /*IndexTypeQuals=*/0);
4783 SizesArray =
4784 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
4785 } else {
4786 // We expect all the sizes to be constant, so we collect them to create
4787 // a constant array.
4788 SmallVector<llvm::Constant *, 16> ConstSizes;
4789 for (auto S : Sizes)
4790 ConstSizes.push_back(cast<llvm::Constant>(S));
4791
4792 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004793 llvm::ArrayType::get(CGF.CGM.SizeTy, ConstSizes.size()),
4794 ConstSizes);
Samuel Antaobed3c462015-10-02 16:14:20 +00004795 auto *SizesArrayGbl = new llvm::GlobalVariable(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004796 CGF.CGM.getModule(), SizesArrayInit->getType(),
Samuel Antaobed3c462015-10-02 16:14:20 +00004797 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4798 SizesArrayInit, ".offload_sizes");
4799 SizesArrayGbl->setUnnamedAddr(true);
4800 SizesArray = SizesArrayGbl;
4801 }
4802
4803 // The map types are always constant so we don't need to generate code to
4804 // fill arrays. Instead, we create an array constant.
4805 llvm::Constant *MapTypesArrayInit =
4806 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
4807 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004808 CGF.CGM.getModule(), MapTypesArrayInit->getType(),
Samuel Antaobed3c462015-10-02 16:14:20 +00004809 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4810 MapTypesArrayInit, ".offload_maptypes");
4811 MapTypesArrayGbl->setUnnamedAddr(true);
4812 MapTypesArray = MapTypesArrayGbl;
4813
4814 for (unsigned i = 0; i < PointerNumVal; ++i) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004815 llvm::Value *BPVal = BasePointers[i];
4816 if (BPVal->getType()->isPointerTy())
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004817 BPVal = CGF.Builder.CreateBitCast(BPVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004818 else {
4819 assert(BPVal->getType()->isIntegerTy() &&
4820 "If not a pointer, the value type must be an integer.");
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004821 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004822 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004823 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004824 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal),
Samuel Antaobed3c462015-10-02 16:14:20 +00004825 BasePointersArray, 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004826 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4827 CGF.Builder.CreateStore(BPVal, BPAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004828
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004829 llvm::Value *PVal = Pointers[i];
4830 if (PVal->getType()->isPointerTy())
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004831 PVal = CGF.Builder.CreateBitCast(PVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004832 else {
4833 assert(PVal->getType()->isIntegerTy() &&
4834 "If not a pointer, the value type must be an integer.");
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004835 PVal = CGF.Builder.CreateIntToPtr(PVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004836 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004837 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004838 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), PointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004839 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004840 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4841 CGF.Builder.CreateStore(PVal, PAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004842
4843 if (hasVLACaptures) {
4844 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004845 llvm::ArrayType::get(CGF.SizeTy, PointerNumVal), SizesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004846 /*Idx0=*/0,
4847 /*Idx1=*/i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004848 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
Samuel Antaobed3c462015-10-02 16:14:20 +00004849 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004850 Sizes[i], CGF.SizeTy, /*isSigned=*/true),
Samuel Antaobed3c462015-10-02 16:14:20 +00004851 SAddr);
4852 }
4853 }
4854
4855 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004856 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), BasePointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004857 /*Idx0=*/0, /*Idx1=*/0);
4858 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004859 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), PointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004860 /*Idx0=*/0,
4861 /*Idx1=*/0);
4862 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004863 llvm::ArrayType::get(CGF.SizeTy, PointerNumVal), SizesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004864 /*Idx0=*/0, /*Idx1=*/0);
4865 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004866 llvm::ArrayType::get(CGF.Int32Ty, PointerNumVal), MapTypesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004867 /*Idx0=*/0,
4868 /*Idx1=*/0);
4869
4870 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004871 BasePointersArray = llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy);
4872 PointersArray = llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy);
4873 SizesArray = llvm::ConstantPointerNull::get(CGF.SizeTy->getPointerTo());
Samuel Antaobed3c462015-10-02 16:14:20 +00004874 MapTypesArray =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004875 llvm::ConstantPointerNull::get(CGF.Int32Ty->getPointerTo());
Samuel Antaobed3c462015-10-02 16:14:20 +00004876 }
4877
4878 // On top of the arrays that were filled up, the target offloading call
4879 // takes as arguments the device id as well as the host pointer. The host
4880 // pointer is used by the runtime library to identify the current target
4881 // region, so it only has to be unique and not necessarily point to
4882 // anything. It could be the pointer to the outlined function that
4883 // implements the target region, but we aren't using that so that the
4884 // compiler doesn't need to keep that, and could therefore inline the host
4885 // function if proven worthwhile during optimization.
4886
Samuel Antaoee8fb302016-01-06 13:42:12 +00004887 // From this point on, we need to have an ID of the target region defined.
4888 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00004889
4890 // Emit device ID if any.
4891 llvm::Value *DeviceID;
4892 if (Device)
4893 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004894 CGF.Int32Ty, /*isSigned=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004895 else
4896 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
4897
Samuel Antaob68e2db2016-03-03 16:20:23 +00004898 // Return value of the runtime offloading call.
4899 llvm::Value *Return;
4900
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004901 auto *NumTeams = emitNumTeamsClauseForTargetDirective(RT, CGF, D);
4902 auto *ThreadLimit = emitThreadLimitClauseForTargetDirective(RT, CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004903
4904 // If we have NumTeams defined this means that we have an enclosed teams
4905 // region. Therefore we also expect to have ThreadLimit defined. These two
4906 // values should be defined in the presence of a teams directive, regardless
4907 // of having any clauses associated. If the user is using teams but no
4908 // clauses, these two values will be the default that should be passed to
4909 // the runtime library - a 32-bit integer with the value zero.
4910 if (NumTeams) {
4911 assert(ThreadLimit && "Thread limit expression should be available along "
4912 "with number of teams.");
4913 llvm::Value *OffloadingArgs[] = {
4914 DeviceID, OutlinedFnID, PointerNum,
4915 BasePointersArray, PointersArray, SizesArray,
4916 MapTypesArray, NumTeams, ThreadLimit};
4917 Return = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004918 RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004919 } else {
4920 llvm::Value *OffloadingArgs[] = {
4921 DeviceID, OutlinedFnID, PointerNum, BasePointersArray,
4922 PointersArray, SizesArray, MapTypesArray};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004923 Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target),
Samuel Antaob68e2db2016-03-03 16:20:23 +00004924 OffloadingArgs);
4925 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004926
4927 CGF.EmitStoreOfScalar(Return, OffloadError);
4928 };
4929
Samuel Antaoee8fb302016-01-06 13:42:12 +00004930 // Notify that the host version must be executed.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004931 auto &&ElseGen = [OffloadError](CodeGenFunction &CGF, PrePostActionTy &) {
4932 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/-1u),
Samuel Antaoee8fb302016-01-06 13:42:12 +00004933 OffloadError);
4934 };
4935
4936 // If we have a target function ID it means that we need to support
4937 // offloading, otherwise, just execute on the host. We need to execute on host
4938 // regardless of the conditional in the if clause if, e.g., the user do not
4939 // specify target triples.
4940 if (OutlinedFnID) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004941 if (IfCond)
Samuel Antaoee8fb302016-01-06 13:42:12 +00004942 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004943 else {
4944 RegionCodeGenTy ThenRCG(ThenGen);
4945 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00004946 }
4947 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004948 RegionCodeGenTy ElseRCG(ElseGen);
4949 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00004950 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004951
4952 // Check the error code and execute the host version if required.
4953 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
4954 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
4955 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
4956 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
4957 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
4958
4959 CGF.EmitBlock(OffloadFailedBlock);
4960 CGF.Builder.CreateCall(OutlinedFn, BasePointers);
4961 CGF.EmitBranch(OffloadContBlock);
4962
4963 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004964}
Samuel Antaoee8fb302016-01-06 13:42:12 +00004965
4966void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
4967 StringRef ParentName) {
4968 if (!S)
4969 return;
4970
4971 // If we find a OMP target directive, codegen the outline function and
4972 // register the result.
4973 // FIXME: Add other directives with target when they become supported.
4974 bool isTargetDirective = isa<OMPTargetDirective>(S);
4975
4976 if (isTargetDirective) {
4977 auto *E = cast<OMPExecutableDirective>(S);
4978 unsigned DeviceID;
4979 unsigned FileID;
4980 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004981 getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004982 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004983
4984 // Is this a target region that should not be emitted as an entry point? If
4985 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00004986 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
4987 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004988 return;
4989
4990 llvm::Function *Fn;
4991 llvm::Constant *Addr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004992 std::tie(Fn, Addr) =
4993 CodeGenFunction::EmitOMPTargetDirectiveOutlinedFunction(
4994 CGM, cast<OMPTargetDirective>(*E), ParentName,
4995 /*isOffloadEntry=*/true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004996 assert(Fn && Addr && "Target region emission failed.");
4997 return;
4998 }
4999
5000 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) {
5001 if (!E->getAssociatedStmt())
5002 return;
5003
5004 scanForTargetRegionsFunctions(
5005 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(),
5006 ParentName);
5007 return;
5008 }
5009
5010 // If this is a lambda function, look into its body.
5011 if (auto *L = dyn_cast<LambdaExpr>(S))
5012 S = L->getBody();
5013
5014 // Keep looking for target regions recursively.
5015 for (auto *II : S->children())
5016 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00005017}
5018
5019bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
5020 auto &FD = *cast<FunctionDecl>(GD.getDecl());
5021
5022 // If emitting code for the host, we do not process FD here. Instead we do
5023 // the normal code generation.
5024 if (!CGM.getLangOpts().OpenMPIsDevice)
5025 return false;
5026
5027 // Try to detect target regions in the function.
5028 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
5029
5030 // We should not emit any function othen that the ones created during the
5031 // scanning. Therefore, we signal that this function is completely dealt
5032 // with.
5033 return true;
5034}
5035
5036bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
5037 if (!CGM.getLangOpts().OpenMPIsDevice)
5038 return false;
5039
5040 // Check if there are Ctors/Dtors in this declaration and look for target
5041 // regions in it. We use the complete variant to produce the kernel name
5042 // mangling.
5043 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
5044 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
5045 for (auto *Ctor : RD->ctors()) {
5046 StringRef ParentName =
5047 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
5048 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
5049 }
5050 auto *Dtor = RD->getDestructor();
5051 if (Dtor) {
5052 StringRef ParentName =
5053 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
5054 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
5055 }
5056 }
5057
5058 // If we are in target mode we do not emit any global (declare target is not
5059 // implemented yet). Therefore we signal that GD was processed in this case.
5060 return true;
5061}
5062
5063bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
5064 auto *VD = GD.getDecl();
5065 if (isa<FunctionDecl>(VD))
5066 return emitTargetFunctions(GD);
5067
5068 return emitTargetGlobalVariable(GD);
5069}
5070
5071llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
5072 // If we have offloading in the current module, we need to emit the entries
5073 // now and register the offloading descriptor.
5074 createOffloadEntriesAndInfoMetadata();
5075
5076 // Create and register the offloading binary descriptors. This is the main
5077 // entity that captures all the information about offloading in the current
5078 // compilation unit.
5079 return createOffloadingBinaryDescriptorRegistration();
5080}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00005081
5082void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
5083 const OMPExecutableDirective &D,
5084 SourceLocation Loc,
5085 llvm::Value *OutlinedFn,
5086 ArrayRef<llvm::Value *> CapturedVars) {
5087 if (!CGF.HaveInsertPoint())
5088 return;
5089
5090 auto *RTLoc = emitUpdateLocation(CGF, Loc);
5091 CodeGenFunction::RunCleanupsScope Scope(CGF);
5092
5093 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
5094 llvm::Value *Args[] = {
5095 RTLoc,
5096 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
5097 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
5098 llvm::SmallVector<llvm::Value *, 16> RealArgs;
5099 RealArgs.append(std::begin(Args), std::end(Args));
5100 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
5101
5102 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
5103 CGF.EmitRuntimeCall(RTLFn, RealArgs);
5104}
5105
5106void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00005107 const Expr *NumTeams,
5108 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00005109 SourceLocation Loc) {
5110 if (!CGF.HaveInsertPoint())
5111 return;
5112
5113 auto *RTLoc = emitUpdateLocation(CGF, Loc);
5114
Carlo Bertollic6872252016-04-04 15:55:02 +00005115 llvm::Value *NumTeamsVal =
5116 (NumTeams)
5117 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
5118 CGF.CGM.Int32Ty, /* isSigned = */ true)
5119 : CGF.Builder.getInt32(0);
5120
5121 llvm::Value *ThreadLimitVal =
5122 (ThreadLimit)
5123 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
5124 CGF.CGM.Int32Ty, /* isSigned = */ true)
5125 : CGF.Builder.getInt32(0);
5126
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00005127 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00005128 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
5129 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00005130 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
5131 PushNumTeamsArgs);
5132}