blob: 828be92d542ecca850dc3eb420a035e80c1bc384 [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 Bataev823acfa2016-04-19 16:27:55 +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 Bataev823acfa2016-04-19 16:27:55 +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 Bataev823acfa2016-04-19 16:27:55 +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 Bataev823acfa2016-04-19 16:27:55 +0000128class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000129public:
Alexey Bataev823acfa2016-04-19 16:27:55 +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 Bataev823acfa2016-04-19 16:27:55 +0000180 OpenMPDirectiveKind Kind, bool HasCancel,
181 const UntiedTaskActionTy &Action)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000182 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev823acfa2016-04-19 16:27:55 +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 Bataev823acfa2016-04-19 16:27:55 +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 Bataev823acfa2016-04-19 16:27:55 +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 Bataev823acfa2016-04-19 16:27:55 +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 Bataev823acfa2016-04-19 16:27:55 +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 Bataev823acfa2016-04-19 16:27:55 +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 Bataev823acfa2016-04-19 16:27:55 +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,
611 /// \brief Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc,
612 /// kmpc_micro microtask, ...);
613 OMPRTL__kmpc_fork_teams,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000614
615 //
616 // Offloading related calls
617 //
618 // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
619 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
620 // *arg_types);
621 OMPRTL__tgt_target,
Samuel Antaob68e2db2016-03-03 16:20:23 +0000622 // Call to int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
623 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
624 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
625 OMPRTL__tgt_target_teams,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000626 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
627 OMPRTL__tgt_register_lib,
628 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
629 OMPRTL__tgt_unregister_lib,
630};
631
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000632/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
633/// region.
634class CleanupTy final : public EHScopeStack::Cleanup {
635 PrePostActionTy *Action;
636
637public:
638 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
639 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
640 if (!CGF.HaveInsertPoint())
641 return;
642 Action->Exit(CGF);
643 }
644};
645
Hans Wennborg7eb54642015-09-10 17:07:54 +0000646} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000647
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000648void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
649 CodeGenFunction::RunCleanupsScope Scope(CGF);
650 if (PrePostAction) {
651 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
652 Callback(CodeGen, CGF, *PrePostAction);
653 } else {
654 PrePostActionTy Action;
655 Callback(CodeGen, CGF, Action);
656 }
657}
658
Alexey Bataev18095712014-10-10 12:19:54 +0000659LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +0000660 return CGF.EmitLoadOfPointerLValue(
661 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
662 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +0000663}
664
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000665void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000666 if (!CGF.HaveInsertPoint())
667 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000668 // 1.2.2 OpenMP Language Terminology
669 // Structured block - An executable statement with a single entry at the
670 // top and a single exit at the bottom.
671 // The point of exit cannot be a branch out of the structured block.
672 // longjmp() and throw() must not violate the entry/exit criteria.
673 CGF.EHStack.pushTerminate();
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000674 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000675 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000676}
677
Alexey Bataev62b63b12015-03-10 07:28:44 +0000678LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
679 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000680 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
681 getThreadIDVariable()->getType(),
682 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000683}
684
Alexey Bataev9959db52014-05-06 10:08:46 +0000685CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000686 : CGM(CGM), OffloadEntriesInfoManager(CGM) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000687 IdentTy = llvm::StructType::create(
688 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
689 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000690 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000691 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +0000692
693 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +0000694}
695
Alexey Bataev91797552015-03-18 04:13:55 +0000696void CGOpenMPRuntime::clear() {
697 InternalVars.clear();
698}
699
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000700static llvm::Function *
701emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
702 const Expr *CombinerInitializer, const VarDecl *In,
703 const VarDecl *Out, bool IsCombiner) {
704 // void .omp_combiner.(Ty *in, Ty *out);
705 auto &C = CGM.getContext();
706 QualType PtrTy = C.getPointerType(Ty).withRestrict();
707 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000708 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
709 /*Id=*/nullptr, PtrTy);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000710 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
711 /*Id=*/nullptr, PtrTy);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000712 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000713 Args.push_back(&OmpInParm);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000714 auto &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +0000715 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000716 auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
717 auto *Fn = llvm::Function::Create(
718 FnTy, llvm::GlobalValue::InternalLinkage,
719 IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
720 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000721 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000722 CodeGenFunction CGF(CGM);
723 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
724 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
725 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args);
726 CodeGenFunction::OMPPrivateScope Scope(CGF);
727 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
728 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() -> Address {
729 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
730 .getAddress();
731 });
732 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
733 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() -> Address {
734 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
735 .getAddress();
736 });
737 (void)Scope.Privatize();
738 CGF.EmitIgnoredExpr(CombinerInitializer);
739 Scope.ForceCleanup();
740 CGF.FinishFunction();
741 return Fn;
742}
743
744void CGOpenMPRuntime::emitUserDefinedReduction(
745 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
746 if (UDRMap.count(D) > 0)
747 return;
748 auto &C = CGM.getContext();
749 if (!In || !Out) {
750 In = &C.Idents.get("omp_in");
751 Out = &C.Idents.get("omp_out");
752 }
753 llvm::Function *Combiner = emitCombinerOrInitializer(
754 CGM, D->getType(), D->getCombiner(), cast<VarDecl>(D->lookup(In).front()),
755 cast<VarDecl>(D->lookup(Out).front()),
756 /*IsCombiner=*/true);
757 llvm::Function *Initializer = nullptr;
758 if (auto *Init = D->getInitializer()) {
759 if (!Priv || !Orig) {
760 Priv = &C.Idents.get("omp_priv");
761 Orig = &C.Idents.get("omp_orig");
762 }
763 Initializer = emitCombinerOrInitializer(
764 CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()),
765 cast<VarDecl>(D->lookup(Priv).front()),
766 /*IsCombiner=*/false);
767 }
768 UDRMap.insert(std::make_pair(D, std::make_pair(Combiner, Initializer)));
769 if (CGF) {
770 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
771 Decls.second.push_back(D);
772 }
773}
774
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000775std::pair<llvm::Function *, llvm::Function *>
776CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
777 auto I = UDRMap.find(D);
778 if (I != UDRMap.end())
779 return I->second;
780 emitUserDefinedReduction(/*CGF=*/nullptr, D);
781 return UDRMap.lookup(D);
782}
783
John McCall7f416cc2015-09-08 08:05:57 +0000784// Layout information for ident_t.
785static CharUnits getIdentAlign(CodeGenModule &CGM) {
786 return CGM.getPointerAlign();
787}
788static CharUnits getIdentSize(CodeGenModule &CGM) {
789 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign()));
790 return CharUnits::fromQuantity(16) + CGM.getPointerSize();
791}
Alexey Bataev50b3c952016-02-19 10:38:26 +0000792static CharUnits getOffsetOfIdentField(IdentFieldIndex Field) {
John McCall7f416cc2015-09-08 08:05:57 +0000793 // All the fields except the last are i32, so this works beautifully.
794 return unsigned(Field) * CharUnits::fromQuantity(4);
795}
796static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000797 IdentFieldIndex Field,
John McCall7f416cc2015-09-08 08:05:57 +0000798 const llvm::Twine &Name = "") {
799 auto Offset = getOffsetOfIdentField(Field);
800 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
801}
802
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000803llvm::Value *CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000804 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
805 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000806 assert(ThreadIDVar->getType()->isPointerType() &&
807 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +0000808 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
809 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +0000810 bool HasCancel = false;
811 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
812 HasCancel = OPD->hasCancel();
813 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
814 HasCancel = OPSD->hasCancel();
815 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
816 HasCancel = OPFD->hasCancel();
817 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
818 HasCancel);
Alexey Bataevd157d472015-06-24 03:35:38 +0000819 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000820 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +0000821}
822
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000823llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
824 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev823acfa2016-04-19 16:27:55 +0000825 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
826 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
827 bool Tied, unsigned &NumberOfParts) {
828 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
829 PrePostActionTy &) {
830 auto *ThreadID = getThreadID(CGF, D.getLocStart());
831 auto *UpLoc = emitUpdateLocation(CGF, D.getLocStart());
832 llvm::Value *TaskArgs[] = {
833 UpLoc, ThreadID,
834 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
835 TaskTVar->getType()->castAs<PointerType>())
836 .getPointer()};
837 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
838 };
839 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
840 UntiedCodeGen);
841 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000842 assert(!ThreadIDVar->getType()->isPointerType() &&
843 "thread id variable must be of type kmp_int32 for tasks");
844 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
845 CodeGenFunction CGF(CGM, true);
Alexey Bataev823acfa2016-04-19 16:27:55 +0000846 CGOpenMPTaskOutlinedRegionInfo CGInfo(
847 *CS, ThreadIDVar, CodeGen, InnermostKind,
848 cast<OMPTaskDirective>(D).hasCancel(), Action);
Alexey Bataevd157d472015-06-24 03:35:38 +0000849 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev823acfa2016-04-19 16:27:55 +0000850 auto *Res = CGF.GenerateCapturedStmtFunction(*CS);
851 CodeGen.clearAction();
852 if (!Tied)
853 NumberOfParts = Action.getNumberOfParts();
854 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000855}
856
Alexey Bataev50b3c952016-02-19 10:38:26 +0000857Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
John McCall7f416cc2015-09-08 08:05:57 +0000858 CharUnits Align = getIdentAlign(CGM);
Alexey Bataev15007ba2014-05-07 06:18:01 +0000859 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000860 if (!Entry) {
861 if (!DefaultOpenMPPSource) {
862 // Initialize default location for psource field of ident_t structure of
863 // all ident_t objects. Format is ";file;function;line;column;;".
864 // Taken from
865 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
866 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +0000867 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000868 DefaultOpenMPPSource =
869 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
870 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000871 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
872 CGM.getModule(), IdentTy, /*isConstant*/ true,
873 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000874 DefaultOpenMPLocation->setUnnamedAddr(true);
John McCall7f416cc2015-09-08 08:05:57 +0000875 DefaultOpenMPLocation->setAlignment(Align.getQuantity());
Alexey Bataev9959db52014-05-06 10:08:46 +0000876
877 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000878 llvm::Constant *Values[] = {Zero,
879 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
880 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000881 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
882 DefaultOpenMPLocation->setInitializer(Init);
John McCall7f416cc2015-09-08 08:05:57 +0000883 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000884 }
John McCall7f416cc2015-09-08 08:05:57 +0000885 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +0000886}
887
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000888llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
889 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000890 unsigned Flags) {
891 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +0000892 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +0000893 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +0000894 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +0000895 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000896
897 assert(CGF.CurFn && "No function in current CodeGenFunction.");
898
John McCall7f416cc2015-09-08 08:05:57 +0000899 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000900 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
901 if (I != OpenMPLocThreadIDMap.end())
John McCall7f416cc2015-09-08 08:05:57 +0000902 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
903
Alexander Musmanc6388682014-12-15 07:07:06 +0000904 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
905 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +0000906 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000907 // Generate "ident_t .kmpc_loc.addr;"
John McCall7f416cc2015-09-08 08:05:57 +0000908 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
909 ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +0000910 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +0000911 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000912 LocValue = AI;
913
914 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
915 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000916 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
John McCall7f416cc2015-09-08 08:05:57 +0000917 CGM.getSize(getIdentSize(CGF.CGM)));
Alexey Bataev9959db52014-05-06 10:08:46 +0000918 }
919
920 // char **psource = &.kmpc_loc_<flags>.addr.psource;
John McCall7f416cc2015-09-08 08:05:57 +0000921 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000922
Alexey Bataevf002aca2014-05-30 05:48:40 +0000923 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
924 if (OMPDebugLoc == nullptr) {
925 SmallString<128> Buffer2;
926 llvm::raw_svector_ostream OS2(Buffer2);
927 // Build debug location
928 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
929 OS2 << ";" << PLoc.getFilename() << ";";
930 if (const FunctionDecl *FD =
931 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
932 OS2 << FD->getQualifiedNameAsString();
933 }
934 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
935 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
936 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000937 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000938 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000939 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
940
John McCall7f416cc2015-09-08 08:05:57 +0000941 // Our callers always pass this to a runtime function, so for
942 // convenience, go ahead and return a naked pointer.
943 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000944}
945
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000946llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
947 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000948 assert(CGF.CurFn && "No function in current CodeGenFunction.");
949
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000950 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000951 // Check whether we've already cached a load of the thread id in this
952 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000953 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000954 if (I != OpenMPLocThreadIDMap.end()) {
955 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000956 if (ThreadID != nullptr)
957 return ThreadID;
958 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +0000959 if (auto *OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000960 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000961 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000962 // Check if this an outlined function with thread id passed as argument.
963 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000964 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
965 // If value loaded in entry block, cache it and use it everywhere in
966 // function.
967 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
968 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
969 Elem.second.ThreadID = ThreadID;
970 }
971 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000972 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000973 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000974
975 // This is not an outlined function region - need to call __kmpc_int32
976 // kmpc_global_thread_num(ident_t *loc).
977 // Generate thread id value and cache this value for use across the
978 // function.
979 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
980 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
981 ThreadID =
982 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
983 emitUpdateLocation(CGF, Loc));
984 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
985 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000986 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000987}
988
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000989void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000990 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000991 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
992 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000993 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
994 for(auto *D : FunctionUDRMap[CGF.CurFn]) {
995 UDRMap.erase(D);
996 }
997 FunctionUDRMap.erase(CGF.CurFn);
998 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000999}
1000
1001llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001002 if (!IdentTy) {
1003 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001004 return llvm::PointerType::getUnqual(IdentTy);
1005}
1006
1007llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001008 if (!Kmpc_MicroTy) {
1009 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1010 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1011 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1012 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1013 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001014 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1015}
1016
1017llvm::Constant *
Alexey Bataev50b3c952016-02-19 10:38:26 +00001018CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001019 llvm::Constant *RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001020 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001021 case OMPRTL__kmpc_fork_call: {
1022 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1023 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001024 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1025 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +00001026 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001027 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001028 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
1029 break;
1030 }
1031 case OMPRTL__kmpc_global_thread_num: {
1032 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001033 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +00001034 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001035 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001036 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1037 break;
1038 }
Alexey Bataev97720002014-11-11 04:05:39 +00001039 case OMPRTL__kmpc_threadprivate_cached: {
1040 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1041 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1042 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1043 CGM.VoidPtrTy, CGM.SizeTy,
1044 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
1045 llvm::FunctionType *FnTy =
1046 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1047 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1048 break;
1049 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001050 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001051 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1052 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001053 llvm::Type *TypeParams[] = {
1054 getIdentTyPointerTy(), CGM.Int32Ty,
1055 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1056 llvm::FunctionType *FnTy =
1057 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1058 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1059 break;
1060 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001061 case OMPRTL__kmpc_critical_with_hint: {
1062 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1063 // kmp_critical_name *crit, uintptr_t hint);
1064 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1065 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1066 CGM.IntPtrTy};
1067 llvm::FunctionType *FnTy =
1068 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1069 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1070 break;
1071 }
Alexey Bataev97720002014-11-11 04:05:39 +00001072 case OMPRTL__kmpc_threadprivate_register: {
1073 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1074 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1075 // typedef void *(*kmpc_ctor)(void *);
1076 auto KmpcCtorTy =
1077 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1078 /*isVarArg*/ false)->getPointerTo();
1079 // typedef void *(*kmpc_cctor)(void *, void *);
1080 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1081 auto KmpcCopyCtorTy =
1082 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
1083 /*isVarArg*/ false)->getPointerTo();
1084 // typedef void (*kmpc_dtor)(void *);
1085 auto KmpcDtorTy =
1086 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1087 ->getPointerTo();
1088 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1089 KmpcCopyCtorTy, KmpcDtorTy};
1090 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
1091 /*isVarArg*/ false);
1092 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1093 break;
1094 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001095 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001096 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1097 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001098 llvm::Type *TypeParams[] = {
1099 getIdentTyPointerTy(), CGM.Int32Ty,
1100 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1101 llvm::FunctionType *FnTy =
1102 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1103 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1104 break;
1105 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001106 case OMPRTL__kmpc_cancel_barrier: {
1107 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1108 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001109 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1110 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001111 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1112 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001113 break;
1114 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001115 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001116 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001117 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1118 llvm::FunctionType *FnTy =
1119 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1120 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1121 break;
1122 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001123 case OMPRTL__kmpc_for_static_fini: {
1124 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1125 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1126 llvm::FunctionType *FnTy =
1127 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1128 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1129 break;
1130 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001131 case OMPRTL__kmpc_push_num_threads: {
1132 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1133 // kmp_int32 num_threads)
1134 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1135 CGM.Int32Ty};
1136 llvm::FunctionType *FnTy =
1137 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1138 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1139 break;
1140 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001141 case OMPRTL__kmpc_serialized_parallel: {
1142 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1143 // global_tid);
1144 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1145 llvm::FunctionType *FnTy =
1146 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1147 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1148 break;
1149 }
1150 case OMPRTL__kmpc_end_serialized_parallel: {
1151 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1152 // global_tid);
1153 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1154 llvm::FunctionType *FnTy =
1155 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1156 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1157 break;
1158 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001159 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001160 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001161 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
1162 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001163 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001164 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1165 break;
1166 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001167 case OMPRTL__kmpc_master: {
1168 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1169 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1170 llvm::FunctionType *FnTy =
1171 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1172 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1173 break;
1174 }
1175 case OMPRTL__kmpc_end_master: {
1176 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1177 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1178 llvm::FunctionType *FnTy =
1179 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1180 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1181 break;
1182 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001183 case OMPRTL__kmpc_omp_taskyield: {
1184 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1185 // int end_part);
1186 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1187 llvm::FunctionType *FnTy =
1188 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1189 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1190 break;
1191 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001192 case OMPRTL__kmpc_single: {
1193 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1194 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1195 llvm::FunctionType *FnTy =
1196 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1197 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1198 break;
1199 }
1200 case OMPRTL__kmpc_end_single: {
1201 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1202 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1203 llvm::FunctionType *FnTy =
1204 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1205 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1206 break;
1207 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001208 case OMPRTL__kmpc_omp_task_alloc: {
1209 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1210 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1211 // kmp_routine_entry_t *task_entry);
1212 assert(KmpRoutineEntryPtrTy != nullptr &&
1213 "Type kmp_routine_entry_t must be created.");
1214 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1215 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1216 // Return void * and then cast to particular kmp_task_t type.
1217 llvm::FunctionType *FnTy =
1218 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1219 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1220 break;
1221 }
1222 case OMPRTL__kmpc_omp_task: {
1223 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1224 // *new_task);
1225 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1226 CGM.VoidPtrTy};
1227 llvm::FunctionType *FnTy =
1228 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1229 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
1230 break;
1231 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001232 case OMPRTL__kmpc_copyprivate: {
1233 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00001234 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001235 // kmp_int32 didit);
1236 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1237 auto *CpyFnTy =
1238 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001239 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001240 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
1241 CGM.Int32Ty};
1242 llvm::FunctionType *FnTy =
1243 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1244 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
1245 break;
1246 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001247 case OMPRTL__kmpc_reduce: {
1248 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
1249 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
1250 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
1251 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1252 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1253 /*isVarArg=*/false);
1254 llvm::Type *TypeParams[] = {
1255 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1256 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1257 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1258 llvm::FunctionType *FnTy =
1259 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1260 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
1261 break;
1262 }
1263 case OMPRTL__kmpc_reduce_nowait: {
1264 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
1265 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
1266 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
1267 // *lck);
1268 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1269 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1270 /*isVarArg=*/false);
1271 llvm::Type *TypeParams[] = {
1272 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1273 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1274 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1275 llvm::FunctionType *FnTy =
1276 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1277 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
1278 break;
1279 }
1280 case OMPRTL__kmpc_end_reduce: {
1281 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
1282 // kmp_critical_name *lck);
1283 llvm::Type *TypeParams[] = {
1284 getIdentTyPointerTy(), CGM.Int32Ty,
1285 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1286 llvm::FunctionType *FnTy =
1287 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1288 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
1289 break;
1290 }
1291 case OMPRTL__kmpc_end_reduce_nowait: {
1292 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
1293 // kmp_critical_name *lck);
1294 llvm::Type *TypeParams[] = {
1295 getIdentTyPointerTy(), CGM.Int32Ty,
1296 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1297 llvm::FunctionType *FnTy =
1298 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1299 RTLFn =
1300 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
1301 break;
1302 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001303 case OMPRTL__kmpc_omp_task_begin_if0: {
1304 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1305 // *new_task);
1306 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1307 CGM.VoidPtrTy};
1308 llvm::FunctionType *FnTy =
1309 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1310 RTLFn =
1311 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
1312 break;
1313 }
1314 case OMPRTL__kmpc_omp_task_complete_if0: {
1315 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1316 // *new_task);
1317 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1318 CGM.VoidPtrTy};
1319 llvm::FunctionType *FnTy =
1320 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1321 RTLFn = CGM.CreateRuntimeFunction(FnTy,
1322 /*Name=*/"__kmpc_omp_task_complete_if0");
1323 break;
1324 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001325 case OMPRTL__kmpc_ordered: {
1326 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
1327 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1328 llvm::FunctionType *FnTy =
1329 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1330 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
1331 break;
1332 }
1333 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001334 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001335 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1336 llvm::FunctionType *FnTy =
1337 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1338 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
1339 break;
1340 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00001341 case OMPRTL__kmpc_omp_taskwait: {
1342 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
1343 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1344 llvm::FunctionType *FnTy =
1345 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1346 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
1347 break;
1348 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001349 case OMPRTL__kmpc_taskgroup: {
1350 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
1351 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1352 llvm::FunctionType *FnTy =
1353 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1354 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
1355 break;
1356 }
1357 case OMPRTL__kmpc_end_taskgroup: {
1358 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
1359 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1360 llvm::FunctionType *FnTy =
1361 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1362 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
1363 break;
1364 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00001365 case OMPRTL__kmpc_push_proc_bind: {
1366 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
1367 // int proc_bind)
1368 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1369 llvm::FunctionType *FnTy =
1370 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1371 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
1372 break;
1373 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00001374 case OMPRTL__kmpc_omp_task_with_deps: {
1375 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
1376 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
1377 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
1378 llvm::Type *TypeParams[] = {
1379 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
1380 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
1381 llvm::FunctionType *FnTy =
1382 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1383 RTLFn =
1384 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
1385 break;
1386 }
1387 case OMPRTL__kmpc_omp_wait_deps: {
1388 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
1389 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
1390 // kmp_depend_info_t *noalias_dep_list);
1391 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1392 CGM.Int32Ty, CGM.VoidPtrTy,
1393 CGM.Int32Ty, CGM.VoidPtrTy};
1394 llvm::FunctionType *FnTy =
1395 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1396 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
1397 break;
1398 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00001399 case OMPRTL__kmpc_cancellationpoint: {
1400 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
1401 // global_tid, kmp_int32 cncl_kind)
1402 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1403 llvm::FunctionType *FnTy =
1404 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1405 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
1406 break;
1407 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001408 case OMPRTL__kmpc_cancel: {
1409 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
1410 // kmp_int32 cncl_kind)
1411 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1412 llvm::FunctionType *FnTy =
1413 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1414 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
1415 break;
1416 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00001417 case OMPRTL__kmpc_push_num_teams: {
1418 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
1419 // kmp_int32 num_teams, kmp_int32 num_threads)
1420 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1421 CGM.Int32Ty};
1422 llvm::FunctionType *FnTy =
1423 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1424 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
1425 break;
1426 }
1427 case OMPRTL__kmpc_fork_teams: {
1428 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
1429 // microtask, ...);
1430 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1431 getKmpc_MicroPointerTy()};
1432 llvm::FunctionType *FnTy =
1433 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
1434 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
1435 break;
1436 }
Samuel Antaobed3c462015-10-02 16:14:20 +00001437 case OMPRTL__tgt_target: {
1438 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
1439 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
1440 // *arg_types);
1441 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1442 CGM.VoidPtrTy,
1443 CGM.Int32Ty,
1444 CGM.VoidPtrPtrTy,
1445 CGM.VoidPtrPtrTy,
1446 CGM.SizeTy->getPointerTo(),
1447 CGM.Int32Ty->getPointerTo()};
1448 llvm::FunctionType *FnTy =
1449 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1450 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
1451 break;
1452 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00001453 case OMPRTL__tgt_target_teams: {
1454 // Build int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
1455 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
1456 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
1457 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1458 CGM.VoidPtrTy,
1459 CGM.Int32Ty,
1460 CGM.VoidPtrPtrTy,
1461 CGM.VoidPtrPtrTy,
1462 CGM.SizeTy->getPointerTo(),
1463 CGM.Int32Ty->getPointerTo(),
1464 CGM.Int32Ty,
1465 CGM.Int32Ty};
1466 llvm::FunctionType *FnTy =
1467 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1468 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
1469 break;
1470 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00001471 case OMPRTL__tgt_register_lib: {
1472 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
1473 QualType ParamTy =
1474 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1475 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1476 llvm::FunctionType *FnTy =
1477 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1478 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
1479 break;
1480 }
1481 case OMPRTL__tgt_unregister_lib: {
1482 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
1483 QualType ParamTy =
1484 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1485 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1486 llvm::FunctionType *FnTy =
1487 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1488 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
1489 break;
1490 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001491 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00001492 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00001493 return RTLFn;
1494}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001495
Alexander Musman21212e42015-03-13 10:38:23 +00001496llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
1497 bool IVSigned) {
1498 assert((IVSize == 32 || IVSize == 64) &&
1499 "IV size is not compatible with the omp runtime");
1500 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
1501 : "__kmpc_for_static_init_4u")
1502 : (IVSigned ? "__kmpc_for_static_init_8"
1503 : "__kmpc_for_static_init_8u");
1504 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1505 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1506 llvm::Type *TypeParams[] = {
1507 getIdentTyPointerTy(), // loc
1508 CGM.Int32Ty, // tid
1509 CGM.Int32Ty, // schedtype
1510 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1511 PtrTy, // p_lower
1512 PtrTy, // p_upper
1513 PtrTy, // p_stride
1514 ITy, // incr
1515 ITy // chunk
1516 };
1517 llvm::FunctionType *FnTy =
1518 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1519 return CGM.CreateRuntimeFunction(FnTy, Name);
1520}
1521
Alexander Musman92bdaab2015-03-12 13:37:50 +00001522llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
1523 bool IVSigned) {
1524 assert((IVSize == 32 || IVSize == 64) &&
1525 "IV size is not compatible with the omp runtime");
1526 auto Name =
1527 IVSize == 32
1528 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
1529 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
1530 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1531 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
1532 CGM.Int32Ty, // tid
1533 CGM.Int32Ty, // schedtype
1534 ITy, // lower
1535 ITy, // upper
1536 ITy, // stride
1537 ITy // chunk
1538 };
1539 llvm::FunctionType *FnTy =
1540 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1541 return CGM.CreateRuntimeFunction(FnTy, Name);
1542}
1543
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001544llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
1545 bool IVSigned) {
1546 assert((IVSize == 32 || IVSize == 64) &&
1547 "IV size is not compatible with the omp runtime");
1548 auto Name =
1549 IVSize == 32
1550 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1551 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1552 llvm::Type *TypeParams[] = {
1553 getIdentTyPointerTy(), // loc
1554 CGM.Int32Ty, // tid
1555 };
1556 llvm::FunctionType *FnTy =
1557 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1558 return CGM.CreateRuntimeFunction(FnTy, Name);
1559}
1560
Alexander Musman92bdaab2015-03-12 13:37:50 +00001561llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
1562 bool IVSigned) {
1563 assert((IVSize == 32 || IVSize == 64) &&
1564 "IV size is not compatible with the omp runtime");
1565 auto Name =
1566 IVSize == 32
1567 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1568 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1569 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1570 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1571 llvm::Type *TypeParams[] = {
1572 getIdentTyPointerTy(), // loc
1573 CGM.Int32Ty, // tid
1574 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1575 PtrTy, // p_lower
1576 PtrTy, // p_upper
1577 PtrTy // p_stride
1578 };
1579 llvm::FunctionType *FnTy =
1580 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1581 return CGM.CreateRuntimeFunction(FnTy, Name);
1582}
1583
Alexey Bataev97720002014-11-11 04:05:39 +00001584llvm::Constant *
1585CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001586 assert(!CGM.getLangOpts().OpenMPUseTLS ||
1587 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00001588 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001589 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001590 Twine(CGM.getMangledName(VD)) + ".cache.");
1591}
1592
John McCall7f416cc2015-09-08 08:05:57 +00001593Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1594 const VarDecl *VD,
1595 Address VDAddr,
1596 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001597 if (CGM.getLangOpts().OpenMPUseTLS &&
1598 CGM.getContext().getTargetInfo().isTLSSupported())
1599 return VDAddr;
1600
John McCall7f416cc2015-09-08 08:05:57 +00001601 auto VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001602 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001603 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1604 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001605 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1606 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00001607 return Address(CGF.EmitRuntimeCall(
1608 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
1609 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00001610}
1611
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001612void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00001613 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00001614 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1615 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1616 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001617 auto OMPLoc = emitUpdateLocation(CGF, Loc);
1618 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00001619 OMPLoc);
1620 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1621 // to register constructor/destructor for variable.
1622 llvm::Value *Args[] = {OMPLoc,
John McCall7f416cc2015-09-08 08:05:57 +00001623 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1624 CGM.VoidPtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001625 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001626 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001627 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001628}
1629
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001630llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00001631 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00001632 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001633 if (CGM.getLangOpts().OpenMPUseTLS &&
1634 CGM.getContext().getTargetInfo().isTLSSupported())
1635 return nullptr;
1636
Alexey Bataev97720002014-11-11 04:05:39 +00001637 VD = VD->getDefinition(CGM.getContext());
1638 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
1639 ThreadPrivateWithDefinition.insert(VD);
1640 QualType ASTTy = VD->getType();
1641
1642 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1643 auto Init = VD->getAnyInitializer();
1644 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1645 // Generate function that re-emits the declaration's initializer into the
1646 // threadprivate copy of the variable VD
1647 CodeGenFunction CtorCGF(CGM);
1648 FunctionArgList Args;
1649 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1650 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1651 Args.push_back(&Dst);
1652
John McCallc56a8b32016-03-11 04:30:31 +00001653 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1654 CGM.getContext().VoidPtrTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001655 auto FTy = CGM.getTypes().GetFunctionType(FI);
1656 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001657 FTy, ".__kmpc_global_ctor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001658 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1659 Args, SourceLocation());
1660 auto ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001661 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001662 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00001663 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1664 Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
1665 CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00001666 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1667 /*IsInitializer=*/true);
1668 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001669 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001670 CGM.getContext().VoidPtrTy, Dst.getLocation());
1671 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1672 CtorCGF.FinishFunction();
1673 Ctor = Fn;
1674 }
1675 if (VD->getType().isDestructedType() != QualType::DK_none) {
1676 // Generate function that emits destructor call for the threadprivate copy
1677 // of the variable VD
1678 CodeGenFunction DtorCGF(CGM);
1679 FunctionArgList Args;
1680 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1681 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1682 Args.push_back(&Dst);
1683
John McCallc56a8b32016-03-11 04:30:31 +00001684 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1685 CGM.getContext().VoidTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001686 auto FTy = CGM.getTypes().GetFunctionType(FI);
1687 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001688 FTy, ".__kmpc_global_dtor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001689 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1690 SourceLocation());
1691 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1692 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00001693 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1694 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001695 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1696 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1697 DtorCGF.FinishFunction();
1698 Dtor = Fn;
1699 }
1700 // Do not emit init function if it is not required.
1701 if (!Ctor && !Dtor)
1702 return nullptr;
1703
1704 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1705 auto CopyCtorTy =
1706 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1707 /*isVarArg=*/false)->getPointerTo();
1708 // Copying constructor for the threadprivate variable.
1709 // Must be NULL - reserved by runtime, but currently it requires that this
1710 // parameter is always NULL. Otherwise it fires assertion.
1711 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1712 if (Ctor == nullptr) {
1713 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1714 /*isVarArg=*/false)->getPointerTo();
1715 Ctor = llvm::Constant::getNullValue(CtorTy);
1716 }
1717 if (Dtor == nullptr) {
1718 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1719 /*isVarArg=*/false)->getPointerTo();
1720 Dtor = llvm::Constant::getNullValue(DtorTy);
1721 }
1722 if (!CGF) {
1723 auto InitFunctionTy =
1724 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1725 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001726 InitFunctionTy, ".__omp_threadprivate_init_.",
1727 CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00001728 CodeGenFunction InitCGF(CGM);
1729 FunctionArgList ArgList;
1730 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1731 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1732 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001733 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001734 InitCGF.FinishFunction();
1735 return InitFunction;
1736 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001737 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001738 }
1739 return nullptr;
1740}
1741
Alexey Bataev1d677132015-04-22 13:57:31 +00001742/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1743/// function. Here is the logic:
1744/// if (Cond) {
1745/// ThenGen();
1746/// } else {
1747/// ElseGen();
1748/// }
1749static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1750 const RegionCodeGenTy &ThenGen,
1751 const RegionCodeGenTy &ElseGen) {
1752 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1753
1754 // If the condition constant folds and can be elided, try to avoid emitting
1755 // the condition and the dead arm of the if/else.
1756 bool CondConstant;
1757 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001758 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00001759 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001760 else
Alexey Bataev1d677132015-04-22 13:57:31 +00001761 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001762 return;
1763 }
1764
1765 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1766 // emit the conditional branch.
1767 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1768 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1769 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1770 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1771
1772 // Emit the 'then' code.
1773 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001774 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001775 CGF.EmitBranch(ContBlock);
1776 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001777 // There is no need to emit line number for unconditional branch.
1778 (void)ApplyDebugLocation::CreateEmpty(CGF);
1779 CGF.EmitBlock(ElseBlock);
1780 ElseGen(CGF);
1781 // There is no need to emit line number for unconditional branch.
1782 (void)ApplyDebugLocation::CreateEmpty(CGF);
1783 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00001784 // Emit the continuation block for code after the if.
1785 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001786}
1787
Alexey Bataev1d677132015-04-22 13:57:31 +00001788void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1789 llvm::Value *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001790 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00001791 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001792 if (!CGF.HaveInsertPoint())
1793 return;
Alexey Bataev1d677132015-04-22 13:57:31 +00001794 auto *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001795 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
1796 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001797 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001798 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00001799 llvm::Value *Args[] = {
1800 RTLoc,
1801 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001802 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00001803 llvm::SmallVector<llvm::Value *, 16> RealArgs;
1804 RealArgs.append(std::begin(Args), std::end(Args));
1805 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1806
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001807 auto RTLFn = RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001808 CGF.EmitRuntimeCall(RTLFn, RealArgs);
1809 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001810 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
1811 PrePostActionTy &) {
1812 auto &RT = CGF.CGM.getOpenMPRuntime();
1813 auto ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00001814 // Build calls:
1815 // __kmpc_serialized_parallel(&Loc, GTid);
1816 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001817 CGF.EmitRuntimeCall(
1818 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001819
Alexey Bataev1d677132015-04-22 13:57:31 +00001820 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001821 auto ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00001822 Address ZeroAddr =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001823 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
1824 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00001825 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00001826 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
1827 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
1828 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1829 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev1d677132015-04-22 13:57:31 +00001830 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001831
Alexey Bataev1d677132015-04-22 13:57:31 +00001832 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001833 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00001834 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001835 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
1836 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00001837 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001838 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00001839 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001840 else {
1841 RegionCodeGenTy ThenRCG(ThenGen);
1842 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00001843 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001844}
1845
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001846// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001847// thread-ID variable (it is passed in a first argument of the outlined function
1848// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1849// regular serial code region, get thread ID by calling kmp_int32
1850// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1851// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00001852Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
1853 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00001854 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001855 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001856 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001857 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001858
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001859 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001860 auto Int32Ty =
1861 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1862 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1863 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00001864 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00001865
1866 return ThreadIDTemp;
1867}
1868
Alexey Bataev97720002014-11-11 04:05:39 +00001869llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001870CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001871 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001872 SmallString<256> Buffer;
1873 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001874 Out << Name;
1875 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001876 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1877 if (Elem.second) {
1878 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001879 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001880 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001881 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001882
David Blaikie13156b62014-11-19 03:06:06 +00001883 return Elem.second = new llvm::GlobalVariable(
1884 CGM.getModule(), Ty, /*IsConstant*/ false,
1885 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1886 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001887}
1888
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001889llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001890 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001891 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001892}
1893
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001894namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001895/// Common pre(post)-action for different OpenMP constructs.
1896class CommonActionTy final : public PrePostActionTy {
1897 llvm::Value *EnterCallee;
1898 ArrayRef<llvm::Value *> EnterArgs;
1899 llvm::Value *ExitCallee;
1900 ArrayRef<llvm::Value *> ExitArgs;
1901 bool Conditional;
1902 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001903
1904public:
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001905 CommonActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs,
1906 llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs,
1907 bool Conditional = false)
1908 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1909 ExitArgs(ExitArgs), Conditional(Conditional) {}
1910 void Enter(CodeGenFunction &CGF) override {
1911 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
1912 if (Conditional) {
1913 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
1914 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1915 ContBlock = CGF.createBasicBlock("omp_if.end");
1916 // Generate the branch (If-stmt)
1917 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1918 CGF.EmitBlock(ThenBlock);
1919 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00001920 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001921 void Done(CodeGenFunction &CGF) {
1922 // Emit the rest of blocks/branches
1923 CGF.EmitBranch(ContBlock);
1924 CGF.EmitBlock(ContBlock, true);
1925 }
1926 void Exit(CodeGenFunction &CGF) override {
1927 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001928 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001929};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001930} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001931
1932void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1933 StringRef CriticalName,
1934 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00001935 SourceLocation Loc, const Expr *Hint) {
1936 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001937 // CriticalOpGen();
1938 // __kmpc_end_critical(ident_t *, gtid, Lock);
1939 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00001940 if (!CGF.HaveInsertPoint())
1941 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00001942 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1943 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001944 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
1945 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00001946 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001947 EnterArgs.push_back(CGF.Builder.CreateIntCast(
1948 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
1949 }
1950 CommonActionTy Action(
1951 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
1952 : OMPRTL__kmpc_critical),
1953 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
1954 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00001955 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001956}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001957
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001958void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001959 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001960 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001961 if (!CGF.HaveInsertPoint())
1962 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00001963 // if(__kmpc_master(ident_t *, gtid)) {
1964 // MasterOpGen();
1965 // __kmpc_end_master(ident_t *, gtid);
1966 // }
1967 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001968 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001969 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
1970 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
1971 /*Conditional=*/true);
1972 MasterOpGen.setAction(Action);
1973 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
1974 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00001975}
1976
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001977void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
1978 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001979 if (!CGF.HaveInsertPoint())
1980 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00001981 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
1982 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001983 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00001984 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001985 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev823acfa2016-04-19 16:27:55 +00001986 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
1987 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00001988}
1989
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001990void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
1991 const RegionCodeGenTy &TaskgroupOpGen,
1992 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001993 if (!CGF.HaveInsertPoint())
1994 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001995 // __kmpc_taskgroup(ident_t *, gtid);
1996 // TaskgroupOpGen();
1997 // __kmpc_end_taskgroup(ident_t *, gtid);
1998 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001999 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2000 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
2001 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
2002 Args);
2003 TaskgroupOpGen.setAction(Action);
2004 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002005}
2006
John McCall7f416cc2015-09-08 08:05:57 +00002007/// Given an array of pointers to variables, project the address of a
2008/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002009static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
2010 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00002011 // Pull out the pointer to the variable.
2012 Address PtrAddr =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002013 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00002014 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
2015
2016 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002017 Addr = CGF.Builder.CreateElementBitCast(
2018 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00002019 return Addr;
2020}
2021
Alexey Bataeva63048e2015-03-23 06:18:07 +00002022static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00002023 CodeGenModule &CGM, llvm::Type *ArgsType,
2024 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
2025 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002026 auto &C = CGM.getContext();
2027 // void copy_func(void *LHSArg, void *RHSArg);
2028 FunctionArgList Args;
2029 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2030 C.VoidPtrTy);
2031 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2032 C.VoidPtrTy);
2033 Args.push_back(&LHSArg);
2034 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00002035 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002036 auto *Fn = llvm::Function::Create(
2037 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
2038 ".omp.copyprivate.copy_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002039 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002040 CodeGenFunction CGF(CGM);
2041 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00002042 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002043 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00002044 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2045 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2046 ArgsType), CGF.getPointerAlign());
2047 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2048 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2049 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00002050 // *(Type0*)Dst[0] = *(Type0*)Src[0];
2051 // *(Type1*)Dst[1] = *(Type1*)Src[1];
2052 // ...
2053 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00002054 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002055 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2056 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
2057
2058 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2059 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
2060
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002061 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2062 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00002063 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002064 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002065 CGF.FinishFunction();
2066 return Fn;
2067}
2068
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002069void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002070 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002071 SourceLocation Loc,
2072 ArrayRef<const Expr *> CopyprivateVars,
2073 ArrayRef<const Expr *> SrcExprs,
2074 ArrayRef<const Expr *> DstExprs,
2075 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002076 if (!CGF.HaveInsertPoint())
2077 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00002078 assert(CopyprivateVars.size() == SrcExprs.size() &&
2079 CopyprivateVars.size() == DstExprs.size() &&
2080 CopyprivateVars.size() == AssignmentOps.size());
2081 auto &C = CGM.getContext();
2082 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002083 // if(__kmpc_single(ident_t *, gtid)) {
2084 // SingleOpGen();
2085 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002086 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002087 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002088 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2089 // <copy_func>, did_it);
2090
John McCall7f416cc2015-09-08 08:05:57 +00002091 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00002092 if (!CopyprivateVars.empty()) {
2093 // int32 did_it = 0;
2094 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2095 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00002096 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002097 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002098 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00002099 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002100 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
2101 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
2102 /*Conditional=*/true);
2103 SingleOpGen.setAction(Action);
2104 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
2105 if (DidIt.isValid()) {
2106 // did_it = 1;
2107 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
2108 }
2109 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002110 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2111 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00002112 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002113 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
2114 auto CopyprivateArrayTy =
2115 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2116 /*IndexTypeQuals=*/0);
2117 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00002118 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002119 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
2120 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002121 Address Elem = CGF.Builder.CreateConstArrayGEP(
2122 CopyprivateList, I, CGF.getPointerSize());
2123 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00002124 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002125 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
2126 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002127 }
2128 // Build function that copies private values from single region to all other
2129 // threads in the corresponding parallel region.
2130 auto *CpyFn = emitCopyprivateCopyFunction(
2131 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00002132 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataev1189bd02016-01-26 12:20:39 +00002133 auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00002134 Address CL =
2135 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
2136 CGF.VoidPtrTy);
2137 auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002138 llvm::Value *Args[] = {
2139 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
2140 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00002141 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00002142 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00002143 CpyFn, // void (*) (void *, void *) <copy_func>
2144 DidItVal // i32 did_it
2145 };
2146 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
2147 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002148}
2149
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002150void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
2151 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00002152 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002153 if (!CGF.HaveInsertPoint())
2154 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002155 // __kmpc_ordered(ident_t *, gtid);
2156 // OrderedOpGen();
2157 // __kmpc_end_ordered(ident_t *, gtid);
2158 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00002159 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002160 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002161 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
2162 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
2163 Args);
2164 OrderedOpGen.setAction(Action);
2165 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2166 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002167 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00002168 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002169}
2170
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002171void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev25e5b442015-09-15 12:52:43 +00002172 OpenMPDirectiveKind Kind, bool EmitChecks,
2173 bool ForceSimpleCall) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002174 if (!CGF.HaveInsertPoint())
2175 return;
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00002176 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002177 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002178 unsigned Flags;
2179 if (Kind == OMPD_for)
2180 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2181 else if (Kind == OMPD_sections)
2182 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2183 else if (Kind == OMPD_single)
2184 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2185 else if (Kind == OMPD_barrier)
2186 Flags = OMP_IDENT_BARRIER_EXPL;
2187 else
2188 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002189 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
2190 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002191 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
2192 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002193 if (auto *OMPRegionInfo =
2194 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00002195 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002196 auto *Result = CGF.EmitRuntimeCall(
2197 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00002198 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002199 // if (__kmpc_cancel_barrier()) {
2200 // exit from construct;
2201 // }
2202 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
2203 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
2204 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
2205 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2206 CGF.EmitBlock(ExitBB);
2207 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00002208 auto CancelDestination =
2209 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002210 CGF.EmitBranchThroughCleanup(CancelDestination);
2211 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2212 }
2213 return;
2214 }
2215 }
2216 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002217}
2218
Alexander Musmanc6388682014-12-15 07:07:06 +00002219/// \brief Map the OpenMP loop schedule to the runtime enumeration.
2220static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002221 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002222 switch (ScheduleKind) {
2223 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002224 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2225 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00002226 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002227 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002228 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002229 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002230 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002231 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2232 case OMPC_SCHEDULE_auto:
2233 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00002234 case OMPC_SCHEDULE_unknown:
2235 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002236 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00002237 }
2238 llvm_unreachable("Unexpected runtime schedule");
2239}
2240
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002241/// \brief Map the OpenMP distribute schedule to the runtime enumeration.
2242static OpenMPSchedType
2243getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
2244 // only static is allowed for dist_schedule
2245 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2246}
2247
Alexander Musmanc6388682014-12-15 07:07:06 +00002248bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
2249 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002250 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00002251 return Schedule == OMP_sch_static;
2252}
2253
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002254bool CGOpenMPRuntime::isStaticNonchunked(
2255 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2256 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2257 return Schedule == OMP_dist_sch_static;
2258}
2259
2260
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002261bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002262 auto Schedule =
2263 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002264 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
2265 return Schedule != OMP_sch_static;
2266}
2267
John McCall7f416cc2015-09-08 08:05:57 +00002268void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
2269 SourceLocation Loc,
2270 OpenMPScheduleClauseKind ScheduleKind,
2271 unsigned IVSize, bool IVSigned,
2272 bool Ordered, llvm::Value *UB,
2273 llvm::Value *Chunk) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002274 if (!CGF.HaveInsertPoint())
2275 return;
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002276 OpenMPSchedType Schedule =
2277 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00002278 assert(Ordered ||
2279 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2280 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
2281 // Call __kmpc_dispatch_init(
2282 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
2283 // kmp_int[32|64] lower, kmp_int[32|64] upper,
2284 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002285
John McCall7f416cc2015-09-08 08:05:57 +00002286 // If the Chunk was not specified in the clause - use default value 1.
2287 if (Chunk == nullptr)
2288 Chunk = CGF.Builder.getIntN(IVSize, 1);
2289 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002290 emitUpdateLocation(CGF, Loc),
2291 getThreadID(CGF, Loc),
2292 CGF.Builder.getInt32(Schedule), // Schedule type
2293 CGF.Builder.getIntN(IVSize, 0), // Lower
2294 UB, // Upper
2295 CGF.Builder.getIntN(IVSize, 1), // Stride
2296 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00002297 };
2298 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
2299}
2300
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002301static void emitForStaticInitCall(CodeGenFunction &CGF,
2302 SourceLocation Loc,
2303 llvm::Value * UpdateLocation,
2304 llvm::Value * ThreadId,
2305 llvm::Constant * ForStaticInitFunction,
2306 OpenMPSchedType Schedule,
2307 unsigned IVSize, bool IVSigned, bool Ordered,
2308 Address IL, Address LB, Address UB,
2309 Address ST, llvm::Value *Chunk) {
2310 if (!CGF.HaveInsertPoint())
2311 return;
2312
2313 assert(!Ordered);
2314 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2315 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2316 Schedule == OMP_dist_sch_static ||
2317 Schedule == OMP_dist_sch_static_chunked);
2318
2319 // Call __kmpc_for_static_init(
2320 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
2321 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
2322 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
2323 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
2324 if (Chunk == nullptr) {
2325 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2326 Schedule == OMP_dist_sch_static) &&
2327 "expected static non-chunked schedule");
2328 // If the Chunk was not specified in the clause - use default value 1.
2329 Chunk = CGF.Builder.getIntN(IVSize, 1);
2330 } else {
2331 assert((Schedule == OMP_sch_static_chunked ||
2332 Schedule == OMP_ord_static_chunked ||
2333 Schedule == OMP_dist_sch_static_chunked) &&
2334 "expected static chunked schedule");
2335 }
2336 llvm::Value *Args[] = {
2337 UpdateLocation,
2338 ThreadId,
2339 CGF.Builder.getInt32(Schedule), // Schedule type
2340 IL.getPointer(), // &isLastIter
2341 LB.getPointer(), // &LB
2342 UB.getPointer(), // &UB
2343 ST.getPointer(), // &Stride
2344 CGF.Builder.getIntN(IVSize, 1), // Incr
2345 Chunk // Chunk
2346 };
2347 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
2348}
2349
John McCall7f416cc2015-09-08 08:05:57 +00002350void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
2351 SourceLocation Loc,
2352 OpenMPScheduleClauseKind ScheduleKind,
2353 unsigned IVSize, bool IVSigned,
2354 bool Ordered, Address IL, Address LB,
2355 Address UB, Address ST,
2356 llvm::Value *Chunk) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002357 OpenMPSchedType ScheduleNum = getRuntimeSchedule(ScheduleKind, Chunk != nullptr,
2358 Ordered);
2359 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2360 auto *ThreadId = getThreadID(CGF, Loc);
2361 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
2362 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction,
2363 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
2364}
John McCall7f416cc2015-09-08 08:05:57 +00002365
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002366void CGOpenMPRuntime::emitDistributeStaticInit(CodeGenFunction &CGF,
2367 SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind,
2368 unsigned IVSize, bool IVSigned,
2369 bool Ordered, Address IL, Address LB,
2370 Address UB, Address ST,
2371 llvm::Value *Chunk) {
2372 OpenMPSchedType ScheduleNum = getRuntimeSchedule(SchedKind, Chunk != nullptr);
2373 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2374 auto *ThreadId = getThreadID(CGF, Loc);
2375 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
2376 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction,
2377 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002378}
2379
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002380void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
2381 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002382 if (!CGF.HaveInsertPoint())
2383 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00002384 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002385 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002386 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
2387 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00002388}
2389
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002390void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
2391 SourceLocation Loc,
2392 unsigned IVSize,
2393 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002394 if (!CGF.HaveInsertPoint())
2395 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002396 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002397 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002398 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
2399}
2400
Alexander Musman92bdaab2015-03-12 13:37:50 +00002401llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
2402 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00002403 bool IVSigned, Address IL,
2404 Address LB, Address UB,
2405 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002406 // Call __kmpc_dispatch_next(
2407 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2408 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2409 // kmp_int[32|64] *p_stride);
2410 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002411 emitUpdateLocation(CGF, Loc),
2412 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002413 IL.getPointer(), // &isLastIter
2414 LB.getPointer(), // &Lower
2415 UB.getPointer(), // &Upper
2416 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00002417 };
2418 llvm::Value *Call =
2419 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
2420 return CGF.EmitScalarConversion(
2421 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00002422 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002423}
2424
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002425void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
2426 llvm::Value *NumThreads,
2427 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002428 if (!CGF.HaveInsertPoint())
2429 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00002430 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
2431 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002432 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00002433 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002434 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
2435 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00002436}
2437
Alexey Bataev7f210c62015-06-18 13:40:03 +00002438void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
2439 OpenMPProcBindClauseKind ProcBind,
2440 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002441 if (!CGF.HaveInsertPoint())
2442 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00002443 // Constants for proc bind value accepted by the runtime.
2444 enum ProcBindTy {
2445 ProcBindFalse = 0,
2446 ProcBindTrue,
2447 ProcBindMaster,
2448 ProcBindClose,
2449 ProcBindSpread,
2450 ProcBindIntel,
2451 ProcBindDefault
2452 } RuntimeProcBind;
2453 switch (ProcBind) {
2454 case OMPC_PROC_BIND_master:
2455 RuntimeProcBind = ProcBindMaster;
2456 break;
2457 case OMPC_PROC_BIND_close:
2458 RuntimeProcBind = ProcBindClose;
2459 break;
2460 case OMPC_PROC_BIND_spread:
2461 RuntimeProcBind = ProcBindSpread;
2462 break;
2463 case OMPC_PROC_BIND_unknown:
2464 llvm_unreachable("Unsupported proc_bind value.");
2465 }
2466 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
2467 llvm::Value *Args[] = {
2468 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2469 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
2470 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
2471}
2472
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002473void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
2474 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002475 if (!CGF.HaveInsertPoint())
2476 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00002477 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002478 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
2479 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00002480}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002481
Alexey Bataev62b63b12015-03-10 07:28:44 +00002482namespace {
2483/// \brief Indexes of fields for type kmp_task_t.
2484enum KmpTaskTFields {
2485 /// \brief List of shared variables.
2486 KmpTaskTShareds,
2487 /// \brief Task routine.
2488 KmpTaskTRoutine,
2489 /// \brief Partition id for the untied tasks.
2490 KmpTaskTPartId,
2491 /// \brief Function with call of destructors for private variables.
2492 KmpTaskTDestructors,
2493};
Hans Wennborg7eb54642015-09-10 17:07:54 +00002494} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00002495
Samuel Antaoee8fb302016-01-06 13:42:12 +00002496bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
2497 // FIXME: Add other entries type when they become supported.
2498 return OffloadEntriesTargetRegion.empty();
2499}
2500
2501/// \brief Initialize target region entry.
2502void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2503 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2504 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002505 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002506 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
2507 "only required for the device "
2508 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002509 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002510 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr);
2511 ++OffloadingEntriesNum;
2512}
2513
2514void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2515 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2516 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002517 llvm::Constant *Addr, llvm::Constant *ID) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002518 // If we are emitting code for a target, the entry is already initialized,
2519 // only has to be registered.
2520 if (CGM.getLangOpts().OpenMPIsDevice) {
Samuel Antao2de62b02016-02-13 23:35:10 +00002521 assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) &&
Samuel Antaoee8fb302016-01-06 13:42:12 +00002522 "Entry must exist.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002523 auto &Entry =
2524 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00002525 assert(Entry.isValid() && "Entry not initialized!");
2526 Entry.setAddress(Addr);
2527 Entry.setID(ID);
2528 return;
2529 } else {
2530 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID);
Samuel Antao2de62b02016-02-13 23:35:10 +00002531 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002532 }
2533}
2534
2535bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00002536 unsigned DeviceID, unsigned FileID, StringRef ParentName,
2537 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002538 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
2539 if (PerDevice == OffloadEntriesTargetRegion.end())
2540 return false;
2541 auto PerFile = PerDevice->second.find(FileID);
2542 if (PerFile == PerDevice->second.end())
2543 return false;
2544 auto PerParentName = PerFile->second.find(ParentName);
2545 if (PerParentName == PerFile->second.end())
2546 return false;
2547 auto PerLine = PerParentName->second.find(LineNum);
2548 if (PerLine == PerParentName->second.end())
2549 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002550 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00002551 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00002552 return false;
2553 return true;
2554}
2555
2556void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
2557 const OffloadTargetRegionEntryInfoActTy &Action) {
2558 // Scan all target region entries and perform the provided action.
2559 for (auto &D : OffloadEntriesTargetRegion)
2560 for (auto &F : D.second)
2561 for (auto &P : F.second)
2562 for (auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00002563 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002564}
2565
2566/// \brief Create a Ctor/Dtor-like function whose body is emitted through
2567/// \a Codegen. This is used to emit the two functions that register and
2568/// unregister the descriptor of the current compilation unit.
2569static llvm::Function *
2570createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
2571 const RegionCodeGenTy &Codegen) {
2572 auto &C = CGM.getContext();
2573 FunctionArgList Args;
2574 ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(),
2575 /*Id=*/nullptr, C.VoidPtrTy);
2576 Args.push_back(&DummyPtr);
2577
2578 CodeGenFunction CGF(CGM);
2579 GlobalDecl();
John McCallc56a8b32016-03-11 04:30:31 +00002580 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002581 auto FTy = CGM.getTypes().GetFunctionType(FI);
2582 auto *Fn =
2583 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation());
2584 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation());
2585 Codegen(CGF);
2586 CGF.FinishFunction();
2587 return Fn;
2588}
2589
2590llvm::Function *
2591CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
2592
2593 // If we don't have entries or if we are emitting code for the device, we
2594 // don't need to do anything.
2595 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
2596 return nullptr;
2597
2598 auto &M = CGM.getModule();
2599 auto &C = CGM.getContext();
2600
2601 // Get list of devices we care about
2602 auto &Devices = CGM.getLangOpts().OMPTargetTriples;
2603
2604 // We should be creating an offloading descriptor only if there are devices
2605 // specified.
2606 assert(!Devices.empty() && "No OpenMP offloading devices??");
2607
2608 // Create the external variables that will point to the begin and end of the
2609 // host entries section. These will be defined by the linker.
2610 auto *OffloadEntryTy =
2611 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
2612 llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable(
2613 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002614 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002615 ".omp_offloading.entries_begin");
2616 llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable(
2617 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002618 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002619 ".omp_offloading.entries_end");
2620
2621 // Create all device images
2622 llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires;
2623 auto *DeviceImageTy = cast<llvm::StructType>(
2624 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
2625
2626 for (unsigned i = 0; i < Devices.size(); ++i) {
2627 StringRef T = Devices[i].getTriple();
2628 auto *ImgBegin = new llvm::GlobalVariable(
2629 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002630 /*Initializer=*/nullptr,
2631 Twine(".omp_offloading.img_start.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002632 auto *ImgEnd = new llvm::GlobalVariable(
2633 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002634 /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002635
2636 llvm::Constant *Dev =
2637 llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd,
2638 HostEntriesBegin, HostEntriesEnd, nullptr);
2639 DeviceImagesEntires.push_back(Dev);
2640 }
2641
2642 // Create device images global array.
2643 llvm::ArrayType *DeviceImagesInitTy =
2644 llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size());
2645 llvm::Constant *DeviceImagesInit =
2646 llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires);
2647
2648 llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable(
2649 M, DeviceImagesInitTy, /*isConstant=*/true,
2650 llvm::GlobalValue::InternalLinkage, DeviceImagesInit,
2651 ".omp_offloading.device_images");
2652 DeviceImages->setUnnamedAddr(true);
2653
2654 // This is a Zero array to be used in the creation of the constant expressions
2655 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
2656 llvm::Constant::getNullValue(CGM.Int32Ty)};
2657
2658 // Create the target region descriptor.
2659 auto *BinaryDescriptorTy = cast<llvm::StructType>(
2660 CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
2661 llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get(
2662 BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
2663 llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages,
2664 Index),
2665 HostEntriesBegin, HostEntriesEnd, nullptr);
2666
2667 auto *Desc = new llvm::GlobalVariable(
2668 M, BinaryDescriptorTy, /*isConstant=*/true,
2669 llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit,
2670 ".omp_offloading.descriptor");
2671
2672 // Emit code to register or unregister the descriptor at execution
2673 // startup or closing, respectively.
2674
2675 // Create a variable to drive the registration and unregistration of the
2676 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
2677 auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var");
2678 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(),
2679 IdentInfo, C.CharTy);
2680
2681 auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002682 CGM, ".omp_offloading.descriptor_unreg",
2683 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002684 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
2685 Desc);
2686 });
2687 auto *RegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002688 CGM, ".omp_offloading.descriptor_reg",
2689 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002690 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib),
2691 Desc);
2692 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
2693 });
2694 return RegFn;
2695}
2696
Samuel Antao2de62b02016-02-13 23:35:10 +00002697void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID,
2698 llvm::Constant *Addr, uint64_t Size) {
2699 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00002700 auto *TgtOffloadEntryType = cast<llvm::StructType>(
2701 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()));
2702 llvm::LLVMContext &C = CGM.getModule().getContext();
2703 llvm::Module &M = CGM.getModule();
2704
2705 // Make sure the address has the right type.
Samuel Antao2de62b02016-02-13 23:35:10 +00002706 llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002707
2708 // Create constant string with the name.
2709 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
2710
2711 llvm::GlobalVariable *Str =
2712 new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true,
2713 llvm::GlobalValue::InternalLinkage, StrPtrInit,
2714 ".omp_offloading.entry_name");
2715 Str->setUnnamedAddr(true);
2716 llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy);
2717
2718 // Create the entry struct.
2719 llvm::Constant *EntryInit = llvm::ConstantStruct::get(
2720 TgtOffloadEntryType, AddrPtr, StrPtr,
2721 llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr);
2722 llvm::GlobalVariable *Entry = new llvm::GlobalVariable(
2723 M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage,
2724 EntryInit, ".omp_offloading.entry");
2725
2726 // The entry has to be created in the section the linker expects it to be.
2727 Entry->setSection(".omp_offloading.entries");
2728 // We can't have any padding between symbols, so we need to have 1-byte
2729 // alignment.
2730 Entry->setAlignment(1);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002731}
2732
2733void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
2734 // Emit the offloading entries and metadata so that the device codegen side
2735 // can
2736 // easily figure out what to emit. The produced metadata looks like this:
2737 //
2738 // !omp_offload.info = !{!1, ...}
2739 //
2740 // Right now we only generate metadata for function that contain target
2741 // regions.
2742
2743 // If we do not have entries, we dont need to do anything.
2744 if (OffloadEntriesInfoManager.empty())
2745 return;
2746
2747 llvm::Module &M = CGM.getModule();
2748 llvm::LLVMContext &C = M.getContext();
2749 SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
2750 OrderedEntries(OffloadEntriesInfoManager.size());
2751
2752 // Create the offloading info metadata node.
2753 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
2754
2755 // Auxiliar methods to create metadata values and strings.
2756 auto getMDInt = [&](unsigned v) {
2757 return llvm::ConstantAsMetadata::get(
2758 llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v));
2759 };
2760
2761 auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); };
2762
2763 // Create function that emits metadata for each target region entry;
2764 auto &&TargetRegionMetadataEmitter = [&](
2765 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002766 OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
2767 llvm::SmallVector<llvm::Metadata *, 32> Ops;
2768 // Generate metadata for target regions. Each entry of this metadata
2769 // contains:
2770 // - Entry 0 -> Kind of this type of metadata (0).
2771 // - Entry 1 -> Device ID of the file where the entry was identified.
2772 // - Entry 2 -> File ID of the file where the entry was identified.
2773 // - Entry 3 -> Mangled name of the function where the entry was identified.
2774 // - Entry 4 -> Line in the file where the entry was identified.
Samuel Antao2de62b02016-02-13 23:35:10 +00002775 // - Entry 5 -> Order the entry was created.
Samuel Antaoee8fb302016-01-06 13:42:12 +00002776 // The first element of the metadata node is the kind.
2777 Ops.push_back(getMDInt(E.getKind()));
2778 Ops.push_back(getMDInt(DeviceID));
2779 Ops.push_back(getMDInt(FileID));
2780 Ops.push_back(getMDString(ParentName));
2781 Ops.push_back(getMDInt(Line));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002782 Ops.push_back(getMDInt(E.getOrder()));
2783
2784 // Save this entry in the right position of the ordered entries array.
2785 OrderedEntries[E.getOrder()] = &E;
2786
2787 // Add metadata to the named metadata node.
2788 MD->addOperand(llvm::MDNode::get(C, Ops));
2789 };
2790
2791 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
2792 TargetRegionMetadataEmitter);
2793
2794 for (auto *E : OrderedEntries) {
2795 assert(E && "All ordered entries must exist!");
2796 if (auto *CE =
2797 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
2798 E)) {
2799 assert(CE->getID() && CE->getAddress() &&
2800 "Entry ID and Addr are invalid!");
Samuel Antao2de62b02016-02-13 23:35:10 +00002801 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002802 } else
2803 llvm_unreachable("Unsupported entry kind.");
2804 }
2805}
2806
2807/// \brief Loads all the offload entries information from the host IR
2808/// metadata.
2809void CGOpenMPRuntime::loadOffloadInfoMetadata() {
2810 // If we are in target mode, load the metadata from the host IR. This code has
2811 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
2812
2813 if (!CGM.getLangOpts().OpenMPIsDevice)
2814 return;
2815
2816 if (CGM.getLangOpts().OMPHostIRFile.empty())
2817 return;
2818
2819 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
2820 if (Buf.getError())
2821 return;
2822
2823 llvm::LLVMContext C;
2824 auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C);
2825
2826 if (ME.getError())
2827 return;
2828
2829 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
2830 if (!MD)
2831 return;
2832
2833 for (auto I : MD->operands()) {
2834 llvm::MDNode *MN = cast<llvm::MDNode>(I);
2835
2836 auto getMDInt = [&](unsigned Idx) {
2837 llvm::ConstantAsMetadata *V =
2838 cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
2839 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
2840 };
2841
2842 auto getMDString = [&](unsigned Idx) {
2843 llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx));
2844 return V->getString();
2845 };
2846
2847 switch (getMDInt(0)) {
2848 default:
2849 llvm_unreachable("Unexpected metadata!");
2850 break;
2851 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
2852 OFFLOAD_ENTRY_INFO_TARGET_REGION:
2853 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
2854 /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2),
2855 /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4),
Samuel Antao2de62b02016-02-13 23:35:10 +00002856 /*Order=*/getMDInt(5));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002857 break;
2858 }
2859 }
2860}
2861
Alexey Bataev62b63b12015-03-10 07:28:44 +00002862void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
2863 if (!KmpRoutineEntryPtrTy) {
2864 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
2865 auto &C = CGM.getContext();
2866 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
2867 FunctionProtoType::ExtProtoInfo EPI;
2868 KmpRoutineEntryPtrQTy = C.getPointerType(
2869 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2870 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
2871 }
2872}
2873
Alexey Bataevc71a4092015-09-11 10:29:41 +00002874static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
2875 QualType FieldTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002876 auto *Field = FieldDecl::Create(
2877 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
2878 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
2879 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
2880 Field->setAccess(AS_public);
2881 DC->addDecl(Field);
Alexey Bataevc71a4092015-09-11 10:29:41 +00002882 return Field;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002883}
2884
Samuel Antaoee8fb302016-01-06 13:42:12 +00002885QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
2886
2887 // Make sure the type of the entry is already created. This is the type we
2888 // have to create:
2889 // struct __tgt_offload_entry{
2890 // void *addr; // Pointer to the offload entry info.
2891 // // (function or global)
2892 // char *name; // Name of the function or global.
2893 // size_t size; // Size of the entry info (0 if it a function).
2894 // };
2895 if (TgtOffloadEntryQTy.isNull()) {
2896 ASTContext &C = CGM.getContext();
2897 auto *RD = C.buildImplicitRecord("__tgt_offload_entry");
2898 RD->startDefinition();
2899 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2900 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
2901 addFieldToRecordDecl(C, RD, C.getSizeType());
2902 RD->completeDefinition();
2903 TgtOffloadEntryQTy = C.getRecordType(RD);
2904 }
2905 return TgtOffloadEntryQTy;
2906}
2907
2908QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
2909 // These are the types we need to build:
2910 // struct __tgt_device_image{
2911 // void *ImageStart; // Pointer to the target code start.
2912 // void *ImageEnd; // Pointer to the target code end.
2913 // // We also add the host entries to the device image, as it may be useful
2914 // // for the target runtime to have access to that information.
2915 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
2916 // // the entries.
2917 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2918 // // entries (non inclusive).
2919 // };
2920 if (TgtDeviceImageQTy.isNull()) {
2921 ASTContext &C = CGM.getContext();
2922 auto *RD = C.buildImplicitRecord("__tgt_device_image");
2923 RD->startDefinition();
2924 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2925 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2926 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2927 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2928 RD->completeDefinition();
2929 TgtDeviceImageQTy = C.getRecordType(RD);
2930 }
2931 return TgtDeviceImageQTy;
2932}
2933
2934QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
2935 // struct __tgt_bin_desc{
2936 // int32_t NumDevices; // Number of devices supported.
2937 // __tgt_device_image *DeviceImages; // Arrays of device images
2938 // // (one per device).
2939 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
2940 // // entries.
2941 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2942 // // entries (non inclusive).
2943 // };
2944 if (TgtBinaryDescriptorQTy.isNull()) {
2945 ASTContext &C = CGM.getContext();
2946 auto *RD = C.buildImplicitRecord("__tgt_bin_desc");
2947 RD->startDefinition();
2948 addFieldToRecordDecl(
2949 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
2950 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
2951 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2952 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2953 RD->completeDefinition();
2954 TgtBinaryDescriptorQTy = C.getRecordType(RD);
2955 }
2956 return TgtBinaryDescriptorQTy;
2957}
2958
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002959namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00002960struct PrivateHelpersTy {
2961 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
2962 const VarDecl *PrivateElemInit)
2963 : Original(Original), PrivateCopy(PrivateCopy),
2964 PrivateElemInit(PrivateElemInit) {}
2965 const VarDecl *Original;
2966 const VarDecl *PrivateCopy;
2967 const VarDecl *PrivateElemInit;
2968};
2969typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00002970} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002971
Alexey Bataev9e034042015-05-05 04:05:12 +00002972static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00002973createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002974 if (!Privates.empty()) {
2975 auto &C = CGM.getContext();
2976 // Build struct .kmp_privates_t. {
2977 // /* private vars */
2978 // };
2979 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
2980 RD->startDefinition();
2981 for (auto &&Pair : Privates) {
Alexey Bataevc71a4092015-09-11 10:29:41 +00002982 auto *VD = Pair.second.Original;
2983 auto Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002984 Type = Type.getNonReferenceType();
Alexey Bataevc71a4092015-09-11 10:29:41 +00002985 auto *FD = addFieldToRecordDecl(C, RD, Type);
2986 if (VD->hasAttrs()) {
2987 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
2988 E(VD->getAttrs().end());
2989 I != E; ++I)
2990 FD->addAttr(*I);
2991 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002992 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002993 RD->completeDefinition();
2994 return RD;
2995 }
2996 return nullptr;
2997}
2998
Alexey Bataev9e034042015-05-05 04:05:12 +00002999static RecordDecl *
3000createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003001 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003002 auto &C = CGM.getContext();
3003 // Build struct kmp_task_t {
3004 // void * shareds;
3005 // kmp_routine_entry_t routine;
3006 // kmp_int32 part_id;
3007 // kmp_routine_entry_t destructors;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003008 // };
3009 auto *RD = C.buildImplicitRecord("kmp_task_t");
3010 RD->startDefinition();
3011 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3012 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
3013 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3014 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003015 RD->completeDefinition();
3016 return RD;
3017}
3018
3019static RecordDecl *
3020createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003021 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003022 auto &C = CGM.getContext();
3023 // Build struct kmp_task_t_with_privates {
3024 // kmp_task_t task_data;
3025 // .kmp_privates_t. privates;
3026 // };
3027 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
3028 RD->startDefinition();
3029 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003030 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
3031 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
3032 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003033 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003034 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003035}
3036
3037/// \brief Emit a proxy function which accepts kmp_task_t as the second
3038/// argument.
3039/// \code
3040/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev823acfa2016-04-19 16:27:55 +00003041/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003042/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003043/// return 0;
3044/// }
3045/// \endcode
3046static llvm::Value *
3047emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003048 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
3049 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003050 QualType SharedsPtrTy, llvm::Value *TaskFunction,
3051 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003052 auto &C = CGM.getContext();
3053 FunctionArgList Args;
3054 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3055 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003056 /*Id=*/nullptr,
3057 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003058 Args.push_back(&GtidArg);
3059 Args.push_back(&TaskTypeArg);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003060 auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003061 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003062 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
3063 auto *TaskEntry =
3064 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
3065 ".omp_task_entry.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003066 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003067 CodeGenFunction CGF(CGM);
3068 CGF.disableDebugInfo();
3069 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
3070
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003071 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev823acfa2016-04-19 16:27:55 +00003072 // tt, tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003073 auto *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00003074 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00003075 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3076 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3077 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003078 auto *KmpTaskTWithPrivatesQTyRD =
3079 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003080 LValue Base =
3081 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003082 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
3083 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3084 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
Alexey Bataev823acfa2016-04-19 16:27:55 +00003085 auto *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003086
3087 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3088 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003089 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003090 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003091 CGF.ConvertTypeForMem(SharedsPtrTy));
3092
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003093 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3094 llvm::Value *PrivatesParam;
3095 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3096 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
3097 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003098 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003099 } else {
3100 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3101 }
3102
3103 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam,
Alexey Bataev823acfa2016-04-19 16:27:55 +00003104 TaskPrivatesMap,
3105 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3106 TDBase.getAddress(), CGF.VoidPtrTy)
3107 .getPointer(),
3108 SharedsParam};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003109 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
3110 CGF.EmitStoreThroughLValue(
3111 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
John McCall7f416cc2015-09-08 08:05:57 +00003112 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00003113 CGF.FinishFunction();
3114 return TaskEntry;
3115}
3116
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003117static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
3118 SourceLocation Loc,
3119 QualType KmpInt32Ty,
3120 QualType KmpTaskTWithPrivatesPtrQTy,
3121 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003122 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003123 FunctionArgList Args;
3124 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3125 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003126 /*Id=*/nullptr,
3127 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003128 Args.push_back(&GtidArg);
3129 Args.push_back(&TaskTypeArg);
3130 FunctionType::ExtInfo Info;
3131 auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003132 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003133 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
3134 auto *DestructorFn =
3135 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3136 ".omp_task_destructor.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003137 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
3138 DestructorFnInfo);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003139 CodeGenFunction CGF(CGM);
3140 CGF.disableDebugInfo();
3141 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
3142 Args);
3143
Alexey Bataev31300ed2016-02-04 11:27:03 +00003144 LValue Base = CGF.EmitLoadOfPointerLValue(
3145 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3146 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003147 auto *KmpTaskTWithPrivatesQTyRD =
3148 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3149 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003150 Base = CGF.EmitLValueForField(Base, *FI);
3151 for (auto *Field :
3152 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3153 if (auto DtorKind = Field->getType().isDestructedType()) {
3154 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
3155 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3156 }
3157 }
3158 CGF.FinishFunction();
3159 return DestructorFn;
3160}
3161
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003162/// \brief Emit a privates mapping function for correct handling of private and
3163/// firstprivate variables.
3164/// \code
3165/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
3166/// **noalias priv1,..., <tyn> **noalias privn) {
3167/// *priv1 = &.privates.priv1;
3168/// ...;
3169/// *privn = &.privates.privn;
3170/// }
3171/// \endcode
3172static llvm::Value *
3173emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00003174 ArrayRef<const Expr *> PrivateVars,
3175 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003176 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003177 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003178 auto &C = CGM.getContext();
3179 FunctionArgList Args;
3180 ImplicitParamDecl TaskPrivatesArg(
3181 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3182 C.getPointerType(PrivatesQTy).withConst().withRestrict());
3183 Args.push_back(&TaskPrivatesArg);
3184 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
3185 unsigned Counter = 1;
3186 for (auto *E: PrivateVars) {
3187 Args.push_back(ImplicitParamDecl::Create(
3188 C, /*DC=*/nullptr, Loc,
3189 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3190 .withConst()
3191 .withRestrict()));
3192 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3193 PrivateVarsPos[VD] = Counter;
3194 ++Counter;
3195 }
3196 for (auto *E : FirstprivateVars) {
3197 Args.push_back(ImplicitParamDecl::Create(
3198 C, /*DC=*/nullptr, Loc,
3199 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3200 .withConst()
3201 .withRestrict()));
3202 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3203 PrivateVarsPos[VD] = Counter;
3204 ++Counter;
3205 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003206 auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003207 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003208 auto *TaskPrivatesMapTy =
3209 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
3210 auto *TaskPrivatesMap = llvm::Function::Create(
3211 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
3212 ".omp_task_privates_map.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003213 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
3214 TaskPrivatesMapFnInfo);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00003215 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003216 CodeGenFunction CGF(CGM);
3217 CGF.disableDebugInfo();
3218 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
3219 TaskPrivatesMapFnInfo, Args);
3220
3221 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00003222 LValue Base = CGF.EmitLoadOfPointerLValue(
3223 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
3224 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003225 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
3226 Counter = 0;
3227 for (auto *Field : PrivatesQTyRD->fields()) {
3228 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
3229 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
John McCall7f416cc2015-09-08 08:05:57 +00003230 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
Alexey Bataev31300ed2016-02-04 11:27:03 +00003231 auto RefLoadLVal = CGF.EmitLoadOfPointerLValue(
3232 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003233 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003234 ++Counter;
3235 }
3236 CGF.FinishFunction();
3237 return TaskPrivatesMap;
3238}
3239
Alexey Bataev9e034042015-05-05 04:05:12 +00003240static int array_pod_sort_comparator(const PrivateDataTy *P1,
3241 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003242 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
3243}
3244
3245void CGOpenMPRuntime::emitTaskCall(
3246 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
3247 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
Alexey Bataev823acfa2016-04-19 16:27:55 +00003248 unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy,
3249 Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003250 ArrayRef<const Expr *> PrivateCopies,
3251 ArrayRef<const Expr *> FirstprivateVars,
3252 ArrayRef<const Expr *> FirstprivateCopies,
3253 ArrayRef<const Expr *> FirstprivateInits,
3254 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003255 if (!CGF.HaveInsertPoint())
3256 return;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003257 auto &C = CGM.getContext();
Alexey Bataev9e034042015-05-05 04:05:12 +00003258 llvm::SmallVector<PrivateDataTy, 8> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003259 // Aggregate privates and sort them by the alignment.
Alexey Bataev9e034042015-05-05 04:05:12 +00003260 auto I = PrivateCopies.begin();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003261 for (auto *E : PrivateVars) {
3262 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3263 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003264 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003265 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3266 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003267 ++I;
3268 }
Alexey Bataev9e034042015-05-05 04:05:12 +00003269 I = FirstprivateCopies.begin();
3270 auto IElemInitRef = FirstprivateInits.begin();
3271 for (auto *E : FirstprivateVars) {
3272 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3273 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003274 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003275 PrivateHelpersTy(
3276 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3277 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
Richard Trieucc3949d2016-02-18 22:34:54 +00003278 ++I;
3279 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00003280 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003281 llvm::array_pod_sort(Privates.begin(), Privates.end(),
3282 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003283 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
3284 // Build type kmp_routine_entry_t (if not built yet).
3285 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003286 // Build type kmp_task_t (if not built yet).
3287 if (KmpTaskTQTy.isNull()) {
3288 KmpTaskTQTy = C.getRecordType(
3289 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
3290 }
3291 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003292 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003293 auto *KmpTaskTWithPrivatesQTyRD =
3294 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
3295 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
3296 QualType KmpTaskTWithPrivatesPtrQTy =
3297 C.getPointerType(KmpTaskTWithPrivatesQTy);
3298 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
3299 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003300 auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003301 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
3302
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003303 // Emit initial values for private copies (if any).
3304 llvm::Value *TaskPrivatesMap = nullptr;
3305 auto *TaskPrivatesMapTy =
3306 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
3307 3)
3308 ->getType();
3309 if (!Privates.empty()) {
3310 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3311 TaskPrivatesMap = emitTaskPrivateMappingFunction(
3312 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
3313 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3314 TaskPrivatesMap, TaskPrivatesMapTy);
3315 } else {
3316 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3317 cast<llvm::PointerType>(TaskPrivatesMapTy));
3318 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003319 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
3320 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003321 auto *TaskEntry = emitProxyTaskFunction(
3322 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003323 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003324
3325 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
3326 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
3327 // kmp_routine_entry_t *task_entry);
3328 // Task flags. Format is taken from
3329 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
3330 // description of kmp_tasking_flags struct.
3331 const unsigned TiedFlag = 0x1;
3332 const unsigned FinalFlag = 0x2;
3333 unsigned Flags = Tied ? TiedFlag : 0;
3334 auto *TaskFlags =
3335 Final.getPointer()
3336 ? CGF.Builder.CreateSelect(Final.getPointer(),
3337 CGF.Builder.getInt32(FinalFlag),
3338 CGF.Builder.getInt32(/*C=*/0))
3339 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
3340 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataev40e36f12015-11-24 13:01:44 +00003341 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003342 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
3343 getThreadID(CGF, Loc), TaskFlags,
3344 KmpTaskTWithPrivatesTySize, SharedsSize,
3345 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3346 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003347 auto *NewTask = CGF.EmitRuntimeCall(
3348 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003349 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3350 NewTask, KmpTaskTWithPrivatesPtrTy);
3351 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
3352 KmpTaskTWithPrivatesQTy);
3353 LValue TDBase =
3354 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003355 // Fill the data in the resulting kmp_task_t record.
3356 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00003357 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003358 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003359 KmpTaskSharedsPtr =
3360 Address(CGF.EmitLoadOfScalar(
3361 CGF.EmitLValueForField(
3362 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
3363 KmpTaskTShareds)),
3364 Loc),
3365 CGF.getNaturalTypeAlignment(SharedsTy));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003366 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003367 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003368 // Emit initial values for private copies (if any).
3369 bool NeedsCleanup = false;
3370 if (!Privates.empty()) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003371 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3372 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003373 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003374 LValue SharedsBase;
3375 if (!FirstprivateVars.empty()) {
John McCall7f416cc2015-09-08 08:05:57 +00003376 SharedsBase = CGF.MakeAddrLValue(
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003377 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3378 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
3379 SharedsTy);
3380 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003381 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
3382 cast<CapturedStmt>(*D.getAssociatedStmt()));
3383 for (auto &&Pair : Privates) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003384 auto *VD = Pair.second.PrivateCopy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003385 auto *Init = VD->getAnyInitializer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003386 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003387 if (Init) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003388 if (auto *Elem = Pair.second.PrivateElemInit) {
3389 auto *OriginalVD = Pair.second.Original;
3390 auto *SharedField = CapturesInfo.lookup(OriginalVD);
3391 auto SharedRefLValue =
3392 CGF.EmitLValueForField(SharedsBase, SharedField);
Alexey Bataevc71a4092015-09-11 10:29:41 +00003393 SharedRefLValue = CGF.MakeAddrLValue(
3394 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
3395 SharedRefLValue.getType(), AlignmentSource::Decl);
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003396 QualType Type = OriginalVD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003397 if (Type->isArrayType()) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003398 // Initialize firstprivate array.
3399 if (!isa<CXXConstructExpr>(Init) ||
3400 CGF.isTrivialInitializer(Init)) {
3401 // Perform simple memcpy.
3402 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003403 SharedRefLValue.getAddress(), Type);
Alexey Bataev9e034042015-05-05 04:05:12 +00003404 } else {
3405 // Initialize firstprivate array using element-by-element
3406 // intialization.
3407 CGF.EmitOMPAggregateAssign(
3408 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003409 Type, [&CGF, Elem, Init, &CapturesInfo](
John McCall7f416cc2015-09-08 08:05:57 +00003410 Address DestElement, Address SrcElement) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003411 // Clean up any temporaries needed by the initialization.
3412 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003413 InitScope.addPrivate(Elem, [SrcElement]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003414 return SrcElement;
3415 });
3416 (void)InitScope.Privatize();
3417 // Emit initialization for single element.
Alexey Bataevd157d472015-06-24 03:35:38 +00003418 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3419 CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003420 CGF.EmitAnyExprToMem(Init, DestElement,
3421 Init->getType().getQualifiers(),
3422 /*IsInitializer=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003423 });
3424 }
3425 } else {
3426 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003427 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003428 return SharedRefLValue.getAddress();
3429 });
3430 (void)InitScope.Privatize();
Alexey Bataevd157d472015-06-24 03:35:38 +00003431 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003432 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
3433 /*capturedByInit=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003434 }
3435 } else {
3436 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
3437 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003438 }
3439 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003440 ++FI;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003441 }
3442 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003443 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003444 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003445 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
3446 KmpTaskTWithPrivatesPtrQTy,
3447 KmpTaskTWithPrivatesQTy)
3448 : llvm::ConstantPointerNull::get(
3449 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
3450 LValue Destructor = CGF.EmitLValueForField(
3451 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
3452 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3453 DestructorFn, KmpRoutineEntryPtrTy),
3454 Destructor);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003455
3456 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00003457 Address DependenciesArray = Address::invalid();
3458 unsigned NumDependencies = Dependences.size();
3459 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003460 // Dependence kind for RTL.
Alexey Bataev92e82f92015-11-23 13:33:42 +00003461 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003462 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
3463 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003464 QualType FlagsTy =
3465 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003466 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
3467 if (KmpDependInfoTy.isNull()) {
3468 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
3469 KmpDependInfoRD->startDefinition();
3470 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
3471 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
3472 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
3473 KmpDependInfoRD->completeDefinition();
3474 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
3475 } else {
3476 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
3477 }
John McCall7f416cc2015-09-08 08:05:57 +00003478 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003479 // Define type kmp_depend_info[<Dependences.size()>];
3480 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00003481 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003482 ArrayType::Normal, /*IndexTypeQuals=*/0);
3483 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev823acfa2016-04-19 16:27:55 +00003484 DependenciesArray =
3485 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
John McCall7f416cc2015-09-08 08:05:57 +00003486 for (unsigned i = 0; i < NumDependencies; ++i) {
3487 const Expr *E = Dependences[i].second;
3488 auto Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003489 llvm::Value *Size;
3490 QualType Ty = E->getType();
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003491 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
3492 LValue UpAddrLVal =
3493 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
3494 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00003495 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003496 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00003497 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003498 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
3499 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003500 } else
Alexey Bataev1189bd02016-01-26 12:20:39 +00003501 Size = CGF.getTypeSize(Ty);
John McCall7f416cc2015-09-08 08:05:57 +00003502 auto Base = CGF.MakeAddrLValue(
3503 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003504 KmpDependInfoTy);
3505 // deps[i].base_addr = &<Dependences[i].second>;
3506 auto BaseAddrLVal = CGF.EmitLValueForField(
3507 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00003508 CGF.EmitStoreOfScalar(
3509 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
3510 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003511 // deps[i].len = sizeof(<Dependences[i].second>);
3512 auto LenLVal = CGF.EmitLValueForField(
3513 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
3514 CGF.EmitStoreOfScalar(Size, LenLVal);
3515 // deps[i].flags = <Dependences[i].first>;
3516 RTLDependenceKindTy DepKind;
3517 switch (Dependences[i].first) {
3518 case OMPC_DEPEND_in:
3519 DepKind = DepIn;
3520 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00003521 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003522 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003523 case OMPC_DEPEND_inout:
3524 DepKind = DepInOut;
3525 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00003526 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00003527 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003528 case OMPC_DEPEND_unknown:
3529 llvm_unreachable("Unknown task dependence type");
3530 }
3531 auto FlagsLVal = CGF.EmitLValueForField(
3532 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
3533 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
3534 FlagsLVal);
3535 }
John McCall7f416cc2015-09-08 08:05:57 +00003536 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3537 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003538 CGF.VoidPtrTy);
3539 }
3540
Alexey Bataev62b63b12015-03-10 07:28:44 +00003541 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
3542 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003543 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
3544 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
3545 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
3546 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00003547 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003548 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00003549 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
3550 llvm::Value *DepTaskArgs[7];
3551 if (NumDependencies) {
3552 DepTaskArgs[0] = UpLoc;
3553 DepTaskArgs[1] = ThreadID;
3554 DepTaskArgs[2] = NewTask;
3555 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
3556 DepTaskArgs[4] = DependenciesArray.getPointer();
3557 DepTaskArgs[5] = CGF.Builder.getInt32(0);
3558 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3559 }
Alexey Bataev823acfa2016-04-19 16:27:55 +00003560 auto &&ThenCodeGen = [this, Tied, Loc, NumberOfParts, TDBase, KmpTaskTQTyRD,
3561 NumDependencies, &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003562 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev823acfa2016-04-19 16:27:55 +00003563 if (!Tied) {
3564 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3565 auto PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
3566 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
3567 }
John McCall7f416cc2015-09-08 08:05:57 +00003568 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003569 CGF.EmitRuntimeCall(
Alexey Bataev823acfa2016-04-19 16:27:55 +00003570 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00003571 } else {
Alexey Bataev823acfa2016-04-19 16:27:55 +00003572 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00003573 TaskArgs);
3574 }
Alexey Bataev823acfa2016-04-19 16:27:55 +00003575 // Check if parent region is untied and build return for untied task;
3576 if (auto *Region =
3577 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3578 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003579 };
John McCall7f416cc2015-09-08 08:05:57 +00003580
3581 llvm::Value *DepWaitTaskArgs[6];
3582 if (NumDependencies) {
3583 DepWaitTaskArgs[0] = UpLoc;
3584 DepWaitTaskArgs[1] = ThreadID;
3585 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
3586 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
3587 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
3588 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3589 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003590 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
3591 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF,
3592 PrePostActionTy &) {
3593 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003594 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
3595 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
3596 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
3597 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
3598 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00003599 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003600 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003601 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003602 // Call proxy_task_entry(gtid, new_task);
3603 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy](
3604 CodeGenFunction &CGF, PrePostActionTy &Action) {
3605 Action.Enter(CGF);
3606 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
3607 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
3608 };
3609
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003610 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
3611 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003612 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
3613 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003614 RegionCodeGenTy RCG(CodeGen);
3615 CommonActionTy Action(
3616 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
3617 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
3618 RCG.setAction(Action);
3619 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003620 };
John McCall7f416cc2015-09-08 08:05:57 +00003621
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003622 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00003623 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003624 else {
3625 RegionCodeGenTy ThenRCG(ThenCodeGen);
3626 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003627 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003628}
3629
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003630/// \brief Emit reduction operation for each element of array (required for
3631/// array sections) LHS op = RHS.
3632/// \param Type Type of array.
3633/// \param LHSVar Variable on the left side of the reduction operation
3634/// (references element of array in original variable).
3635/// \param RHSVar Variable on the right side of the reduction operation
3636/// (references element of array in original variable).
3637/// \param RedOpGen Generator of reduction operation with use of LHSVar and
3638/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00003639static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003640 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
3641 const VarDecl *RHSVar,
3642 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
3643 const Expr *, const Expr *)> &RedOpGen,
3644 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
3645 const Expr *UpExpr = nullptr) {
3646 // Perform element-by-element initialization.
3647 QualType ElementTy;
3648 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
3649 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
3650
3651 // Drill down to the base element type on both arrays.
3652 auto ArrayTy = Type->getAsArrayTypeUnsafe();
3653 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
3654
3655 auto RHSBegin = RHSAddr.getPointer();
3656 auto LHSBegin = LHSAddr.getPointer();
3657 // Cast from pointer to array type to pointer to single element.
3658 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
3659 // The basic structure here is a while-do loop.
3660 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
3661 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
3662 auto IsEmpty =
3663 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
3664 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
3665
3666 // Enter the loop body, making that address the current address.
3667 auto EntryBB = CGF.Builder.GetInsertBlock();
3668 CGF.EmitBlock(BodyBB);
3669
3670 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
3671
3672 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
3673 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
3674 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
3675 Address RHSElementCurrent =
3676 Address(RHSElementPHI,
3677 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3678
3679 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
3680 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
3681 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
3682 Address LHSElementCurrent =
3683 Address(LHSElementPHI,
3684 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3685
3686 // Emit copy.
3687 CodeGenFunction::OMPPrivateScope Scope(CGF);
3688 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
3689 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
3690 Scope.Privatize();
3691 RedOpGen(CGF, XExpr, EExpr, UpExpr);
3692 Scope.ForceCleanup();
3693
3694 // Shift the address forward by one element.
3695 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
3696 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
3697 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
3698 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
3699 // Check whether we've reached the end.
3700 auto Done =
3701 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
3702 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
3703 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
3704 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
3705
3706 // Done.
3707 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
3708}
3709
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003710/// Emit reduction combiner. If the combiner is a simple expression emit it as
3711/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
3712/// UDR combiner function.
3713static void emitReductionCombiner(CodeGenFunction &CGF,
3714 const Expr *ReductionOp) {
3715 if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
3716 if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
3717 if (auto *DRE =
3718 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
3719 if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
3720 std::pair<llvm::Function *, llvm::Function *> Reduction =
3721 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
3722 RValue Func = RValue::get(Reduction.first);
3723 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
3724 CGF.EmitIgnoredExpr(ReductionOp);
3725 return;
3726 }
3727 CGF.EmitIgnoredExpr(ReductionOp);
3728}
3729
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003730static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
3731 llvm::Type *ArgsType,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003732 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003733 ArrayRef<const Expr *> LHSExprs,
3734 ArrayRef<const Expr *> RHSExprs,
3735 ArrayRef<const Expr *> ReductionOps) {
3736 auto &C = CGM.getContext();
3737
3738 // void reduction_func(void *LHSArg, void *RHSArg);
3739 FunctionArgList Args;
3740 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3741 C.VoidPtrTy);
3742 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3743 C.VoidPtrTy);
3744 Args.push_back(&LHSArg);
3745 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00003746 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003747 auto *Fn = llvm::Function::Create(
3748 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
3749 ".omp.reduction.reduction_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003750 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003751 CodeGenFunction CGF(CGM);
3752 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
3753
3754 // Dst = (void*[n])(LHSArg);
3755 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003756 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3757 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3758 ArgsType), CGF.getPointerAlign());
3759 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3760 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3761 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003762
3763 // ...
3764 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
3765 // ...
3766 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003767 auto IPriv = Privates.begin();
3768 unsigned Idx = 0;
3769 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003770 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
3771 Scope.addPrivate(RHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003772 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003773 });
3774 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
3775 Scope.addPrivate(LHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003776 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003777 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003778 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003779 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003780 // Get array size and emit VLA type.
3781 ++Idx;
3782 Address Elem =
3783 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
3784 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003785 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy);
3786 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003787 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00003788 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003789 CGF.EmitVariablyModifiedType(PrivTy);
3790 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003791 }
3792 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003793 IPriv = Privates.begin();
3794 auto ILHS = LHSExprs.begin();
3795 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003796 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003797 if ((*IPriv)->getType()->isArrayType()) {
3798 // Emit reduction for array section.
3799 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3800 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003801 EmitOMPAggregateReduction(
3802 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3803 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
3804 emitReductionCombiner(CGF, E);
3805 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003806 } else
3807 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003808 emitReductionCombiner(CGF, E);
Richard Trieucc3949d2016-02-18 22:34:54 +00003809 ++IPriv;
3810 ++ILHS;
3811 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003812 }
3813 Scope.ForceCleanup();
3814 CGF.FinishFunction();
3815 return Fn;
3816}
3817
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003818static void emitSingleReductionCombiner(CodeGenFunction &CGF,
3819 const Expr *ReductionOp,
3820 const Expr *PrivateRef,
3821 const DeclRefExpr *LHS,
3822 const DeclRefExpr *RHS) {
3823 if (PrivateRef->getType()->isArrayType()) {
3824 // Emit reduction for array section.
3825 auto *LHSVar = cast<VarDecl>(LHS->getDecl());
3826 auto *RHSVar = cast<VarDecl>(RHS->getDecl());
3827 EmitOMPAggregateReduction(
3828 CGF, PrivateRef->getType(), LHSVar, RHSVar,
3829 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
3830 emitReductionCombiner(CGF, ReductionOp);
3831 });
3832 } else
3833 // Emit reduction for array subscript or single variable.
3834 emitReductionCombiner(CGF, ReductionOp);
3835}
3836
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003837void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003838 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003839 ArrayRef<const Expr *> LHSExprs,
3840 ArrayRef<const Expr *> RHSExprs,
3841 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003842 bool WithNowait, bool SimpleReduction) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003843 if (!CGF.HaveInsertPoint())
3844 return;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003845 // Next code should be emitted for reduction:
3846 //
3847 // static kmp_critical_name lock = { 0 };
3848 //
3849 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
3850 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
3851 // ...
3852 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
3853 // *(Type<n>-1*)rhs[<n>-1]);
3854 // }
3855 //
3856 // ...
3857 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
3858 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
3859 // RedList, reduce_func, &<lock>)) {
3860 // case 1:
3861 // ...
3862 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3863 // ...
3864 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3865 // break;
3866 // case 2:
3867 // ...
3868 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
3869 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00003870 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003871 // break;
3872 // default:;
3873 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003874 //
3875 // if SimpleReduction is true, only the next code is generated:
3876 // ...
3877 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3878 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003879
3880 auto &C = CGM.getContext();
3881
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003882 if (SimpleReduction) {
3883 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003884 auto IPriv = Privates.begin();
3885 auto ILHS = LHSExprs.begin();
3886 auto IRHS = RHSExprs.begin();
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003887 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003888 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
3889 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00003890 ++IPriv;
3891 ++ILHS;
3892 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003893 }
3894 return;
3895 }
3896
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003897 // 1. Build a list of reduction variables.
3898 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003899 auto Size = RHSExprs.size();
3900 for (auto *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00003901 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003902 // Reserve place for array size.
3903 ++Size;
3904 }
3905 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003906 QualType ReductionArrayTy =
3907 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
3908 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00003909 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003910 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003911 auto IPriv = Privates.begin();
3912 unsigned Idx = 0;
3913 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003914 Address Elem =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003915 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00003916 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003917 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003918 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
3919 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003920 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003921 // Store array size.
3922 ++Idx;
3923 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
3924 CGF.getPointerSize());
Alexey Bataev1189bd02016-01-26 12:20:39 +00003925 llvm::Value *Size = CGF.Builder.CreateIntCast(
3926 CGF.getVLASize(
3927 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
3928 .first,
3929 CGF.SizeTy, /*isSigned=*/false);
3930 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
3931 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003932 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003933 }
3934
3935 // 2. Emit reduce_func().
3936 auto *ReductionFn = emitReductionFunction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003937 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
3938 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003939
3940 // 3. Create static kmp_critical_name lock = { 0 };
3941 auto *Lock = getCriticalRegionLock(".reduction");
3942
3943 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
3944 // RedList, reduce_func, &<lock>);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003945 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003946 auto *ThreadId = getThreadID(CGF, Loc);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003947 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003948 auto *RL =
3949 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
3950 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003951 llvm::Value *Args[] = {
3952 IdentTLoc, // ident_t *<loc>
3953 ThreadId, // i32 <gtid>
3954 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
3955 ReductionArrayTySize, // size_type sizeof(RedList)
3956 RL, // void *RedList
3957 ReductionFn, // void (*) (void *, void *) <reduce_func>
3958 Lock // kmp_critical_name *&<lock>
3959 };
3960 auto Res = CGF.EmitRuntimeCall(
3961 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
3962 : OMPRTL__kmpc_reduce),
3963 Args);
3964
3965 // 5. Build switch(res)
3966 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
3967 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
3968
3969 // 6. Build case 1:
3970 // ...
3971 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3972 // ...
3973 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3974 // break;
3975 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
3976 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
3977 CGF.EmitBlock(Case1BB);
3978
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003979 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3980 llvm::Value *EndArgs[] = {
3981 IdentTLoc, // ident_t *<loc>
3982 ThreadId, // i32 <gtid>
3983 Lock // kmp_critical_name *&<lock>
3984 };
3985 auto &&CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps](
3986 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003987 auto IPriv = Privates.begin();
3988 auto ILHS = LHSExprs.begin();
3989 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003990 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003991 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
3992 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00003993 ++IPriv;
3994 ++ILHS;
3995 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003996 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003997 };
3998 RegionCodeGenTy RCG(CodeGen);
3999 CommonActionTy Action(
4000 nullptr, llvm::None,
4001 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
4002 : OMPRTL__kmpc_end_reduce),
4003 EndArgs);
4004 RCG.setAction(Action);
4005 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004006
4007 CGF.EmitBranch(DefaultBB);
4008
4009 // 7. Build case 2:
4010 // ...
4011 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
4012 // ...
4013 // break;
4014 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
4015 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
4016 CGF.EmitBlock(Case2BB);
4017
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004018 auto &&AtomicCodeGen = [Loc, &Privates, &LHSExprs, &RHSExprs, &ReductionOps](
4019 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004020 auto ILHS = LHSExprs.begin();
4021 auto IRHS = RHSExprs.begin();
4022 auto IPriv = Privates.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004023 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004024 const Expr *XExpr = nullptr;
4025 const Expr *EExpr = nullptr;
4026 const Expr *UpExpr = nullptr;
4027 BinaryOperatorKind BO = BO_Comma;
4028 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
4029 if (BO->getOpcode() == BO_Assign) {
4030 XExpr = BO->getLHS();
4031 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004032 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004033 }
4034 // Try to emit update expression as a simple atomic.
4035 auto *RHSExpr = UpExpr;
4036 if (RHSExpr) {
4037 // Analyze RHS part of the whole expression.
4038 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
4039 RHSExpr->IgnoreParenImpCasts())) {
4040 // If this is a conditional operator, analyze its condition for
4041 // min/max reduction operator.
4042 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00004043 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004044 if (auto *BORHS =
4045 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
4046 EExpr = BORHS->getRHS();
4047 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004048 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004049 }
4050 if (XExpr) {
4051 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4052 auto &&AtomicRedGen = [BO, VD, IPriv,
4053 Loc](CodeGenFunction &CGF, const Expr *XExpr,
4054 const Expr *EExpr, const Expr *UpExpr) {
4055 LValue X = CGF.EmitLValue(XExpr);
4056 RValue E;
4057 if (EExpr)
4058 E = CGF.EmitAnyExpr(EExpr);
4059 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00004060 X, E, BO, /*IsXLHSInRHSPart=*/true,
4061 llvm::AtomicOrdering::Monotonic, Loc,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004062 [&CGF, UpExpr, VD, IPriv, Loc](RValue XRValue) {
4063 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4064 PrivateScope.addPrivate(
4065 VD, [&CGF, VD, XRValue, Loc]() -> Address {
4066 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
4067 CGF.emitOMPSimpleStore(
4068 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
4069 VD->getType().getNonReferenceType(), Loc);
4070 return LHSTemp;
4071 });
4072 (void)PrivateScope.Privatize();
4073 return CGF.EmitAnyExpr(UpExpr);
4074 });
4075 };
4076 if ((*IPriv)->getType()->isArrayType()) {
4077 // Emit atomic reduction for array section.
4078 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4079 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
4080 AtomicRedGen, XExpr, EExpr, UpExpr);
4081 } else
4082 // Emit atomic reduction for array subscript or single variable.
4083 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
4084 } else {
4085 // Emit as a critical region.
4086 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
4087 const Expr *, const Expr *) {
4088 auto &RT = CGF.CGM.getOpenMPRuntime();
4089 RT.emitCriticalRegion(
4090 CGF, ".atomic_reduction",
4091 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
4092 Action.Enter(CGF);
4093 emitReductionCombiner(CGF, E);
4094 },
4095 Loc);
4096 };
4097 if ((*IPriv)->getType()->isArrayType()) {
4098 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4099 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4100 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4101 CritRedGen);
4102 } else
4103 CritRedGen(CGF, nullptr, nullptr, nullptr);
4104 }
Richard Trieucc3949d2016-02-18 22:34:54 +00004105 ++ILHS;
4106 ++IRHS;
4107 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004108 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004109 };
4110 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
4111 if (!WithNowait) {
4112 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
4113 llvm::Value *EndArgs[] = {
4114 IdentTLoc, // ident_t *<loc>
4115 ThreadId, // i32 <gtid>
4116 Lock // kmp_critical_name *&<lock>
4117 };
4118 CommonActionTy Action(nullptr, llvm::None,
4119 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
4120 EndArgs);
4121 AtomicRCG.setAction(Action);
4122 AtomicRCG(CGF);
4123 } else
4124 AtomicRCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004125
4126 CGF.EmitBranch(DefaultBB);
4127 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
4128}
4129
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004130void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
4131 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004132 if (!CGF.HaveInsertPoint())
4133 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004134 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
4135 // global_tid);
4136 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
4137 // Ignore return result until untied tasks are supported.
4138 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev823acfa2016-04-19 16:27:55 +00004139 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
4140 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004141}
4142
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004143void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004144 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00004145 const RegionCodeGenTy &CodeGen,
4146 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004147 if (!CGF.HaveInsertPoint())
4148 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004149 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004150 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00004151}
4152
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004153namespace {
4154enum RTCancelKind {
4155 CancelNoreq = 0,
4156 CancelParallel = 1,
4157 CancelLoop = 2,
4158 CancelSections = 3,
4159 CancelTaskgroup = 4
4160};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004161} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004162
4163static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
4164 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00004165 if (CancelRegion == OMPD_parallel)
4166 CancelKind = CancelParallel;
4167 else if (CancelRegion == OMPD_for)
4168 CancelKind = CancelLoop;
4169 else if (CancelRegion == OMPD_sections)
4170 CancelKind = CancelSections;
4171 else {
4172 assert(CancelRegion == OMPD_taskgroup);
4173 CancelKind = CancelTaskgroup;
4174 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004175 return CancelKind;
4176}
4177
4178void CGOpenMPRuntime::emitCancellationPointCall(
4179 CodeGenFunction &CGF, SourceLocation Loc,
4180 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004181 if (!CGF.HaveInsertPoint())
4182 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004183 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
4184 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004185 if (auto *OMPRegionInfo =
4186 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00004187 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004188 llvm::Value *Args[] = {
4189 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
4190 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004191 // Ignore return result until untied tasks are supported.
4192 auto *Result = CGF.EmitRuntimeCall(
4193 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
4194 // if (__kmpc_cancellationpoint()) {
4195 // __kmpc_cancel_barrier();
4196 // exit from construct;
4197 // }
4198 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4199 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4200 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4201 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4202 CGF.EmitBlock(ExitBB);
4203 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00004204 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004205 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004206 auto CancelDest =
4207 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004208 CGF.EmitBranchThroughCleanup(CancelDest);
4209 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4210 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004211 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004212}
4213
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004214void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00004215 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004216 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004217 if (!CGF.HaveInsertPoint())
4218 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004219 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
4220 // kmp_int32 cncl_kind);
4221 if (auto *OMPRegionInfo =
4222 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004223 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
4224 PrePostActionTy &) {
4225 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00004226 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004227 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00004228 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
4229 // Ignore return result until untied tasks are supported.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004230 auto *Result = CGF.EmitRuntimeCall(
4231 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00004232 // if (__kmpc_cancel()) {
4233 // __kmpc_cancel_barrier();
4234 // exit from construct;
4235 // }
4236 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4237 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4238 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4239 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4240 CGF.EmitBlock(ExitBB);
4241 // __kmpc_cancel_barrier();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004242 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev87933c72015-09-18 08:07:34 +00004243 // exit from construct;
4244 auto CancelDest =
4245 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
4246 CGF.EmitBranchThroughCleanup(CancelDest);
4247 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4248 };
4249 if (IfCond)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004250 emitOMPIfClause(CGF, IfCond, ThenGen,
4251 [](CodeGenFunction &, PrePostActionTy &) {});
4252 else {
4253 RegionCodeGenTy ThenRCG(ThenGen);
4254 ThenRCG(CGF);
4255 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004256 }
4257}
Samuel Antaobed3c462015-10-02 16:14:20 +00004258
Samuel Antaoee8fb302016-01-06 13:42:12 +00004259/// \brief Obtain information that uniquely identifies a target entry. This
Samuel Antao2de62b02016-02-13 23:35:10 +00004260/// consists of the file and device IDs as well as line number associated with
4261/// the relevant entry source location.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004262static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
4263 unsigned &DeviceID, unsigned &FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004264 unsigned &LineNum) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004265
4266 auto &SM = C.getSourceManager();
4267
4268 // The loc should be always valid and have a file ID (the user cannot use
4269 // #pragma directives in macros)
4270
4271 assert(Loc.isValid() && "Source location is expected to be always valid.");
4272 assert(Loc.isFileID() && "Source location is expected to refer to a file.");
4273
4274 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
4275 assert(PLoc.isValid() && "Source location is expected to be always valid.");
4276
4277 llvm::sys::fs::UniqueID ID;
4278 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
4279 llvm_unreachable("Source file with target region no longer exists!");
4280
4281 DeviceID = ID.getDevice();
4282 FileID = ID.getFile();
4283 LineNum = PLoc.getLine();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004284}
4285
4286void CGOpenMPRuntime::emitTargetOutlinedFunction(
4287 const OMPExecutableDirective &D, StringRef ParentName,
4288 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004289 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004290 assert(!ParentName.empty() && "Invalid target region parent name!");
4291
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004292 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
4293 IsOffloadEntry, CodeGen);
4294}
4295
4296void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
4297 const OMPExecutableDirective &D, StringRef ParentName,
4298 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
4299 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004300 // Create a unique name for the entry function using the source location
4301 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004302 //
Samuel Antao2de62b02016-02-13 23:35:10 +00004303 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00004304 //
4305 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00004306 // mangled name of the function that encloses the target region and BB is the
4307 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004308
4309 unsigned DeviceID;
4310 unsigned FileID;
4311 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004312 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004313 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004314 SmallString<64> EntryFnName;
4315 {
4316 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00004317 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
4318 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004319 }
4320
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004321 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4322
Samuel Antaobed3c462015-10-02 16:14:20 +00004323 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004324 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00004325 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004326
4327 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
4328
4329 // If this target outline function is not an offload entry, we don't need to
4330 // register it.
4331 if (!IsOffloadEntry)
4332 return;
4333
4334 // The target region ID is used by the runtime library to identify the current
4335 // target region, so it only has to be unique and not necessarily point to
4336 // anything. It could be the pointer to the outlined function that implements
4337 // the target region, but we aren't using that so that the compiler doesn't
4338 // need to keep that, and could therefore inline the host function if proven
4339 // worthwhile during optimization. In the other hand, if emitting code for the
4340 // device, the ID has to be the function address so that it can retrieved from
4341 // the offloading entry and launched by the runtime library. We also mark the
4342 // outlined function to have external linkage in case we are emitting code for
4343 // the device, because these functions will be entry points to the device.
4344
4345 if (CGM.getLangOpts().OpenMPIsDevice) {
4346 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
4347 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage);
4348 } else
4349 OutlinedFnID = new llvm::GlobalVariable(
4350 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
4351 llvm::GlobalValue::PrivateLinkage,
4352 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id");
4353
4354 // Register the information for the entry associated with this target region.
4355 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00004356 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID);
Samuel Antaobed3c462015-10-02 16:14:20 +00004357}
4358
Samuel Antaob68e2db2016-03-03 16:20:23 +00004359/// \brief Emit the num_teams clause of an enclosed teams directive at the
4360/// target region scope. If there is no teams directive associated with the
4361/// target directive, or if there is no num_teams clause associated with the
4362/// enclosed teams directive, return nullptr.
4363static llvm::Value *
4364emitNumTeamsClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4365 CodeGenFunction &CGF,
4366 const OMPExecutableDirective &D) {
4367
4368 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4369 "teams directive expected to be "
4370 "emitted only for the host!");
4371
4372 // FIXME: For the moment we do not support combined directives with target and
4373 // teams, so we do not expect to get any num_teams clause in the provided
4374 // directive. Once we support that, this assertion can be replaced by the
4375 // actual emission of the clause expression.
4376 assert(D.getSingleClause<OMPNumTeamsClause>() == nullptr &&
4377 "Not expecting clause in directive.");
4378
4379 // If the current target region has a teams region enclosed, we need to get
4380 // the number of teams to pass to the runtime function call. This is done
4381 // by generating the expression in a inlined region. This is required because
4382 // the expression is captured in the enclosing target environment when the
4383 // teams directive is not combined with target.
4384
4385 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4386
4387 // FIXME: Accommodate other combined directives with teams when they become
4388 // available.
4389 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) {
4390 if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) {
4391 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4392 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4393 llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams());
4394 return CGF.Builder.CreateIntCast(NumTeams, CGF.Int32Ty,
4395 /*IsSigned=*/true);
4396 }
4397
4398 // If we have an enclosed teams directive but no num_teams clause we use
4399 // the default value 0.
4400 return CGF.Builder.getInt32(0);
4401 }
4402
4403 // No teams associated with the directive.
4404 return nullptr;
4405}
4406
4407/// \brief Emit the thread_limit clause of an enclosed teams directive at the
4408/// target region scope. If there is no teams directive associated with the
4409/// target directive, or if there is no thread_limit clause associated with the
4410/// enclosed teams directive, return nullptr.
4411static llvm::Value *
4412emitThreadLimitClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4413 CodeGenFunction &CGF,
4414 const OMPExecutableDirective &D) {
4415
4416 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4417 "teams directive expected to be "
4418 "emitted only for the host!");
4419
4420 // FIXME: For the moment we do not support combined directives with target and
4421 // teams, so we do not expect to get any thread_limit clause in the provided
4422 // directive. Once we support that, this assertion can be replaced by the
4423 // actual emission of the clause expression.
4424 assert(D.getSingleClause<OMPThreadLimitClause>() == nullptr &&
4425 "Not expecting clause in directive.");
4426
4427 // If the current target region has a teams region enclosed, we need to get
4428 // the thread limit to pass to the runtime function call. This is done
4429 // by generating the expression in a inlined region. This is required because
4430 // the expression is captured in the enclosing target environment when the
4431 // teams directive is not combined with target.
4432
4433 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4434
4435 // FIXME: Accommodate other combined directives with teams when they become
4436 // available.
4437 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) {
4438 if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) {
4439 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4440 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4441 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit());
4442 return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty,
4443 /*IsSigned=*/true);
4444 }
4445
4446 // If we have an enclosed teams directive but no thread_limit clause we use
4447 // the default value 0.
4448 return CGF.Builder.getInt32(0);
4449 }
4450
4451 // No teams associated with the directive.
4452 return nullptr;
4453}
4454
Samuel Antaobed3c462015-10-02 16:14:20 +00004455void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
4456 const OMPExecutableDirective &D,
4457 llvm::Value *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00004458 llvm::Value *OutlinedFnID,
Samuel Antaobed3c462015-10-02 16:14:20 +00004459 const Expr *IfCond, const Expr *Device,
4460 ArrayRef<llvm::Value *> CapturedVars) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004461 if (!CGF.HaveInsertPoint())
4462 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00004463 /// \brief Values for bit flags used to specify the mapping type for
4464 /// offloading.
4465 enum OpenMPOffloadMappingFlags {
4466 /// \brief Allocate memory on the device and move data from host to device.
4467 OMP_MAP_TO = 0x01,
4468 /// \brief Allocate memory on the device and move data from device to host.
4469 OMP_MAP_FROM = 0x02,
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004470 /// \brief The element passed to the device is a pointer.
4471 OMP_MAP_PTR = 0x20,
4472 /// \brief Pass the element to the device by value.
4473 OMP_MAP_BYCOPY = 0x80,
Samuel Antaobed3c462015-10-02 16:14:20 +00004474 };
4475
4476 enum OpenMPOffloadingReservedDeviceIDs {
4477 /// \brief Device ID if the device was not defined, runtime should get it
4478 /// from environment variables in the spec.
4479 OMP_DEVICEID_UNDEF = -1,
4480 };
4481
Samuel Antaoee8fb302016-01-06 13:42:12 +00004482 assert(OutlinedFn && "Invalid outlined function!");
4483
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004484 auto &Ctx = CGF.getContext();
4485
Samuel Antaobed3c462015-10-02 16:14:20 +00004486 // Fill up the arrays with the all the captured variables.
4487 SmallVector<llvm::Value *, 16> BasePointers;
4488 SmallVector<llvm::Value *, 16> Pointers;
4489 SmallVector<llvm::Value *, 16> Sizes;
4490 SmallVector<unsigned, 16> MapTypes;
4491
4492 bool hasVLACaptures = false;
4493
4494 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4495 auto RI = CS.getCapturedRecordDecl()->field_begin();
4496 // auto II = CS.capture_init_begin();
4497 auto CV = CapturedVars.begin();
4498 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
4499 CE = CS.capture_end();
4500 CI != CE; ++CI, ++RI, ++CV) {
4501 StringRef Name;
4502 QualType Ty;
4503 llvm::Value *BasePointer;
4504 llvm::Value *Pointer;
4505 llvm::Value *Size;
4506 unsigned MapType;
4507
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004508 // VLA sizes are passed to the outlined region by copy.
Samuel Antaobed3c462015-10-02 16:14:20 +00004509 if (CI->capturesVariableArrayType()) {
4510 BasePointer = Pointer = *CV;
Alexey Bataev1189bd02016-01-26 12:20:39 +00004511 Size = CGF.getTypeSize(RI->getType());
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004512 // Copy to the device as an argument. No need to retrieve it.
4513 MapType = OMP_MAP_BYCOPY;
Samuel Antaobed3c462015-10-02 16:14:20 +00004514 hasVLACaptures = true;
Samuel Antaobed3c462015-10-02 16:14:20 +00004515 } else if (CI->capturesThis()) {
4516 BasePointer = Pointer = *CV;
4517 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr());
Alexey Bataev1189bd02016-01-26 12:20:39 +00004518 Size = CGF.getTypeSize(PtrTy->getPointeeType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004519 // Default map type.
4520 MapType = OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004521 } else if (CI->capturesVariableByCopy()) {
4522 MapType = OMP_MAP_BYCOPY;
4523 if (!RI->getType()->isAnyPointerType()) {
4524 // If the field is not a pointer, we need to save the actual value and
4525 // load it as a void pointer.
4526 auto DstAddr = CGF.CreateMemTemp(
4527 Ctx.getUIntPtrType(),
4528 Twine(CI->getCapturedVar()->getName()) + ".casted");
4529 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
4530
4531 auto *SrcAddrVal = CGF.EmitScalarConversion(
4532 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
4533 Ctx.getPointerType(RI->getType()), SourceLocation());
4534 LValue SrcLV =
4535 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType());
4536
4537 // Store the value using the source type pointer.
4538 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV);
4539
4540 // Load the value using the destination type pointer.
4541 BasePointer = Pointer =
4542 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
4543 } else {
4544 MapType |= OMP_MAP_PTR;
4545 BasePointer = Pointer = *CV;
4546 }
Alexey Bataev1189bd02016-01-26 12:20:39 +00004547 Size = CGF.getTypeSize(RI->getType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004548 } else {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004549 assert(CI->capturesVariable() && "Expected captured reference.");
Samuel Antaobed3c462015-10-02 16:14:20 +00004550 BasePointer = Pointer = *CV;
4551
4552 const ReferenceType *PtrTy =
4553 cast<ReferenceType>(RI->getType().getTypePtr());
4554 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00004555 Size = CGF.getTypeSize(ElementType);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004556 // The default map type for a scalar/complex type is 'to' because by
4557 // default the value doesn't have to be retrieved. For an aggregate type,
4558 // the default is 'tofrom'.
4559 MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
4560 : OMP_MAP_TO;
4561 if (ElementType->isAnyPointerType())
4562 MapType |= OMP_MAP_PTR;
Samuel Antaobed3c462015-10-02 16:14:20 +00004563 }
4564
4565 BasePointers.push_back(BasePointer);
4566 Pointers.push_back(Pointer);
4567 Sizes.push_back(Size);
4568 MapTypes.push_back(MapType);
4569 }
4570
4571 // Keep track on whether the host function has to be executed.
4572 auto OffloadErrorQType =
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004573 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004574 auto OffloadError = CGF.MakeAddrLValue(
4575 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
4576 OffloadErrorQType);
4577 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
4578 OffloadError);
4579
4580 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004581 auto &&ThenGen = [&Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes,
Alexey Bataevf539faa2016-03-28 12:58:34 +00004582 hasVLACaptures, Device, OutlinedFnID, OffloadError,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004583 OffloadErrorQType,
4584 &D](CodeGenFunction &CGF, PrePostActionTy &) {
4585 auto &RT = CGF.CGM.getOpenMPRuntime();
Samuel Antaobed3c462015-10-02 16:14:20 +00004586 unsigned PointerNumVal = BasePointers.size();
4587 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal);
4588 llvm::Value *BasePointersArray;
4589 llvm::Value *PointersArray;
4590 llvm::Value *SizesArray;
4591 llvm::Value *MapTypesArray;
4592
4593 if (PointerNumVal) {
4594 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004595 QualType PointerArrayType = Ctx.getConstantArrayType(
4596 Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004597 /*IndexTypeQuals=*/0);
4598
4599 BasePointersArray =
4600 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
4601 PointersArray =
4602 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
4603
4604 // If we don't have any VLA types, we can use a constant array for the map
4605 // sizes, otherwise we need to fill up the arrays as we do for the
4606 // pointers.
4607 if (hasVLACaptures) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004608 QualType SizeArrayType = Ctx.getConstantArrayType(
4609 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004610 /*IndexTypeQuals=*/0);
4611 SizesArray =
4612 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
4613 } else {
4614 // We expect all the sizes to be constant, so we collect them to create
4615 // a constant array.
4616 SmallVector<llvm::Constant *, 16> ConstSizes;
4617 for (auto S : Sizes)
4618 ConstSizes.push_back(cast<llvm::Constant>(S));
4619
4620 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004621 llvm::ArrayType::get(CGF.CGM.SizeTy, ConstSizes.size()),
4622 ConstSizes);
Samuel Antaobed3c462015-10-02 16:14:20 +00004623 auto *SizesArrayGbl = new llvm::GlobalVariable(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004624 CGF.CGM.getModule(), SizesArrayInit->getType(),
Samuel Antaobed3c462015-10-02 16:14:20 +00004625 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4626 SizesArrayInit, ".offload_sizes");
4627 SizesArrayGbl->setUnnamedAddr(true);
4628 SizesArray = SizesArrayGbl;
4629 }
4630
4631 // The map types are always constant so we don't need to generate code to
4632 // fill arrays. Instead, we create an array constant.
4633 llvm::Constant *MapTypesArrayInit =
4634 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
4635 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004636 CGF.CGM.getModule(), MapTypesArrayInit->getType(),
Samuel Antaobed3c462015-10-02 16:14:20 +00004637 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4638 MapTypesArrayInit, ".offload_maptypes");
4639 MapTypesArrayGbl->setUnnamedAddr(true);
4640 MapTypesArray = MapTypesArrayGbl;
4641
4642 for (unsigned i = 0; i < PointerNumVal; ++i) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004643 llvm::Value *BPVal = BasePointers[i];
4644 if (BPVal->getType()->isPointerTy())
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004645 BPVal = CGF.Builder.CreateBitCast(BPVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004646 else {
4647 assert(BPVal->getType()->isIntegerTy() &&
4648 "If not a pointer, the value type must be an integer.");
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004649 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004650 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004651 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004652 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal),
Samuel Antaobed3c462015-10-02 16:14:20 +00004653 BasePointersArray, 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004654 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4655 CGF.Builder.CreateStore(BPVal, BPAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004656
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004657 llvm::Value *PVal = Pointers[i];
4658 if (PVal->getType()->isPointerTy())
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004659 PVal = CGF.Builder.CreateBitCast(PVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004660 else {
4661 assert(PVal->getType()->isIntegerTy() &&
4662 "If not a pointer, the value type must be an integer.");
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004663 PVal = CGF.Builder.CreateIntToPtr(PVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004664 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004665 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004666 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), PointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004667 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004668 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4669 CGF.Builder.CreateStore(PVal, PAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004670
4671 if (hasVLACaptures) {
4672 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004673 llvm::ArrayType::get(CGF.SizeTy, PointerNumVal), SizesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004674 /*Idx0=*/0,
4675 /*Idx1=*/i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004676 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
Samuel Antaobed3c462015-10-02 16:14:20 +00004677 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004678 Sizes[i], CGF.SizeTy, /*isSigned=*/true),
Samuel Antaobed3c462015-10-02 16:14:20 +00004679 SAddr);
4680 }
4681 }
4682
4683 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004684 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), BasePointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004685 /*Idx0=*/0, /*Idx1=*/0);
4686 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004687 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), PointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004688 /*Idx0=*/0,
4689 /*Idx1=*/0);
4690 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004691 llvm::ArrayType::get(CGF.SizeTy, PointerNumVal), SizesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004692 /*Idx0=*/0, /*Idx1=*/0);
4693 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004694 llvm::ArrayType::get(CGF.Int32Ty, PointerNumVal), MapTypesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004695 /*Idx0=*/0,
4696 /*Idx1=*/0);
4697
4698 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004699 BasePointersArray = llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy);
4700 PointersArray = llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy);
4701 SizesArray = llvm::ConstantPointerNull::get(CGF.SizeTy->getPointerTo());
Samuel Antaobed3c462015-10-02 16:14:20 +00004702 MapTypesArray =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004703 llvm::ConstantPointerNull::get(CGF.Int32Ty->getPointerTo());
Samuel Antaobed3c462015-10-02 16:14:20 +00004704 }
4705
4706 // On top of the arrays that were filled up, the target offloading call
4707 // takes as arguments the device id as well as the host pointer. The host
4708 // pointer is used by the runtime library to identify the current target
4709 // region, so it only has to be unique and not necessarily point to
4710 // anything. It could be the pointer to the outlined function that
4711 // implements the target region, but we aren't using that so that the
4712 // compiler doesn't need to keep that, and could therefore inline the host
4713 // function if proven worthwhile during optimization.
4714
Samuel Antaoee8fb302016-01-06 13:42:12 +00004715 // From this point on, we need to have an ID of the target region defined.
4716 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00004717
4718 // Emit device ID if any.
4719 llvm::Value *DeviceID;
4720 if (Device)
4721 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004722 CGF.Int32Ty, /*isSigned=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004723 else
4724 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
4725
Samuel Antaob68e2db2016-03-03 16:20:23 +00004726 // Return value of the runtime offloading call.
4727 llvm::Value *Return;
4728
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004729 auto *NumTeams = emitNumTeamsClauseForTargetDirective(RT, CGF, D);
4730 auto *ThreadLimit = emitThreadLimitClauseForTargetDirective(RT, CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004731
4732 // If we have NumTeams defined this means that we have an enclosed teams
4733 // region. Therefore we also expect to have ThreadLimit defined. These two
4734 // values should be defined in the presence of a teams directive, regardless
4735 // of having any clauses associated. If the user is using teams but no
4736 // clauses, these two values will be the default that should be passed to
4737 // the runtime library - a 32-bit integer with the value zero.
4738 if (NumTeams) {
4739 assert(ThreadLimit && "Thread limit expression should be available along "
4740 "with number of teams.");
4741 llvm::Value *OffloadingArgs[] = {
4742 DeviceID, OutlinedFnID, PointerNum,
4743 BasePointersArray, PointersArray, SizesArray,
4744 MapTypesArray, NumTeams, ThreadLimit};
4745 Return = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004746 RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004747 } else {
4748 llvm::Value *OffloadingArgs[] = {
4749 DeviceID, OutlinedFnID, PointerNum, BasePointersArray,
4750 PointersArray, SizesArray, MapTypesArray};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004751 Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target),
Samuel Antaob68e2db2016-03-03 16:20:23 +00004752 OffloadingArgs);
4753 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004754
4755 CGF.EmitStoreOfScalar(Return, OffloadError);
4756 };
4757
Samuel Antaoee8fb302016-01-06 13:42:12 +00004758 // Notify that the host version must be executed.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004759 auto &&ElseGen = [OffloadError](CodeGenFunction &CGF, PrePostActionTy &) {
4760 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/-1u),
Samuel Antaoee8fb302016-01-06 13:42:12 +00004761 OffloadError);
4762 };
4763
4764 // If we have a target function ID it means that we need to support
4765 // offloading, otherwise, just execute on the host. We need to execute on host
4766 // regardless of the conditional in the if clause if, e.g., the user do not
4767 // specify target triples.
4768 if (OutlinedFnID) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004769 if (IfCond)
Samuel Antaoee8fb302016-01-06 13:42:12 +00004770 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004771 else {
4772 RegionCodeGenTy ThenRCG(ThenGen);
4773 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00004774 }
4775 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004776 RegionCodeGenTy ElseRCG(ElseGen);
4777 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00004778 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004779
4780 // Check the error code and execute the host version if required.
4781 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
4782 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
4783 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
4784 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
4785 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
4786
4787 CGF.EmitBlock(OffloadFailedBlock);
4788 CGF.Builder.CreateCall(OutlinedFn, BasePointers);
4789 CGF.EmitBranch(OffloadContBlock);
4790
4791 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004792}
Samuel Antaoee8fb302016-01-06 13:42:12 +00004793
4794void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
4795 StringRef ParentName) {
4796 if (!S)
4797 return;
4798
4799 // If we find a OMP target directive, codegen the outline function and
4800 // register the result.
4801 // FIXME: Add other directives with target when they become supported.
4802 bool isTargetDirective = isa<OMPTargetDirective>(S);
4803
4804 if (isTargetDirective) {
4805 auto *E = cast<OMPExecutableDirective>(S);
4806 unsigned DeviceID;
4807 unsigned FileID;
4808 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004809 getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004810 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004811
4812 // Is this a target region that should not be emitted as an entry point? If
4813 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00004814 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
4815 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004816 return;
4817
4818 llvm::Function *Fn;
4819 llvm::Constant *Addr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004820 std::tie(Fn, Addr) =
4821 CodeGenFunction::EmitOMPTargetDirectiveOutlinedFunction(
4822 CGM, cast<OMPTargetDirective>(*E), ParentName,
4823 /*isOffloadEntry=*/true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004824 assert(Fn && Addr && "Target region emission failed.");
4825 return;
4826 }
4827
4828 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) {
4829 if (!E->getAssociatedStmt())
4830 return;
4831
4832 scanForTargetRegionsFunctions(
4833 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(),
4834 ParentName);
4835 return;
4836 }
4837
4838 // If this is a lambda function, look into its body.
4839 if (auto *L = dyn_cast<LambdaExpr>(S))
4840 S = L->getBody();
4841
4842 // Keep looking for target regions recursively.
4843 for (auto *II : S->children())
4844 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004845}
4846
4847bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
4848 auto &FD = *cast<FunctionDecl>(GD.getDecl());
4849
4850 // If emitting code for the host, we do not process FD here. Instead we do
4851 // the normal code generation.
4852 if (!CGM.getLangOpts().OpenMPIsDevice)
4853 return false;
4854
4855 // Try to detect target regions in the function.
4856 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
4857
4858 // We should not emit any function othen that the ones created during the
4859 // scanning. Therefore, we signal that this function is completely dealt
4860 // with.
4861 return true;
4862}
4863
4864bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
4865 if (!CGM.getLangOpts().OpenMPIsDevice)
4866 return false;
4867
4868 // Check if there are Ctors/Dtors in this declaration and look for target
4869 // regions in it. We use the complete variant to produce the kernel name
4870 // mangling.
4871 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
4872 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
4873 for (auto *Ctor : RD->ctors()) {
4874 StringRef ParentName =
4875 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
4876 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
4877 }
4878 auto *Dtor = RD->getDestructor();
4879 if (Dtor) {
4880 StringRef ParentName =
4881 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
4882 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
4883 }
4884 }
4885
4886 // If we are in target mode we do not emit any global (declare target is not
4887 // implemented yet). Therefore we signal that GD was processed in this case.
4888 return true;
4889}
4890
4891bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
4892 auto *VD = GD.getDecl();
4893 if (isa<FunctionDecl>(VD))
4894 return emitTargetFunctions(GD);
4895
4896 return emitTargetGlobalVariable(GD);
4897}
4898
4899llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
4900 // If we have offloading in the current module, we need to emit the entries
4901 // now and register the offloading descriptor.
4902 createOffloadEntriesAndInfoMetadata();
4903
4904 // Create and register the offloading binary descriptors. This is the main
4905 // entity that captures all the information about offloading in the current
4906 // compilation unit.
4907 return createOffloadingBinaryDescriptorRegistration();
4908}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004909
4910void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
4911 const OMPExecutableDirective &D,
4912 SourceLocation Loc,
4913 llvm::Value *OutlinedFn,
4914 ArrayRef<llvm::Value *> CapturedVars) {
4915 if (!CGF.HaveInsertPoint())
4916 return;
4917
4918 auto *RTLoc = emitUpdateLocation(CGF, Loc);
4919 CodeGenFunction::RunCleanupsScope Scope(CGF);
4920
4921 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
4922 llvm::Value *Args[] = {
4923 RTLoc,
4924 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
4925 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
4926 llvm::SmallVector<llvm::Value *, 16> RealArgs;
4927 RealArgs.append(std::begin(Args), std::end(Args));
4928 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
4929
4930 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
4931 CGF.EmitRuntimeCall(RTLFn, RealArgs);
4932}
4933
4934void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00004935 const Expr *NumTeams,
4936 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004937 SourceLocation Loc) {
4938 if (!CGF.HaveInsertPoint())
4939 return;
4940
4941 auto *RTLoc = emitUpdateLocation(CGF, Loc);
4942
Carlo Bertollic6872252016-04-04 15:55:02 +00004943 llvm::Value *NumTeamsVal =
4944 (NumTeams)
4945 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
4946 CGF.CGM.Int32Ty, /* isSigned = */ true)
4947 : CGF.Builder.getInt32(0);
4948
4949 llvm::Value *ThreadLimitVal =
4950 (ThreadLimit)
4951 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
4952 CGF.CGM.Int32Ty, /* isSigned = */ true)
4953 : CGF.Builder.getInt32(0);
4954
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004955 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00004956 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
4957 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004958 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
4959 PushNumTeamsArgs);
4960}