blob: 37ecc053afaf58d2acb433c554d28771f0d7f96a [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides a class for OpenMP runtime code generation.
11//
12//===----------------------------------------------------------------------===//
13
Samuel Antaoee8fb302016-01-06 13:42:12 +000014#include "CGCXXABI.h"
15#include "CGCleanup.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000016#include "CGOpenMPRuntime.h"
17#include "CodeGenFunction.h"
18#include "clang/AST/Decl.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000019#include "clang/AST/StmtOpenMP.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000020#include "llvm/ADT/ArrayRef.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000021#include "llvm/Bitcode/ReaderWriter.h"
Alexey Bataevd74d0602014-10-13 06:02:40 +000022#include "llvm/IR/CallSite.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000023#include "llvm/IR/DerivedTypes.h"
24#include "llvm/IR/GlobalValue.h"
25#include "llvm/IR/Value.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000026#include "llvm/Support/Format.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000027#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000028#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000029
30using namespace clang;
31using namespace CodeGen;
32
Benjamin Kramerc52193f2014-10-10 13:57:57 +000033namespace {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000034/// \brief Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000035class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
36public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000037 /// \brief Kinds of OpenMP regions used in codegen.
38 enum CGOpenMPRegionKind {
39 /// \brief Region with outlined function for standalone 'parallel'
40 /// directive.
41 ParallelOutlinedRegion,
42 /// \brief Region with outlined function for standalone 'task' directive.
43 TaskOutlinedRegion,
44 /// \brief Region for constructs that do not require function outlining,
45 /// like 'for', 'sections', 'atomic' etc. directives.
46 InlinedRegion,
Samuel Antaobed3c462015-10-02 16:14:20 +000047 /// \brief Region with outlined function for standalone 'target' directive.
48 TargetRegion,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000049 };
Alexey Bataev18095712014-10-10 12:19:54 +000050
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000051 CGOpenMPRegionInfo(const CapturedStmt &CS,
52 const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000053 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
54 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000055 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000056 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000057
58 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000059 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
60 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000061 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000062 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000063
64 /// \brief Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000065 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000066 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000067
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000068 /// \brief Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000069 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000070
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000071 /// \brief Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000072 /// \return LValue for thread id variable. This LValue always has type int32*.
73 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000074
Alexey Bataev48591dd2016-04-20 04:01:36 +000075 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
76
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000077 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000078
Alexey Bataev81c7ea02015-07-03 09:56:58 +000079 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
80
Alexey Bataev25e5b442015-09-15 12:52:43 +000081 bool hasCancel() const { return HasCancel; }
82
Alexey Bataev18095712014-10-10 12:19:54 +000083 static bool classof(const CGCapturedStmtInfo *Info) {
84 return Info->getKind() == CR_OpenMP;
85 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000086
Alexey Bataev48591dd2016-04-20 04:01:36 +000087 ~CGOpenMPRegionInfo() override = default;
88
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000089protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000090 CGOpenMPRegionKind RegionKind;
Hans Wennborg45c74392016-01-12 20:54:36 +000091 RegionCodeGenTy CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000092 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +000093 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000094};
Alexey Bataev18095712014-10-10 12:19:54 +000095
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000096/// \brief API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +000097class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000098public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000099 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000100 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000101 OpenMPDirectiveKind Kind, bool HasCancel)
102 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
103 HasCancel),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000104 ThreadIDVar(ThreadIDVar) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000105 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
106 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000107
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000108 /// \brief Get a variable or parameter for storing global thread id
109 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000110 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000111
Alexey Bataev18095712014-10-10 12:19:54 +0000112 /// \brief Get the name of the capture helper.
Benjamin Kramerc52193f2014-10-10 13:57:57 +0000113 StringRef getHelperName() const override { return ".omp_outlined."; }
Alexey Bataev18095712014-10-10 12:19:54 +0000114
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000115 static bool classof(const CGCapturedStmtInfo *Info) {
116 return CGOpenMPRegionInfo::classof(Info) &&
117 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
118 ParallelOutlinedRegion;
119 }
120
Alexey Bataev18095712014-10-10 12:19:54 +0000121private:
122 /// \brief A variable or parameter storing global thread id for OpenMP
123 /// constructs.
124 const VarDecl *ThreadIDVar;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000125};
126
Alexey Bataev62b63b12015-03-10 07:28:44 +0000127/// \brief API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000128class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000129public:
Alexey Bataev48591dd2016-04-20 04:01:36 +0000130 class UntiedTaskActionTy final : public PrePostActionTy {
131 bool Untied;
132 const VarDecl *PartIDVar;
133 const RegionCodeGenTy UntiedCodeGen;
134 llvm::SwitchInst *UntiedSwitch = nullptr;
135
136 public:
137 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
138 const RegionCodeGenTy &UntiedCodeGen)
139 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
140 void Enter(CodeGenFunction &CGF) override {
141 if (Untied) {
142 // Emit task switching point.
143 auto PartIdLVal = CGF.EmitLoadOfPointerLValue(
144 CGF.GetAddrOfLocalVar(PartIDVar),
145 PartIDVar->getType()->castAs<PointerType>());
146 auto *Res = CGF.EmitLoadOfScalar(PartIdLVal, SourceLocation());
147 auto *DoneBB = CGF.createBasicBlock(".untied.done.");
148 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
149 CGF.EmitBlock(DoneBB);
150 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
151 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
152 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
153 CGF.Builder.GetInsertBlock());
154 emitUntiedSwitch(CGF);
155 }
156 }
157 void emitUntiedSwitch(CodeGenFunction &CGF) const {
158 if (Untied) {
159 auto PartIdLVal = CGF.EmitLoadOfPointerLValue(
160 CGF.GetAddrOfLocalVar(PartIDVar),
161 PartIDVar->getType()->castAs<PointerType>());
162 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
163 PartIdLVal);
164 UntiedCodeGen(CGF);
165 CodeGenFunction::JumpDest CurPoint =
166 CGF.getJumpDestInCurrentScope(".untied.next.");
167 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
168 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
169 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
170 CGF.Builder.GetInsertBlock());
171 CGF.EmitBranchThroughCleanup(CurPoint);
172 CGF.EmitBlock(CurPoint.getBlock());
173 }
174 }
175 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
176 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000177 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000178 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000179 const RegionCodeGenTy &CodeGen,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000180 OpenMPDirectiveKind Kind, bool HasCancel,
181 const UntiedTaskActionTy &Action)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000182 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev48591dd2016-04-20 04:01:36 +0000183 ThreadIDVar(ThreadIDVar), Action(Action) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000184 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
185 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000186
Alexey Bataev62b63b12015-03-10 07:28:44 +0000187 /// \brief Get a variable or parameter for storing global thread id
188 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000189 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000190
191 /// \brief Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000192 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000193
Alexey Bataev62b63b12015-03-10 07:28:44 +0000194 /// \brief Get the name of the capture helper.
195 StringRef getHelperName() const override { return ".omp_outlined."; }
196
Alexey Bataev48591dd2016-04-20 04:01:36 +0000197 void emitUntiedSwitch(CodeGenFunction &CGF) override {
198 Action.emitUntiedSwitch(CGF);
199 }
200
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000201 static bool classof(const CGCapturedStmtInfo *Info) {
202 return CGOpenMPRegionInfo::classof(Info) &&
203 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
204 TaskOutlinedRegion;
205 }
206
Alexey Bataev62b63b12015-03-10 07:28:44 +0000207private:
208 /// \brief A variable or parameter storing global thread id for OpenMP
209 /// constructs.
210 const VarDecl *ThreadIDVar;
Alexey Bataev48591dd2016-04-20 04:01:36 +0000211 /// Action for emitting code for untied tasks.
212 const UntiedTaskActionTy &Action;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000213};
214
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000215/// \brief API for inlined captured statement code generation in OpenMP
216/// constructs.
217class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
218public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000219 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000220 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000221 OpenMPDirectiveKind Kind, bool HasCancel)
222 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
223 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000224 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000225
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000226 // \brief Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000227 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000228 if (OuterRegionInfo)
229 return OuterRegionInfo->getContextValue();
230 llvm_unreachable("No context value for inlined OpenMP region");
231 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000232
Hans Wennborg7eb54642015-09-10 17:07:54 +0000233 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000234 if (OuterRegionInfo) {
235 OuterRegionInfo->setContextValue(V);
236 return;
237 }
238 llvm_unreachable("No context value for inlined OpenMP region");
239 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000240
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000241 /// \brief Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000242 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000243 if (OuterRegionInfo)
244 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000245 // If there is no outer outlined region,no need to lookup in a list of
246 // captured variables, we can use the original one.
247 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000248 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000249
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000250 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000251 if (OuterRegionInfo)
252 return OuterRegionInfo->getThisFieldDecl();
253 return nullptr;
254 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000255
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000256 /// \brief Get a variable or parameter for storing global thread id
257 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000258 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000259 if (OuterRegionInfo)
260 return OuterRegionInfo->getThreadIDVariable();
261 return nullptr;
262 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000263
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000264 /// \brief Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000265 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000266 if (auto *OuterRegionInfo = getOldCSI())
267 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000268 llvm_unreachable("No helper name for inlined OpenMP construct");
269 }
270
Alexey Bataev48591dd2016-04-20 04:01:36 +0000271 void emitUntiedSwitch(CodeGenFunction &CGF) override {
272 if (OuterRegionInfo)
273 OuterRegionInfo->emitUntiedSwitch(CGF);
274 }
275
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000276 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
277
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000278 static bool classof(const CGCapturedStmtInfo *Info) {
279 return CGOpenMPRegionInfo::classof(Info) &&
280 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
281 }
282
Alexey Bataev48591dd2016-04-20 04:01:36 +0000283 ~CGOpenMPInlinedRegionInfo() override = default;
284
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000285private:
286 /// \brief CodeGen info about outer OpenMP region.
287 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
288 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000289};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000290
Samuel Antaobed3c462015-10-02 16:14:20 +0000291/// \brief API for captured statement code generation in OpenMP target
292/// constructs. For this captures, implicit parameters are used instead of the
Samuel Antaoee8fb302016-01-06 13:42:12 +0000293/// captured fields. The name of the target region has to be unique in a given
294/// application so it is provided by the client, because only the client has
295/// the information to generate that.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000296class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
Samuel Antaobed3c462015-10-02 16:14:20 +0000297public:
298 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000299 const RegionCodeGenTy &CodeGen, StringRef HelperName)
Samuel Antaobed3c462015-10-02 16:14:20 +0000300 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000301 /*HasCancel=*/false),
302 HelperName(HelperName) {}
Samuel Antaobed3c462015-10-02 16:14:20 +0000303
304 /// \brief This is unused for target regions because each starts executing
305 /// with a single thread.
306 const VarDecl *getThreadIDVariable() const override { return nullptr; }
307
308 /// \brief Get the name of the capture helper.
Samuel Antaoee8fb302016-01-06 13:42:12 +0000309 StringRef getHelperName() const override { return HelperName; }
Samuel Antaobed3c462015-10-02 16:14:20 +0000310
311 static bool classof(const CGCapturedStmtInfo *Info) {
312 return CGOpenMPRegionInfo::classof(Info) &&
313 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
314 }
Samuel Antaoee8fb302016-01-06 13:42:12 +0000315
316private:
317 StringRef HelperName;
Samuel Antaobed3c462015-10-02 16:14:20 +0000318};
319
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000320static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000321 llvm_unreachable("No codegen for expressions");
322}
323/// \brief API for generation of expressions captured in a innermost OpenMP
324/// region.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000325class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000326public:
327 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
328 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
329 OMPD_unknown,
330 /*HasCancel=*/false),
331 PrivScope(CGF) {
332 // Make sure the globals captured in the provided statement are local by
333 // using the privatization logic. We assume the same variable is not
334 // captured more than once.
335 for (auto &C : CS.captures()) {
336 if (!C.capturesVariable() && !C.capturesVariableByCopy())
337 continue;
338
339 const VarDecl *VD = C.getCapturedVar();
340 if (VD->isLocalVarDeclOrParm())
341 continue;
342
343 DeclRefExpr DRE(const_cast<VarDecl *>(VD),
344 /*RefersToEnclosingVariableOrCapture=*/false,
345 VD->getType().getNonReferenceType(), VK_LValue,
346 SourceLocation());
347 PrivScope.addPrivate(VD, [&CGF, &DRE]() -> Address {
348 return CGF.EmitLValue(&DRE).getAddress();
349 });
350 }
351 (void)PrivScope.Privatize();
352 }
353
354 /// \brief Lookup the captured field decl for a variable.
355 const FieldDecl *lookup(const VarDecl *VD) const override {
356 if (auto *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
357 return FD;
358 return nullptr;
359 }
360
361 /// \brief Emit the captured statement body.
362 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
363 llvm_unreachable("No body for expressions");
364 }
365
366 /// \brief Get a variable or parameter for storing global thread id
367 /// inside OpenMP construct.
368 const VarDecl *getThreadIDVariable() const override {
369 llvm_unreachable("No thread id for expressions");
370 }
371
372 /// \brief Get the name of the capture helper.
373 StringRef getHelperName() const override {
374 llvm_unreachable("No helper name for expressions");
375 }
376
377 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
378
379private:
380 /// Private scope to capture global variables.
381 CodeGenFunction::OMPPrivateScope PrivScope;
382};
383
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000384/// \brief RAII for emitting code of OpenMP constructs.
385class InlinedOpenMPRegionRAII {
386 CodeGenFunction &CGF;
387
388public:
389 /// \brief Constructs region for combined constructs.
390 /// \param CodeGen Code generation sequence for combined directives. Includes
391 /// a list of functions used for code generation of implicitly inlined
392 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000393 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000394 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000395 : CGF(CGF) {
396 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000397 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
398 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000399 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000400
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000401 ~InlinedOpenMPRegionRAII() {
402 // Restore original CapturedStmtInfo only if we're done with code emission.
403 auto *OldCSI =
404 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
405 delete CGF.CapturedStmtInfo;
406 CGF.CapturedStmtInfo = OldCSI;
407 }
408};
409
Alexey Bataev50b3c952016-02-19 10:38:26 +0000410/// \brief Values for bit flags used in the ident_t to describe the fields.
411/// All enumeric elements are named and described in accordance with the code
412/// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
413enum OpenMPLocationFlags {
414 /// \brief Use trampoline for internal microtask.
415 OMP_IDENT_IMD = 0x01,
416 /// \brief Use c-style ident structure.
417 OMP_IDENT_KMPC = 0x02,
418 /// \brief Atomic reduction option for kmpc_reduce.
419 OMP_ATOMIC_REDUCE = 0x10,
420 /// \brief Explicit 'barrier' directive.
421 OMP_IDENT_BARRIER_EXPL = 0x20,
422 /// \brief Implicit barrier in code.
423 OMP_IDENT_BARRIER_IMPL = 0x40,
424 /// \brief Implicit barrier in 'for' directive.
425 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
426 /// \brief Implicit barrier in 'sections' directive.
427 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
428 /// \brief Implicit barrier in 'single' directive.
429 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140
430};
431
432/// \brief Describes ident structure that describes a source location.
433/// All descriptions are taken from
434/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
435/// Original structure:
436/// typedef struct ident {
437/// kmp_int32 reserved_1; /**< might be used in Fortran;
438/// see above */
439/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
440/// KMP_IDENT_KMPC identifies this union
441/// member */
442/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
443/// see above */
444///#if USE_ITT_BUILD
445/// /* but currently used for storing
446/// region-specific ITT */
447/// /* contextual information. */
448///#endif /* USE_ITT_BUILD */
449/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
450/// C++ */
451/// char const *psource; /**< String describing the source location.
452/// The string is composed of semi-colon separated
453// fields which describe the source file,
454/// the function and a pair of line numbers that
455/// delimit the construct.
456/// */
457/// } ident_t;
458enum IdentFieldIndex {
459 /// \brief might be used in Fortran
460 IdentField_Reserved_1,
461 /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
462 IdentField_Flags,
463 /// \brief Not really used in Fortran any more
464 IdentField_Reserved_2,
465 /// \brief Source[4] in Fortran, do not use for C++
466 IdentField_Reserved_3,
467 /// \brief String describing the source location. The string is composed of
468 /// semi-colon separated fields which describe the source file, the function
469 /// and a pair of line numbers that delimit the construct.
470 IdentField_PSource
471};
472
473/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
474/// the enum sched_type in kmp.h).
475enum OpenMPSchedType {
476 /// \brief Lower bound for default (unordered) versions.
477 OMP_sch_lower = 32,
478 OMP_sch_static_chunked = 33,
479 OMP_sch_static = 34,
480 OMP_sch_dynamic_chunked = 35,
481 OMP_sch_guided_chunked = 36,
482 OMP_sch_runtime = 37,
483 OMP_sch_auto = 38,
484 /// \brief Lower bound for 'ordered' versions.
485 OMP_ord_lower = 64,
486 OMP_ord_static_chunked = 65,
487 OMP_ord_static = 66,
488 OMP_ord_dynamic_chunked = 67,
489 OMP_ord_guided_chunked = 68,
490 OMP_ord_runtime = 69,
491 OMP_ord_auto = 70,
492 OMP_sch_default = OMP_sch_static,
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000493 /// \brief dist_schedule types
494 OMP_dist_sch_static_chunked = 91,
495 OMP_dist_sch_static = 92,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000496};
497
498enum OpenMPRTLFunction {
499 /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
500 /// kmpc_micro microtask, ...);
501 OMPRTL__kmpc_fork_call,
502 /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc,
503 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
504 OMPRTL__kmpc_threadprivate_cached,
505 /// \brief Call to void __kmpc_threadprivate_register( ident_t *,
506 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
507 OMPRTL__kmpc_threadprivate_register,
508 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
509 OMPRTL__kmpc_global_thread_num,
510 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
511 // kmp_critical_name *crit);
512 OMPRTL__kmpc_critical,
513 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
514 // global_tid, kmp_critical_name *crit, uintptr_t hint);
515 OMPRTL__kmpc_critical_with_hint,
516 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
517 // kmp_critical_name *crit);
518 OMPRTL__kmpc_end_critical,
519 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
520 // global_tid);
521 OMPRTL__kmpc_cancel_barrier,
522 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
523 OMPRTL__kmpc_barrier,
524 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
525 OMPRTL__kmpc_for_static_fini,
526 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
527 // global_tid);
528 OMPRTL__kmpc_serialized_parallel,
529 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
530 // global_tid);
531 OMPRTL__kmpc_end_serialized_parallel,
532 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
533 // kmp_int32 num_threads);
534 OMPRTL__kmpc_push_num_threads,
535 // Call to void __kmpc_flush(ident_t *loc);
536 OMPRTL__kmpc_flush,
537 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
538 OMPRTL__kmpc_master,
539 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
540 OMPRTL__kmpc_end_master,
541 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
542 // int end_part);
543 OMPRTL__kmpc_omp_taskyield,
544 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
545 OMPRTL__kmpc_single,
546 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
547 OMPRTL__kmpc_end_single,
548 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
549 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
550 // kmp_routine_entry_t *task_entry);
551 OMPRTL__kmpc_omp_task_alloc,
552 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
553 // new_task);
554 OMPRTL__kmpc_omp_task,
555 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
556 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
557 // kmp_int32 didit);
558 OMPRTL__kmpc_copyprivate,
559 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
560 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
561 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
562 OMPRTL__kmpc_reduce,
563 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
564 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
565 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
566 // *lck);
567 OMPRTL__kmpc_reduce_nowait,
568 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
569 // kmp_critical_name *lck);
570 OMPRTL__kmpc_end_reduce,
571 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
572 // kmp_critical_name *lck);
573 OMPRTL__kmpc_end_reduce_nowait,
574 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
575 // kmp_task_t * new_task);
576 OMPRTL__kmpc_omp_task_begin_if0,
577 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
578 // kmp_task_t * new_task);
579 OMPRTL__kmpc_omp_task_complete_if0,
580 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
581 OMPRTL__kmpc_ordered,
582 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
583 OMPRTL__kmpc_end_ordered,
584 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
585 // global_tid);
586 OMPRTL__kmpc_omp_taskwait,
587 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
588 OMPRTL__kmpc_taskgroup,
589 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
590 OMPRTL__kmpc_end_taskgroup,
591 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
592 // int proc_bind);
593 OMPRTL__kmpc_push_proc_bind,
594 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
595 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
596 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
597 OMPRTL__kmpc_omp_task_with_deps,
598 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
599 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
600 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
601 OMPRTL__kmpc_omp_wait_deps,
602 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
603 // global_tid, kmp_int32 cncl_kind);
604 OMPRTL__kmpc_cancellationpoint,
605 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
606 // kmp_int32 cncl_kind);
607 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000608 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
609 // kmp_int32 num_teams, kmp_int32 thread_limit);
610 OMPRTL__kmpc_push_num_teams,
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 Bataev48591dd2016-04-20 04:01:36 +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 Bataev48591dd2016-04-20 04:01:36 +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 Bataev48591dd2016-04-20 04:01:36 +0000850 auto *Res = CGF.GenerateCapturedStmtFunction(*CS);
851 if (!Tied)
852 NumberOfParts = Action.getNumberOfParts();
853 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000854}
855
Alexey Bataev50b3c952016-02-19 10:38:26 +0000856Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
John McCall7f416cc2015-09-08 08:05:57 +0000857 CharUnits Align = getIdentAlign(CGM);
Alexey Bataev15007ba2014-05-07 06:18:01 +0000858 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000859 if (!Entry) {
860 if (!DefaultOpenMPPSource) {
861 // Initialize default location for psource field of ident_t structure of
862 // all ident_t objects. Format is ";file;function;line;column;;".
863 // Taken from
864 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
865 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +0000866 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000867 DefaultOpenMPPSource =
868 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
869 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000870 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
871 CGM.getModule(), IdentTy, /*isConstant*/ true,
872 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000873 DefaultOpenMPLocation->setUnnamedAddr(true);
John McCall7f416cc2015-09-08 08:05:57 +0000874 DefaultOpenMPLocation->setAlignment(Align.getQuantity());
Alexey Bataev9959db52014-05-06 10:08:46 +0000875
876 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000877 llvm::Constant *Values[] = {Zero,
878 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
879 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000880 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
881 DefaultOpenMPLocation->setInitializer(Init);
John McCall7f416cc2015-09-08 08:05:57 +0000882 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000883 }
John McCall7f416cc2015-09-08 08:05:57 +0000884 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +0000885}
886
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000887llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
888 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000889 unsigned Flags) {
890 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +0000891 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +0000892 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +0000893 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +0000894 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000895
896 assert(CGF.CurFn && "No function in current CodeGenFunction.");
897
John McCall7f416cc2015-09-08 08:05:57 +0000898 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000899 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
900 if (I != OpenMPLocThreadIDMap.end())
John McCall7f416cc2015-09-08 08:05:57 +0000901 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
902
Alexander Musmanc6388682014-12-15 07:07:06 +0000903 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
904 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +0000905 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000906 // Generate "ident_t .kmpc_loc.addr;"
John McCall7f416cc2015-09-08 08:05:57 +0000907 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
908 ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +0000909 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +0000910 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000911 LocValue = AI;
912
913 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
914 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000915 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
John McCall7f416cc2015-09-08 08:05:57 +0000916 CGM.getSize(getIdentSize(CGF.CGM)));
Alexey Bataev9959db52014-05-06 10:08:46 +0000917 }
918
919 // char **psource = &.kmpc_loc_<flags>.addr.psource;
John McCall7f416cc2015-09-08 08:05:57 +0000920 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000921
Alexey Bataevf002aca2014-05-30 05:48:40 +0000922 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
923 if (OMPDebugLoc == nullptr) {
924 SmallString<128> Buffer2;
925 llvm::raw_svector_ostream OS2(Buffer2);
926 // Build debug location
927 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
928 OS2 << ";" << PLoc.getFilename() << ";";
929 if (const FunctionDecl *FD =
930 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
931 OS2 << FD->getQualifiedNameAsString();
932 }
933 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
934 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
935 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000936 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000937 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000938 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
939
John McCall7f416cc2015-09-08 08:05:57 +0000940 // Our callers always pass this to a runtime function, so for
941 // convenience, go ahead and return a naked pointer.
942 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000943}
944
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000945llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
946 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000947 assert(CGF.CurFn && "No function in current CodeGenFunction.");
948
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000949 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000950 // Check whether we've already cached a load of the thread id in this
951 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000952 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000953 if (I != OpenMPLocThreadIDMap.end()) {
954 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000955 if (ThreadID != nullptr)
956 return ThreadID;
957 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +0000958 if (auto *OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000959 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000960 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000961 // Check if this an outlined function with thread id passed as argument.
962 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000963 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
964 // If value loaded in entry block, cache it and use it everywhere in
965 // function.
966 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
967 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
968 Elem.second.ThreadID = ThreadID;
969 }
970 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000971 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000972 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000973
974 // This is not an outlined function region - need to call __kmpc_int32
975 // kmpc_global_thread_num(ident_t *loc).
976 // Generate thread id value and cache this value for use across the
977 // function.
978 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
979 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
980 ThreadID =
981 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
982 emitUpdateLocation(CGF, Loc));
983 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
984 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000985 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000986}
987
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000988void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000989 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000990 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
991 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000992 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
993 for(auto *D : FunctionUDRMap[CGF.CurFn]) {
994 UDRMap.erase(D);
995 }
996 FunctionUDRMap.erase(CGF.CurFn);
997 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000998}
999
1000llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001001 if (!IdentTy) {
1002 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001003 return llvm::PointerType::getUnqual(IdentTy);
1004}
1005
1006llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001007 if (!Kmpc_MicroTy) {
1008 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1009 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1010 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1011 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1012 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001013 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1014}
1015
1016llvm::Constant *
Alexey Bataev50b3c952016-02-19 10:38:26 +00001017CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001018 llvm::Constant *RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001019 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001020 case OMPRTL__kmpc_fork_call: {
1021 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1022 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001023 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1024 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +00001025 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001026 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001027 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
1028 break;
1029 }
1030 case OMPRTL__kmpc_global_thread_num: {
1031 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001032 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +00001033 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001034 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001035 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1036 break;
1037 }
Alexey Bataev97720002014-11-11 04:05:39 +00001038 case OMPRTL__kmpc_threadprivate_cached: {
1039 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1040 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1041 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1042 CGM.VoidPtrTy, CGM.SizeTy,
1043 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
1044 llvm::FunctionType *FnTy =
1045 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1046 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1047 break;
1048 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001049 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001050 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1051 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001052 llvm::Type *TypeParams[] = {
1053 getIdentTyPointerTy(), CGM.Int32Ty,
1054 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1055 llvm::FunctionType *FnTy =
1056 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1057 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1058 break;
1059 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001060 case OMPRTL__kmpc_critical_with_hint: {
1061 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1062 // kmp_critical_name *crit, uintptr_t hint);
1063 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1064 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1065 CGM.IntPtrTy};
1066 llvm::FunctionType *FnTy =
1067 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1068 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1069 break;
1070 }
Alexey Bataev97720002014-11-11 04:05:39 +00001071 case OMPRTL__kmpc_threadprivate_register: {
1072 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1073 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1074 // typedef void *(*kmpc_ctor)(void *);
1075 auto KmpcCtorTy =
1076 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1077 /*isVarArg*/ false)->getPointerTo();
1078 // typedef void *(*kmpc_cctor)(void *, void *);
1079 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1080 auto KmpcCopyCtorTy =
1081 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
1082 /*isVarArg*/ false)->getPointerTo();
1083 // typedef void (*kmpc_dtor)(void *);
1084 auto KmpcDtorTy =
1085 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1086 ->getPointerTo();
1087 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1088 KmpcCopyCtorTy, KmpcDtorTy};
1089 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
1090 /*isVarArg*/ false);
1091 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1092 break;
1093 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001094 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001095 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1096 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001097 llvm::Type *TypeParams[] = {
1098 getIdentTyPointerTy(), CGM.Int32Ty,
1099 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1100 llvm::FunctionType *FnTy =
1101 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1102 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1103 break;
1104 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001105 case OMPRTL__kmpc_cancel_barrier: {
1106 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1107 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001108 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1109 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001110 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1111 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001112 break;
1113 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001114 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001115 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001116 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1117 llvm::FunctionType *FnTy =
1118 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1119 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1120 break;
1121 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001122 case OMPRTL__kmpc_for_static_fini: {
1123 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1124 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1125 llvm::FunctionType *FnTy =
1126 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1127 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1128 break;
1129 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001130 case OMPRTL__kmpc_push_num_threads: {
1131 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1132 // kmp_int32 num_threads)
1133 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1134 CGM.Int32Ty};
1135 llvm::FunctionType *FnTy =
1136 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1137 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1138 break;
1139 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001140 case OMPRTL__kmpc_serialized_parallel: {
1141 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1142 // global_tid);
1143 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1144 llvm::FunctionType *FnTy =
1145 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1146 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1147 break;
1148 }
1149 case OMPRTL__kmpc_end_serialized_parallel: {
1150 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1151 // global_tid);
1152 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1153 llvm::FunctionType *FnTy =
1154 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1155 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1156 break;
1157 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001158 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001159 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001160 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
1161 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001162 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001163 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1164 break;
1165 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001166 case OMPRTL__kmpc_master: {
1167 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1168 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1169 llvm::FunctionType *FnTy =
1170 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1171 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1172 break;
1173 }
1174 case OMPRTL__kmpc_end_master: {
1175 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1176 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1177 llvm::FunctionType *FnTy =
1178 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1179 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1180 break;
1181 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001182 case OMPRTL__kmpc_omp_taskyield: {
1183 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1184 // int end_part);
1185 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1186 llvm::FunctionType *FnTy =
1187 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1188 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1189 break;
1190 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001191 case OMPRTL__kmpc_single: {
1192 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1193 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1194 llvm::FunctionType *FnTy =
1195 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1196 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1197 break;
1198 }
1199 case OMPRTL__kmpc_end_single: {
1200 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1201 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1202 llvm::FunctionType *FnTy =
1203 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1204 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1205 break;
1206 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001207 case OMPRTL__kmpc_omp_task_alloc: {
1208 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1209 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1210 // kmp_routine_entry_t *task_entry);
1211 assert(KmpRoutineEntryPtrTy != nullptr &&
1212 "Type kmp_routine_entry_t must be created.");
1213 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1214 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1215 // Return void * and then cast to particular kmp_task_t type.
1216 llvm::FunctionType *FnTy =
1217 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1218 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1219 break;
1220 }
1221 case OMPRTL__kmpc_omp_task: {
1222 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1223 // *new_task);
1224 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1225 CGM.VoidPtrTy};
1226 llvm::FunctionType *FnTy =
1227 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1228 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
1229 break;
1230 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001231 case OMPRTL__kmpc_copyprivate: {
1232 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00001233 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001234 // kmp_int32 didit);
1235 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1236 auto *CpyFnTy =
1237 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001238 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001239 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
1240 CGM.Int32Ty};
1241 llvm::FunctionType *FnTy =
1242 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1243 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
1244 break;
1245 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001246 case OMPRTL__kmpc_reduce: {
1247 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
1248 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
1249 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
1250 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1251 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1252 /*isVarArg=*/false);
1253 llvm::Type *TypeParams[] = {
1254 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1255 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1256 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1257 llvm::FunctionType *FnTy =
1258 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1259 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
1260 break;
1261 }
1262 case OMPRTL__kmpc_reduce_nowait: {
1263 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
1264 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
1265 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
1266 // *lck);
1267 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1268 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1269 /*isVarArg=*/false);
1270 llvm::Type *TypeParams[] = {
1271 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1272 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1273 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1274 llvm::FunctionType *FnTy =
1275 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1276 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
1277 break;
1278 }
1279 case OMPRTL__kmpc_end_reduce: {
1280 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
1281 // kmp_critical_name *lck);
1282 llvm::Type *TypeParams[] = {
1283 getIdentTyPointerTy(), CGM.Int32Ty,
1284 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1285 llvm::FunctionType *FnTy =
1286 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1287 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
1288 break;
1289 }
1290 case OMPRTL__kmpc_end_reduce_nowait: {
1291 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
1292 // kmp_critical_name *lck);
1293 llvm::Type *TypeParams[] = {
1294 getIdentTyPointerTy(), CGM.Int32Ty,
1295 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1296 llvm::FunctionType *FnTy =
1297 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1298 RTLFn =
1299 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
1300 break;
1301 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001302 case OMPRTL__kmpc_omp_task_begin_if0: {
1303 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1304 // *new_task);
1305 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1306 CGM.VoidPtrTy};
1307 llvm::FunctionType *FnTy =
1308 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1309 RTLFn =
1310 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
1311 break;
1312 }
1313 case OMPRTL__kmpc_omp_task_complete_if0: {
1314 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1315 // *new_task);
1316 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1317 CGM.VoidPtrTy};
1318 llvm::FunctionType *FnTy =
1319 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1320 RTLFn = CGM.CreateRuntimeFunction(FnTy,
1321 /*Name=*/"__kmpc_omp_task_complete_if0");
1322 break;
1323 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001324 case OMPRTL__kmpc_ordered: {
1325 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
1326 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1327 llvm::FunctionType *FnTy =
1328 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1329 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
1330 break;
1331 }
1332 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001333 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001334 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1335 llvm::FunctionType *FnTy =
1336 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1337 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
1338 break;
1339 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00001340 case OMPRTL__kmpc_omp_taskwait: {
1341 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
1342 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1343 llvm::FunctionType *FnTy =
1344 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1345 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
1346 break;
1347 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001348 case OMPRTL__kmpc_taskgroup: {
1349 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
1350 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1351 llvm::FunctionType *FnTy =
1352 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1353 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
1354 break;
1355 }
1356 case OMPRTL__kmpc_end_taskgroup: {
1357 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
1358 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1359 llvm::FunctionType *FnTy =
1360 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1361 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
1362 break;
1363 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00001364 case OMPRTL__kmpc_push_proc_bind: {
1365 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
1366 // int proc_bind)
1367 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1368 llvm::FunctionType *FnTy =
1369 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1370 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
1371 break;
1372 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00001373 case OMPRTL__kmpc_omp_task_with_deps: {
1374 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
1375 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
1376 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
1377 llvm::Type *TypeParams[] = {
1378 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
1379 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
1380 llvm::FunctionType *FnTy =
1381 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1382 RTLFn =
1383 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
1384 break;
1385 }
1386 case OMPRTL__kmpc_omp_wait_deps: {
1387 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
1388 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
1389 // kmp_depend_info_t *noalias_dep_list);
1390 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1391 CGM.Int32Ty, CGM.VoidPtrTy,
1392 CGM.Int32Ty, CGM.VoidPtrTy};
1393 llvm::FunctionType *FnTy =
1394 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1395 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
1396 break;
1397 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00001398 case OMPRTL__kmpc_cancellationpoint: {
1399 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
1400 // global_tid, kmp_int32 cncl_kind)
1401 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1402 llvm::FunctionType *FnTy =
1403 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1404 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
1405 break;
1406 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001407 case OMPRTL__kmpc_cancel: {
1408 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
1409 // kmp_int32 cncl_kind)
1410 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1411 llvm::FunctionType *FnTy =
1412 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1413 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
1414 break;
1415 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00001416 case OMPRTL__kmpc_push_num_teams: {
1417 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
1418 // kmp_int32 num_teams, kmp_int32 num_threads)
1419 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1420 CGM.Int32Ty};
1421 llvm::FunctionType *FnTy =
1422 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1423 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
1424 break;
1425 }
1426 case OMPRTL__kmpc_fork_teams: {
1427 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
1428 // microtask, ...);
1429 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1430 getKmpc_MicroPointerTy()};
1431 llvm::FunctionType *FnTy =
1432 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
1433 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
1434 break;
1435 }
Samuel Antaobed3c462015-10-02 16:14:20 +00001436 case OMPRTL__tgt_target: {
1437 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
1438 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
1439 // *arg_types);
1440 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1441 CGM.VoidPtrTy,
1442 CGM.Int32Ty,
1443 CGM.VoidPtrPtrTy,
1444 CGM.VoidPtrPtrTy,
1445 CGM.SizeTy->getPointerTo(),
1446 CGM.Int32Ty->getPointerTo()};
1447 llvm::FunctionType *FnTy =
1448 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1449 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
1450 break;
1451 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00001452 case OMPRTL__tgt_target_teams: {
1453 // Build int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
1454 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
1455 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
1456 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1457 CGM.VoidPtrTy,
1458 CGM.Int32Ty,
1459 CGM.VoidPtrPtrTy,
1460 CGM.VoidPtrPtrTy,
1461 CGM.SizeTy->getPointerTo(),
1462 CGM.Int32Ty->getPointerTo(),
1463 CGM.Int32Ty,
1464 CGM.Int32Ty};
1465 llvm::FunctionType *FnTy =
1466 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1467 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
1468 break;
1469 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00001470 case OMPRTL__tgt_register_lib: {
1471 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
1472 QualType ParamTy =
1473 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1474 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1475 llvm::FunctionType *FnTy =
1476 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1477 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
1478 break;
1479 }
1480 case OMPRTL__tgt_unregister_lib: {
1481 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
1482 QualType ParamTy =
1483 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1484 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1485 llvm::FunctionType *FnTy =
1486 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1487 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
1488 break;
1489 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001490 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00001491 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00001492 return RTLFn;
1493}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001494
Alexander Musman21212e42015-03-13 10:38:23 +00001495llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
1496 bool IVSigned) {
1497 assert((IVSize == 32 || IVSize == 64) &&
1498 "IV size is not compatible with the omp runtime");
1499 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
1500 : "__kmpc_for_static_init_4u")
1501 : (IVSigned ? "__kmpc_for_static_init_8"
1502 : "__kmpc_for_static_init_8u");
1503 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1504 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1505 llvm::Type *TypeParams[] = {
1506 getIdentTyPointerTy(), // loc
1507 CGM.Int32Ty, // tid
1508 CGM.Int32Ty, // schedtype
1509 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1510 PtrTy, // p_lower
1511 PtrTy, // p_upper
1512 PtrTy, // p_stride
1513 ITy, // incr
1514 ITy // chunk
1515 };
1516 llvm::FunctionType *FnTy =
1517 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1518 return CGM.CreateRuntimeFunction(FnTy, Name);
1519}
1520
Alexander Musman92bdaab2015-03-12 13:37:50 +00001521llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
1522 bool IVSigned) {
1523 assert((IVSize == 32 || IVSize == 64) &&
1524 "IV size is not compatible with the omp runtime");
1525 auto Name =
1526 IVSize == 32
1527 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
1528 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
1529 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1530 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
1531 CGM.Int32Ty, // tid
1532 CGM.Int32Ty, // schedtype
1533 ITy, // lower
1534 ITy, // upper
1535 ITy, // stride
1536 ITy // chunk
1537 };
1538 llvm::FunctionType *FnTy =
1539 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1540 return CGM.CreateRuntimeFunction(FnTy, Name);
1541}
1542
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001543llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
1544 bool IVSigned) {
1545 assert((IVSize == 32 || IVSize == 64) &&
1546 "IV size is not compatible with the omp runtime");
1547 auto Name =
1548 IVSize == 32
1549 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1550 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1551 llvm::Type *TypeParams[] = {
1552 getIdentTyPointerTy(), // loc
1553 CGM.Int32Ty, // tid
1554 };
1555 llvm::FunctionType *FnTy =
1556 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1557 return CGM.CreateRuntimeFunction(FnTy, Name);
1558}
1559
Alexander Musman92bdaab2015-03-12 13:37:50 +00001560llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
1561 bool IVSigned) {
1562 assert((IVSize == 32 || IVSize == 64) &&
1563 "IV size is not compatible with the omp runtime");
1564 auto Name =
1565 IVSize == 32
1566 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1567 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1568 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1569 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1570 llvm::Type *TypeParams[] = {
1571 getIdentTyPointerTy(), // loc
1572 CGM.Int32Ty, // tid
1573 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1574 PtrTy, // p_lower
1575 PtrTy, // p_upper
1576 PtrTy // p_stride
1577 };
1578 llvm::FunctionType *FnTy =
1579 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1580 return CGM.CreateRuntimeFunction(FnTy, Name);
1581}
1582
Alexey Bataev97720002014-11-11 04:05:39 +00001583llvm::Constant *
1584CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001585 assert(!CGM.getLangOpts().OpenMPUseTLS ||
1586 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00001587 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001588 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001589 Twine(CGM.getMangledName(VD)) + ".cache.");
1590}
1591
John McCall7f416cc2015-09-08 08:05:57 +00001592Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1593 const VarDecl *VD,
1594 Address VDAddr,
1595 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001596 if (CGM.getLangOpts().OpenMPUseTLS &&
1597 CGM.getContext().getTargetInfo().isTLSSupported())
1598 return VDAddr;
1599
John McCall7f416cc2015-09-08 08:05:57 +00001600 auto VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001601 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001602 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1603 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001604 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1605 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00001606 return Address(CGF.EmitRuntimeCall(
1607 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
1608 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00001609}
1610
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001611void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00001612 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00001613 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1614 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1615 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001616 auto OMPLoc = emitUpdateLocation(CGF, Loc);
1617 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00001618 OMPLoc);
1619 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1620 // to register constructor/destructor for variable.
1621 llvm::Value *Args[] = {OMPLoc,
John McCall7f416cc2015-09-08 08:05:57 +00001622 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1623 CGM.VoidPtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001624 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001625 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001626 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001627}
1628
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001629llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00001630 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00001631 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001632 if (CGM.getLangOpts().OpenMPUseTLS &&
1633 CGM.getContext().getTargetInfo().isTLSSupported())
1634 return nullptr;
1635
Alexey Bataev97720002014-11-11 04:05:39 +00001636 VD = VD->getDefinition(CGM.getContext());
1637 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
1638 ThreadPrivateWithDefinition.insert(VD);
1639 QualType ASTTy = VD->getType();
1640
1641 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1642 auto Init = VD->getAnyInitializer();
1643 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1644 // Generate function that re-emits the declaration's initializer into the
1645 // threadprivate copy of the variable VD
1646 CodeGenFunction CtorCGF(CGM);
1647 FunctionArgList Args;
1648 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1649 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1650 Args.push_back(&Dst);
1651
John McCallc56a8b32016-03-11 04:30:31 +00001652 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1653 CGM.getContext().VoidPtrTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001654 auto FTy = CGM.getTypes().GetFunctionType(FI);
1655 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001656 FTy, ".__kmpc_global_ctor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001657 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1658 Args, SourceLocation());
1659 auto ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001660 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001661 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00001662 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1663 Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
1664 CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00001665 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1666 /*IsInitializer=*/true);
1667 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001668 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001669 CGM.getContext().VoidPtrTy, Dst.getLocation());
1670 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1671 CtorCGF.FinishFunction();
1672 Ctor = Fn;
1673 }
1674 if (VD->getType().isDestructedType() != QualType::DK_none) {
1675 // Generate function that emits destructor call for the threadprivate copy
1676 // of the variable VD
1677 CodeGenFunction DtorCGF(CGM);
1678 FunctionArgList Args;
1679 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1680 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1681 Args.push_back(&Dst);
1682
John McCallc56a8b32016-03-11 04:30:31 +00001683 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1684 CGM.getContext().VoidTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001685 auto FTy = CGM.getTypes().GetFunctionType(FI);
1686 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001687 FTy, ".__kmpc_global_dtor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001688 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1689 SourceLocation());
1690 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1691 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00001692 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1693 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001694 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1695 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1696 DtorCGF.FinishFunction();
1697 Dtor = Fn;
1698 }
1699 // Do not emit init function if it is not required.
1700 if (!Ctor && !Dtor)
1701 return nullptr;
1702
1703 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1704 auto CopyCtorTy =
1705 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1706 /*isVarArg=*/false)->getPointerTo();
1707 // Copying constructor for the threadprivate variable.
1708 // Must be NULL - reserved by runtime, but currently it requires that this
1709 // parameter is always NULL. Otherwise it fires assertion.
1710 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1711 if (Ctor == nullptr) {
1712 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1713 /*isVarArg=*/false)->getPointerTo();
1714 Ctor = llvm::Constant::getNullValue(CtorTy);
1715 }
1716 if (Dtor == nullptr) {
1717 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1718 /*isVarArg=*/false)->getPointerTo();
1719 Dtor = llvm::Constant::getNullValue(DtorTy);
1720 }
1721 if (!CGF) {
1722 auto InitFunctionTy =
1723 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1724 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001725 InitFunctionTy, ".__omp_threadprivate_init_.",
1726 CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00001727 CodeGenFunction InitCGF(CGM);
1728 FunctionArgList ArgList;
1729 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1730 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1731 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001732 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001733 InitCGF.FinishFunction();
1734 return InitFunction;
1735 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001736 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001737 }
1738 return nullptr;
1739}
1740
Alexey Bataev1d677132015-04-22 13:57:31 +00001741/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1742/// function. Here is the logic:
1743/// if (Cond) {
1744/// ThenGen();
1745/// } else {
1746/// ElseGen();
1747/// }
1748static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1749 const RegionCodeGenTy &ThenGen,
1750 const RegionCodeGenTy &ElseGen) {
1751 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1752
1753 // If the condition constant folds and can be elided, try to avoid emitting
1754 // the condition and the dead arm of the if/else.
1755 bool CondConstant;
1756 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001757 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00001758 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001759 else
Alexey Bataev1d677132015-04-22 13:57:31 +00001760 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001761 return;
1762 }
1763
1764 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1765 // emit the conditional branch.
1766 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1767 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1768 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1769 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1770
1771 // Emit the 'then' code.
1772 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001773 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001774 CGF.EmitBranch(ContBlock);
1775 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001776 // There is no need to emit line number for unconditional branch.
1777 (void)ApplyDebugLocation::CreateEmpty(CGF);
1778 CGF.EmitBlock(ElseBlock);
1779 ElseGen(CGF);
1780 // There is no need to emit line number for unconditional branch.
1781 (void)ApplyDebugLocation::CreateEmpty(CGF);
1782 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00001783 // Emit the continuation block for code after the if.
1784 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001785}
1786
Alexey Bataev1d677132015-04-22 13:57:31 +00001787void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1788 llvm::Value *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001789 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00001790 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001791 if (!CGF.HaveInsertPoint())
1792 return;
Alexey Bataev1d677132015-04-22 13:57:31 +00001793 auto *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001794 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
1795 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001796 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001797 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00001798 llvm::Value *Args[] = {
1799 RTLoc,
1800 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001801 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00001802 llvm::SmallVector<llvm::Value *, 16> RealArgs;
1803 RealArgs.append(std::begin(Args), std::end(Args));
1804 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1805
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001806 auto RTLFn = RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001807 CGF.EmitRuntimeCall(RTLFn, RealArgs);
1808 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001809 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
1810 PrePostActionTy &) {
1811 auto &RT = CGF.CGM.getOpenMPRuntime();
1812 auto ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00001813 // Build calls:
1814 // __kmpc_serialized_parallel(&Loc, GTid);
1815 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001816 CGF.EmitRuntimeCall(
1817 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001818
Alexey Bataev1d677132015-04-22 13:57:31 +00001819 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001820 auto ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00001821 Address ZeroAddr =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001822 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
1823 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00001824 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00001825 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
1826 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
1827 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1828 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev1d677132015-04-22 13:57:31 +00001829 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001830
Alexey Bataev1d677132015-04-22 13:57:31 +00001831 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001832 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00001833 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001834 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
1835 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00001836 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001837 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00001838 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001839 else {
1840 RegionCodeGenTy ThenRCG(ThenGen);
1841 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00001842 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001843}
1844
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001845// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001846// thread-ID variable (it is passed in a first argument of the outlined function
1847// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1848// regular serial code region, get thread ID by calling kmp_int32
1849// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1850// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00001851Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
1852 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00001853 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001854 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001855 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001856 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001857
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001858 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001859 auto Int32Ty =
1860 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1861 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1862 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00001863 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00001864
1865 return ThreadIDTemp;
1866}
1867
Alexey Bataev97720002014-11-11 04:05:39 +00001868llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001869CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001870 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001871 SmallString<256> Buffer;
1872 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001873 Out << Name;
1874 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001875 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1876 if (Elem.second) {
1877 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001878 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001879 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001880 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001881
David Blaikie13156b62014-11-19 03:06:06 +00001882 return Elem.second = new llvm::GlobalVariable(
1883 CGM.getModule(), Ty, /*IsConstant*/ false,
1884 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1885 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001886}
1887
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001888llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001889 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001890 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001891}
1892
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001893namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001894/// Common pre(post)-action for different OpenMP constructs.
1895class CommonActionTy final : public PrePostActionTy {
1896 llvm::Value *EnterCallee;
1897 ArrayRef<llvm::Value *> EnterArgs;
1898 llvm::Value *ExitCallee;
1899 ArrayRef<llvm::Value *> ExitArgs;
1900 bool Conditional;
1901 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001902
1903public:
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001904 CommonActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs,
1905 llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs,
1906 bool Conditional = false)
1907 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1908 ExitArgs(ExitArgs), Conditional(Conditional) {}
1909 void Enter(CodeGenFunction &CGF) override {
1910 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
1911 if (Conditional) {
1912 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
1913 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1914 ContBlock = CGF.createBasicBlock("omp_if.end");
1915 // Generate the branch (If-stmt)
1916 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1917 CGF.EmitBlock(ThenBlock);
1918 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00001919 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001920 void Done(CodeGenFunction &CGF) {
1921 // Emit the rest of blocks/branches
1922 CGF.EmitBranch(ContBlock);
1923 CGF.EmitBlock(ContBlock, true);
1924 }
1925 void Exit(CodeGenFunction &CGF) override {
1926 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001927 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001928};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001929} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001930
1931void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1932 StringRef CriticalName,
1933 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00001934 SourceLocation Loc, const Expr *Hint) {
1935 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001936 // CriticalOpGen();
1937 // __kmpc_end_critical(ident_t *, gtid, Lock);
1938 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00001939 if (!CGF.HaveInsertPoint())
1940 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00001941 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1942 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001943 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
1944 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00001945 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001946 EnterArgs.push_back(CGF.Builder.CreateIntCast(
1947 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
1948 }
1949 CommonActionTy Action(
1950 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
1951 : OMPRTL__kmpc_critical),
1952 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
1953 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00001954 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001955}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001956
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001957void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001958 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001959 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001960 if (!CGF.HaveInsertPoint())
1961 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00001962 // if(__kmpc_master(ident_t *, gtid)) {
1963 // MasterOpGen();
1964 // __kmpc_end_master(ident_t *, gtid);
1965 // }
1966 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001967 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001968 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
1969 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
1970 /*Conditional=*/true);
1971 MasterOpGen.setAction(Action);
1972 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
1973 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00001974}
1975
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001976void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
1977 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001978 if (!CGF.HaveInsertPoint())
1979 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00001980 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
1981 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001982 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00001983 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001984 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00001985 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
1986 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00001987}
1988
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001989void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
1990 const RegionCodeGenTy &TaskgroupOpGen,
1991 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001992 if (!CGF.HaveInsertPoint())
1993 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001994 // __kmpc_taskgroup(ident_t *, gtid);
1995 // TaskgroupOpGen();
1996 // __kmpc_end_taskgroup(ident_t *, gtid);
1997 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001998 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
1999 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
2000 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
2001 Args);
2002 TaskgroupOpGen.setAction(Action);
2003 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002004}
2005
John McCall7f416cc2015-09-08 08:05:57 +00002006/// Given an array of pointers to variables, project the address of a
2007/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002008static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
2009 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00002010 // Pull out the pointer to the variable.
2011 Address PtrAddr =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002012 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00002013 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
2014
2015 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002016 Addr = CGF.Builder.CreateElementBitCast(
2017 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00002018 return Addr;
2019}
2020
Alexey Bataeva63048e2015-03-23 06:18:07 +00002021static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00002022 CodeGenModule &CGM, llvm::Type *ArgsType,
2023 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
2024 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002025 auto &C = CGM.getContext();
2026 // void copy_func(void *LHSArg, void *RHSArg);
2027 FunctionArgList Args;
2028 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2029 C.VoidPtrTy);
2030 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2031 C.VoidPtrTy);
2032 Args.push_back(&LHSArg);
2033 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00002034 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002035 auto *Fn = llvm::Function::Create(
2036 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
2037 ".omp.copyprivate.copy_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002038 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002039 CodeGenFunction CGF(CGM);
2040 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00002041 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002042 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00002043 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2044 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2045 ArgsType), CGF.getPointerAlign());
2046 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2047 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2048 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00002049 // *(Type0*)Dst[0] = *(Type0*)Src[0];
2050 // *(Type1*)Dst[1] = *(Type1*)Src[1];
2051 // ...
2052 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00002053 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002054 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2055 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
2056
2057 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2058 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
2059
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002060 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2061 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00002062 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002063 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002064 CGF.FinishFunction();
2065 return Fn;
2066}
2067
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002068void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002069 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002070 SourceLocation Loc,
2071 ArrayRef<const Expr *> CopyprivateVars,
2072 ArrayRef<const Expr *> SrcExprs,
2073 ArrayRef<const Expr *> DstExprs,
2074 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002075 if (!CGF.HaveInsertPoint())
2076 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00002077 assert(CopyprivateVars.size() == SrcExprs.size() &&
2078 CopyprivateVars.size() == DstExprs.size() &&
2079 CopyprivateVars.size() == AssignmentOps.size());
2080 auto &C = CGM.getContext();
2081 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002082 // if(__kmpc_single(ident_t *, gtid)) {
2083 // SingleOpGen();
2084 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002085 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002086 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002087 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2088 // <copy_func>, did_it);
2089
John McCall7f416cc2015-09-08 08:05:57 +00002090 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00002091 if (!CopyprivateVars.empty()) {
2092 // int32 did_it = 0;
2093 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2094 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00002095 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002096 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002097 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00002098 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002099 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
2100 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
2101 /*Conditional=*/true);
2102 SingleOpGen.setAction(Action);
2103 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
2104 if (DidIt.isValid()) {
2105 // did_it = 1;
2106 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
2107 }
2108 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002109 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2110 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00002111 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002112 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
2113 auto CopyprivateArrayTy =
2114 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2115 /*IndexTypeQuals=*/0);
2116 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00002117 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002118 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
2119 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002120 Address Elem = CGF.Builder.CreateConstArrayGEP(
2121 CopyprivateList, I, CGF.getPointerSize());
2122 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00002123 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002124 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
2125 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002126 }
2127 // Build function that copies private values from single region to all other
2128 // threads in the corresponding parallel region.
2129 auto *CpyFn = emitCopyprivateCopyFunction(
2130 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00002131 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataev1189bd02016-01-26 12:20:39 +00002132 auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00002133 Address CL =
2134 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
2135 CGF.VoidPtrTy);
2136 auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002137 llvm::Value *Args[] = {
2138 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
2139 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00002140 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00002141 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00002142 CpyFn, // void (*) (void *, void *) <copy_func>
2143 DidItVal // i32 did_it
2144 };
2145 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
2146 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002147}
2148
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002149void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
2150 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00002151 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002152 if (!CGF.HaveInsertPoint())
2153 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002154 // __kmpc_ordered(ident_t *, gtid);
2155 // OrderedOpGen();
2156 // __kmpc_end_ordered(ident_t *, gtid);
2157 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00002158 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002159 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002160 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
2161 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
2162 Args);
2163 OrderedOpGen.setAction(Action);
2164 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2165 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002166 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00002167 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002168}
2169
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002170void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev25e5b442015-09-15 12:52:43 +00002171 OpenMPDirectiveKind Kind, bool EmitChecks,
2172 bool ForceSimpleCall) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002173 if (!CGF.HaveInsertPoint())
2174 return;
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00002175 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002176 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002177 unsigned Flags;
2178 if (Kind == OMPD_for)
2179 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2180 else if (Kind == OMPD_sections)
2181 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2182 else if (Kind == OMPD_single)
2183 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2184 else if (Kind == OMPD_barrier)
2185 Flags = OMP_IDENT_BARRIER_EXPL;
2186 else
2187 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002188 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
2189 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002190 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
2191 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002192 if (auto *OMPRegionInfo =
2193 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00002194 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002195 auto *Result = CGF.EmitRuntimeCall(
2196 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00002197 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002198 // if (__kmpc_cancel_barrier()) {
2199 // exit from construct;
2200 // }
2201 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
2202 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
2203 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
2204 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2205 CGF.EmitBlock(ExitBB);
2206 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00002207 auto CancelDestination =
2208 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002209 CGF.EmitBranchThroughCleanup(CancelDestination);
2210 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2211 }
2212 return;
2213 }
2214 }
2215 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002216}
2217
Alexander Musmanc6388682014-12-15 07:07:06 +00002218/// \brief Map the OpenMP loop schedule to the runtime enumeration.
2219static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002220 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002221 switch (ScheduleKind) {
2222 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002223 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2224 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00002225 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002226 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002227 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002228 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002229 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002230 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2231 case OMPC_SCHEDULE_auto:
2232 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00002233 case OMPC_SCHEDULE_unknown:
2234 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002235 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00002236 }
2237 llvm_unreachable("Unexpected runtime schedule");
2238}
2239
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002240/// \brief Map the OpenMP distribute schedule to the runtime enumeration.
2241static OpenMPSchedType
2242getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
2243 // only static is allowed for dist_schedule
2244 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2245}
2246
Alexander Musmanc6388682014-12-15 07:07:06 +00002247bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
2248 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002249 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00002250 return Schedule == OMP_sch_static;
2251}
2252
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002253bool CGOpenMPRuntime::isStaticNonchunked(
2254 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2255 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2256 return Schedule == OMP_dist_sch_static;
2257}
2258
2259
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002260bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002261 auto Schedule =
2262 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002263 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
2264 return Schedule != OMP_sch_static;
2265}
2266
John McCall7f416cc2015-09-08 08:05:57 +00002267void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
2268 SourceLocation Loc,
2269 OpenMPScheduleClauseKind ScheduleKind,
2270 unsigned IVSize, bool IVSigned,
2271 bool Ordered, llvm::Value *UB,
2272 llvm::Value *Chunk) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002273 if (!CGF.HaveInsertPoint())
2274 return;
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002275 OpenMPSchedType Schedule =
2276 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00002277 assert(Ordered ||
2278 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2279 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
2280 // Call __kmpc_dispatch_init(
2281 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
2282 // kmp_int[32|64] lower, kmp_int[32|64] upper,
2283 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002284
John McCall7f416cc2015-09-08 08:05:57 +00002285 // If the Chunk was not specified in the clause - use default value 1.
2286 if (Chunk == nullptr)
2287 Chunk = CGF.Builder.getIntN(IVSize, 1);
2288 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002289 emitUpdateLocation(CGF, Loc),
2290 getThreadID(CGF, Loc),
2291 CGF.Builder.getInt32(Schedule), // Schedule type
2292 CGF.Builder.getIntN(IVSize, 0), // Lower
2293 UB, // Upper
2294 CGF.Builder.getIntN(IVSize, 1), // Stride
2295 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00002296 };
2297 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
2298}
2299
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002300static void emitForStaticInitCall(CodeGenFunction &CGF,
2301 SourceLocation Loc,
2302 llvm::Value * UpdateLocation,
2303 llvm::Value * ThreadId,
2304 llvm::Constant * ForStaticInitFunction,
2305 OpenMPSchedType Schedule,
2306 unsigned IVSize, bool IVSigned, bool Ordered,
2307 Address IL, Address LB, Address UB,
2308 Address ST, llvm::Value *Chunk) {
2309 if (!CGF.HaveInsertPoint())
2310 return;
2311
2312 assert(!Ordered);
2313 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2314 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2315 Schedule == OMP_dist_sch_static ||
2316 Schedule == OMP_dist_sch_static_chunked);
2317
2318 // Call __kmpc_for_static_init(
2319 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
2320 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
2321 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
2322 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
2323 if (Chunk == nullptr) {
2324 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2325 Schedule == OMP_dist_sch_static) &&
2326 "expected static non-chunked schedule");
2327 // If the Chunk was not specified in the clause - use default value 1.
2328 Chunk = CGF.Builder.getIntN(IVSize, 1);
2329 } else {
2330 assert((Schedule == OMP_sch_static_chunked ||
2331 Schedule == OMP_ord_static_chunked ||
2332 Schedule == OMP_dist_sch_static_chunked) &&
2333 "expected static chunked schedule");
2334 }
2335 llvm::Value *Args[] = {
2336 UpdateLocation,
2337 ThreadId,
2338 CGF.Builder.getInt32(Schedule), // Schedule type
2339 IL.getPointer(), // &isLastIter
2340 LB.getPointer(), // &LB
2341 UB.getPointer(), // &UB
2342 ST.getPointer(), // &Stride
2343 CGF.Builder.getIntN(IVSize, 1), // Incr
2344 Chunk // Chunk
2345 };
2346 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
2347}
2348
John McCall7f416cc2015-09-08 08:05:57 +00002349void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
2350 SourceLocation Loc,
2351 OpenMPScheduleClauseKind ScheduleKind,
2352 unsigned IVSize, bool IVSigned,
2353 bool Ordered, Address IL, Address LB,
2354 Address UB, Address ST,
2355 llvm::Value *Chunk) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002356 OpenMPSchedType ScheduleNum = getRuntimeSchedule(ScheduleKind, Chunk != nullptr,
2357 Ordered);
2358 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2359 auto *ThreadId = getThreadID(CGF, Loc);
2360 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
2361 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction,
2362 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
2363}
John McCall7f416cc2015-09-08 08:05:57 +00002364
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002365void CGOpenMPRuntime::emitDistributeStaticInit(CodeGenFunction &CGF,
2366 SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind,
2367 unsigned IVSize, bool IVSigned,
2368 bool Ordered, Address IL, Address LB,
2369 Address UB, Address ST,
2370 llvm::Value *Chunk) {
2371 OpenMPSchedType ScheduleNum = getRuntimeSchedule(SchedKind, Chunk != nullptr);
2372 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2373 auto *ThreadId = getThreadID(CGF, Loc);
2374 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
2375 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction,
2376 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002377}
2378
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002379void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
2380 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002381 if (!CGF.HaveInsertPoint())
2382 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00002383 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002384 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002385 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
2386 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00002387}
2388
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002389void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
2390 SourceLocation Loc,
2391 unsigned IVSize,
2392 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002393 if (!CGF.HaveInsertPoint())
2394 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002395 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002396 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002397 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
2398}
2399
Alexander Musman92bdaab2015-03-12 13:37:50 +00002400llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
2401 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00002402 bool IVSigned, Address IL,
2403 Address LB, Address UB,
2404 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002405 // Call __kmpc_dispatch_next(
2406 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2407 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2408 // kmp_int[32|64] *p_stride);
2409 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002410 emitUpdateLocation(CGF, Loc),
2411 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002412 IL.getPointer(), // &isLastIter
2413 LB.getPointer(), // &Lower
2414 UB.getPointer(), // &Upper
2415 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00002416 };
2417 llvm::Value *Call =
2418 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
2419 return CGF.EmitScalarConversion(
2420 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00002421 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002422}
2423
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002424void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
2425 llvm::Value *NumThreads,
2426 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002427 if (!CGF.HaveInsertPoint())
2428 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00002429 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
2430 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002431 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00002432 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002433 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
2434 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00002435}
2436
Alexey Bataev7f210c62015-06-18 13:40:03 +00002437void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
2438 OpenMPProcBindClauseKind ProcBind,
2439 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002440 if (!CGF.HaveInsertPoint())
2441 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00002442 // Constants for proc bind value accepted by the runtime.
2443 enum ProcBindTy {
2444 ProcBindFalse = 0,
2445 ProcBindTrue,
2446 ProcBindMaster,
2447 ProcBindClose,
2448 ProcBindSpread,
2449 ProcBindIntel,
2450 ProcBindDefault
2451 } RuntimeProcBind;
2452 switch (ProcBind) {
2453 case OMPC_PROC_BIND_master:
2454 RuntimeProcBind = ProcBindMaster;
2455 break;
2456 case OMPC_PROC_BIND_close:
2457 RuntimeProcBind = ProcBindClose;
2458 break;
2459 case OMPC_PROC_BIND_spread:
2460 RuntimeProcBind = ProcBindSpread;
2461 break;
2462 case OMPC_PROC_BIND_unknown:
2463 llvm_unreachable("Unsupported proc_bind value.");
2464 }
2465 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
2466 llvm::Value *Args[] = {
2467 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2468 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
2469 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
2470}
2471
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002472void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
2473 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002474 if (!CGF.HaveInsertPoint())
2475 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00002476 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002477 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
2478 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00002479}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002480
Alexey Bataev62b63b12015-03-10 07:28:44 +00002481namespace {
2482/// \brief Indexes of fields for type kmp_task_t.
2483enum KmpTaskTFields {
2484 /// \brief List of shared variables.
2485 KmpTaskTShareds,
2486 /// \brief Task routine.
2487 KmpTaskTRoutine,
2488 /// \brief Partition id for the untied tasks.
2489 KmpTaskTPartId,
2490 /// \brief Function with call of destructors for private variables.
2491 KmpTaskTDestructors,
2492};
Hans Wennborg7eb54642015-09-10 17:07:54 +00002493} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00002494
Samuel Antaoee8fb302016-01-06 13:42:12 +00002495bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
2496 // FIXME: Add other entries type when they become supported.
2497 return OffloadEntriesTargetRegion.empty();
2498}
2499
2500/// \brief Initialize target region entry.
2501void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2502 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2503 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002504 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002505 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
2506 "only required for the device "
2507 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002508 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002509 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr);
2510 ++OffloadingEntriesNum;
2511}
2512
2513void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2514 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2515 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002516 llvm::Constant *Addr, llvm::Constant *ID) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002517 // If we are emitting code for a target, the entry is already initialized,
2518 // only has to be registered.
2519 if (CGM.getLangOpts().OpenMPIsDevice) {
Samuel Antao2de62b02016-02-13 23:35:10 +00002520 assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) &&
Samuel Antaoee8fb302016-01-06 13:42:12 +00002521 "Entry must exist.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002522 auto &Entry =
2523 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00002524 assert(Entry.isValid() && "Entry not initialized!");
2525 Entry.setAddress(Addr);
2526 Entry.setID(ID);
2527 return;
2528 } else {
2529 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID);
Samuel Antao2de62b02016-02-13 23:35:10 +00002530 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002531 }
2532}
2533
2534bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00002535 unsigned DeviceID, unsigned FileID, StringRef ParentName,
2536 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002537 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
2538 if (PerDevice == OffloadEntriesTargetRegion.end())
2539 return false;
2540 auto PerFile = PerDevice->second.find(FileID);
2541 if (PerFile == PerDevice->second.end())
2542 return false;
2543 auto PerParentName = PerFile->second.find(ParentName);
2544 if (PerParentName == PerFile->second.end())
2545 return false;
2546 auto PerLine = PerParentName->second.find(LineNum);
2547 if (PerLine == PerParentName->second.end())
2548 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002549 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00002550 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00002551 return false;
2552 return true;
2553}
2554
2555void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
2556 const OffloadTargetRegionEntryInfoActTy &Action) {
2557 // Scan all target region entries and perform the provided action.
2558 for (auto &D : OffloadEntriesTargetRegion)
2559 for (auto &F : D.second)
2560 for (auto &P : F.second)
2561 for (auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00002562 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002563}
2564
2565/// \brief Create a Ctor/Dtor-like function whose body is emitted through
2566/// \a Codegen. This is used to emit the two functions that register and
2567/// unregister the descriptor of the current compilation unit.
2568static llvm::Function *
2569createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
2570 const RegionCodeGenTy &Codegen) {
2571 auto &C = CGM.getContext();
2572 FunctionArgList Args;
2573 ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(),
2574 /*Id=*/nullptr, C.VoidPtrTy);
2575 Args.push_back(&DummyPtr);
2576
2577 CodeGenFunction CGF(CGM);
2578 GlobalDecl();
John McCallc56a8b32016-03-11 04:30:31 +00002579 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002580 auto FTy = CGM.getTypes().GetFunctionType(FI);
2581 auto *Fn =
2582 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation());
2583 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation());
2584 Codegen(CGF);
2585 CGF.FinishFunction();
2586 return Fn;
2587}
2588
2589llvm::Function *
2590CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
2591
2592 // If we don't have entries or if we are emitting code for the device, we
2593 // don't need to do anything.
2594 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
2595 return nullptr;
2596
2597 auto &M = CGM.getModule();
2598 auto &C = CGM.getContext();
2599
2600 // Get list of devices we care about
2601 auto &Devices = CGM.getLangOpts().OMPTargetTriples;
2602
2603 // We should be creating an offloading descriptor only if there are devices
2604 // specified.
2605 assert(!Devices.empty() && "No OpenMP offloading devices??");
2606
2607 // Create the external variables that will point to the begin and end of the
2608 // host entries section. These will be defined by the linker.
2609 auto *OffloadEntryTy =
2610 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
2611 llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable(
2612 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002613 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002614 ".omp_offloading.entries_begin");
2615 llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable(
2616 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002617 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002618 ".omp_offloading.entries_end");
2619
2620 // Create all device images
2621 llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires;
2622 auto *DeviceImageTy = cast<llvm::StructType>(
2623 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
2624
2625 for (unsigned i = 0; i < Devices.size(); ++i) {
2626 StringRef T = Devices[i].getTriple();
2627 auto *ImgBegin = new llvm::GlobalVariable(
2628 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002629 /*Initializer=*/nullptr,
2630 Twine(".omp_offloading.img_start.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002631 auto *ImgEnd = new llvm::GlobalVariable(
2632 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002633 /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002634
2635 llvm::Constant *Dev =
2636 llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd,
2637 HostEntriesBegin, HostEntriesEnd, nullptr);
2638 DeviceImagesEntires.push_back(Dev);
2639 }
2640
2641 // Create device images global array.
2642 llvm::ArrayType *DeviceImagesInitTy =
2643 llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size());
2644 llvm::Constant *DeviceImagesInit =
2645 llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires);
2646
2647 llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable(
2648 M, DeviceImagesInitTy, /*isConstant=*/true,
2649 llvm::GlobalValue::InternalLinkage, DeviceImagesInit,
2650 ".omp_offloading.device_images");
2651 DeviceImages->setUnnamedAddr(true);
2652
2653 // This is a Zero array to be used in the creation of the constant expressions
2654 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
2655 llvm::Constant::getNullValue(CGM.Int32Ty)};
2656
2657 // Create the target region descriptor.
2658 auto *BinaryDescriptorTy = cast<llvm::StructType>(
2659 CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
2660 llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get(
2661 BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
2662 llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages,
2663 Index),
2664 HostEntriesBegin, HostEntriesEnd, nullptr);
2665
2666 auto *Desc = new llvm::GlobalVariable(
2667 M, BinaryDescriptorTy, /*isConstant=*/true,
2668 llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit,
2669 ".omp_offloading.descriptor");
2670
2671 // Emit code to register or unregister the descriptor at execution
2672 // startup or closing, respectively.
2673
2674 // Create a variable to drive the registration and unregistration of the
2675 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
2676 auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var");
2677 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(),
2678 IdentInfo, C.CharTy);
2679
2680 auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002681 CGM, ".omp_offloading.descriptor_unreg",
2682 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002683 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
2684 Desc);
2685 });
2686 auto *RegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002687 CGM, ".omp_offloading.descriptor_reg",
2688 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002689 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib),
2690 Desc);
2691 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
2692 });
2693 return RegFn;
2694}
2695
Samuel Antao2de62b02016-02-13 23:35:10 +00002696void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID,
2697 llvm::Constant *Addr, uint64_t Size) {
2698 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00002699 auto *TgtOffloadEntryType = cast<llvm::StructType>(
2700 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()));
2701 llvm::LLVMContext &C = CGM.getModule().getContext();
2702 llvm::Module &M = CGM.getModule();
2703
2704 // Make sure the address has the right type.
Samuel Antao2de62b02016-02-13 23:35:10 +00002705 llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002706
2707 // Create constant string with the name.
2708 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
2709
2710 llvm::GlobalVariable *Str =
2711 new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true,
2712 llvm::GlobalValue::InternalLinkage, StrPtrInit,
2713 ".omp_offloading.entry_name");
2714 Str->setUnnamedAddr(true);
2715 llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy);
2716
2717 // Create the entry struct.
2718 llvm::Constant *EntryInit = llvm::ConstantStruct::get(
2719 TgtOffloadEntryType, AddrPtr, StrPtr,
2720 llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr);
2721 llvm::GlobalVariable *Entry = new llvm::GlobalVariable(
2722 M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage,
2723 EntryInit, ".omp_offloading.entry");
2724
2725 // The entry has to be created in the section the linker expects it to be.
2726 Entry->setSection(".omp_offloading.entries");
2727 // We can't have any padding between symbols, so we need to have 1-byte
2728 // alignment.
2729 Entry->setAlignment(1);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002730}
2731
2732void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
2733 // Emit the offloading entries and metadata so that the device codegen side
2734 // can
2735 // easily figure out what to emit. The produced metadata looks like this:
2736 //
2737 // !omp_offload.info = !{!1, ...}
2738 //
2739 // Right now we only generate metadata for function that contain target
2740 // regions.
2741
2742 // If we do not have entries, we dont need to do anything.
2743 if (OffloadEntriesInfoManager.empty())
2744 return;
2745
2746 llvm::Module &M = CGM.getModule();
2747 llvm::LLVMContext &C = M.getContext();
2748 SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
2749 OrderedEntries(OffloadEntriesInfoManager.size());
2750
2751 // Create the offloading info metadata node.
2752 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
2753
2754 // Auxiliar methods to create metadata values and strings.
2755 auto getMDInt = [&](unsigned v) {
2756 return llvm::ConstantAsMetadata::get(
2757 llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v));
2758 };
2759
2760 auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); };
2761
2762 // Create function that emits metadata for each target region entry;
2763 auto &&TargetRegionMetadataEmitter = [&](
2764 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002765 OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
2766 llvm::SmallVector<llvm::Metadata *, 32> Ops;
2767 // Generate metadata for target regions. Each entry of this metadata
2768 // contains:
2769 // - Entry 0 -> Kind of this type of metadata (0).
2770 // - Entry 1 -> Device ID of the file where the entry was identified.
2771 // - Entry 2 -> File ID of the file where the entry was identified.
2772 // - Entry 3 -> Mangled name of the function where the entry was identified.
2773 // - Entry 4 -> Line in the file where the entry was identified.
Samuel Antao2de62b02016-02-13 23:35:10 +00002774 // - Entry 5 -> Order the entry was created.
Samuel Antaoee8fb302016-01-06 13:42:12 +00002775 // The first element of the metadata node is the kind.
2776 Ops.push_back(getMDInt(E.getKind()));
2777 Ops.push_back(getMDInt(DeviceID));
2778 Ops.push_back(getMDInt(FileID));
2779 Ops.push_back(getMDString(ParentName));
2780 Ops.push_back(getMDInt(Line));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002781 Ops.push_back(getMDInt(E.getOrder()));
2782
2783 // Save this entry in the right position of the ordered entries array.
2784 OrderedEntries[E.getOrder()] = &E;
2785
2786 // Add metadata to the named metadata node.
2787 MD->addOperand(llvm::MDNode::get(C, Ops));
2788 };
2789
2790 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
2791 TargetRegionMetadataEmitter);
2792
2793 for (auto *E : OrderedEntries) {
2794 assert(E && "All ordered entries must exist!");
2795 if (auto *CE =
2796 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
2797 E)) {
2798 assert(CE->getID() && CE->getAddress() &&
2799 "Entry ID and Addr are invalid!");
Samuel Antao2de62b02016-02-13 23:35:10 +00002800 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002801 } else
2802 llvm_unreachable("Unsupported entry kind.");
2803 }
2804}
2805
2806/// \brief Loads all the offload entries information from the host IR
2807/// metadata.
2808void CGOpenMPRuntime::loadOffloadInfoMetadata() {
2809 // If we are in target mode, load the metadata from the host IR. This code has
2810 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
2811
2812 if (!CGM.getLangOpts().OpenMPIsDevice)
2813 return;
2814
2815 if (CGM.getLangOpts().OMPHostIRFile.empty())
2816 return;
2817
2818 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
2819 if (Buf.getError())
2820 return;
2821
2822 llvm::LLVMContext C;
2823 auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C);
2824
2825 if (ME.getError())
2826 return;
2827
2828 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
2829 if (!MD)
2830 return;
2831
2832 for (auto I : MD->operands()) {
2833 llvm::MDNode *MN = cast<llvm::MDNode>(I);
2834
2835 auto getMDInt = [&](unsigned Idx) {
2836 llvm::ConstantAsMetadata *V =
2837 cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
2838 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
2839 };
2840
2841 auto getMDString = [&](unsigned Idx) {
2842 llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx));
2843 return V->getString();
2844 };
2845
2846 switch (getMDInt(0)) {
2847 default:
2848 llvm_unreachable("Unexpected metadata!");
2849 break;
2850 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
2851 OFFLOAD_ENTRY_INFO_TARGET_REGION:
2852 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
2853 /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2),
2854 /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4),
Samuel Antao2de62b02016-02-13 23:35:10 +00002855 /*Order=*/getMDInt(5));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002856 break;
2857 }
2858 }
2859}
2860
Alexey Bataev62b63b12015-03-10 07:28:44 +00002861void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
2862 if (!KmpRoutineEntryPtrTy) {
2863 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
2864 auto &C = CGM.getContext();
2865 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
2866 FunctionProtoType::ExtProtoInfo EPI;
2867 KmpRoutineEntryPtrQTy = C.getPointerType(
2868 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2869 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
2870 }
2871}
2872
Alexey Bataevc71a4092015-09-11 10:29:41 +00002873static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
2874 QualType FieldTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002875 auto *Field = FieldDecl::Create(
2876 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
2877 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
2878 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
2879 Field->setAccess(AS_public);
2880 DC->addDecl(Field);
Alexey Bataevc71a4092015-09-11 10:29:41 +00002881 return Field;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002882}
2883
Samuel Antaoee8fb302016-01-06 13:42:12 +00002884QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
2885
2886 // Make sure the type of the entry is already created. This is the type we
2887 // have to create:
2888 // struct __tgt_offload_entry{
2889 // void *addr; // Pointer to the offload entry info.
2890 // // (function or global)
2891 // char *name; // Name of the function or global.
2892 // size_t size; // Size of the entry info (0 if it a function).
2893 // };
2894 if (TgtOffloadEntryQTy.isNull()) {
2895 ASTContext &C = CGM.getContext();
2896 auto *RD = C.buildImplicitRecord("__tgt_offload_entry");
2897 RD->startDefinition();
2898 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2899 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
2900 addFieldToRecordDecl(C, RD, C.getSizeType());
2901 RD->completeDefinition();
2902 TgtOffloadEntryQTy = C.getRecordType(RD);
2903 }
2904 return TgtOffloadEntryQTy;
2905}
2906
2907QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
2908 // These are the types we need to build:
2909 // struct __tgt_device_image{
2910 // void *ImageStart; // Pointer to the target code start.
2911 // void *ImageEnd; // Pointer to the target code end.
2912 // // We also add the host entries to the device image, as it may be useful
2913 // // for the target runtime to have access to that information.
2914 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
2915 // // the entries.
2916 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2917 // // entries (non inclusive).
2918 // };
2919 if (TgtDeviceImageQTy.isNull()) {
2920 ASTContext &C = CGM.getContext();
2921 auto *RD = C.buildImplicitRecord("__tgt_device_image");
2922 RD->startDefinition();
2923 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2924 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2925 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2926 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2927 RD->completeDefinition();
2928 TgtDeviceImageQTy = C.getRecordType(RD);
2929 }
2930 return TgtDeviceImageQTy;
2931}
2932
2933QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
2934 // struct __tgt_bin_desc{
2935 // int32_t NumDevices; // Number of devices supported.
2936 // __tgt_device_image *DeviceImages; // Arrays of device images
2937 // // (one per device).
2938 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
2939 // // entries.
2940 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2941 // // entries (non inclusive).
2942 // };
2943 if (TgtBinaryDescriptorQTy.isNull()) {
2944 ASTContext &C = CGM.getContext();
2945 auto *RD = C.buildImplicitRecord("__tgt_bin_desc");
2946 RD->startDefinition();
2947 addFieldToRecordDecl(
2948 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
2949 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
2950 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2951 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2952 RD->completeDefinition();
2953 TgtBinaryDescriptorQTy = C.getRecordType(RD);
2954 }
2955 return TgtBinaryDescriptorQTy;
2956}
2957
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002958namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00002959struct PrivateHelpersTy {
2960 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
2961 const VarDecl *PrivateElemInit)
2962 : Original(Original), PrivateCopy(PrivateCopy),
2963 PrivateElemInit(PrivateElemInit) {}
2964 const VarDecl *Original;
2965 const VarDecl *PrivateCopy;
2966 const VarDecl *PrivateElemInit;
2967};
2968typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00002969} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002970
Alexey Bataev9e034042015-05-05 04:05:12 +00002971static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00002972createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002973 if (!Privates.empty()) {
2974 auto &C = CGM.getContext();
2975 // Build struct .kmp_privates_t. {
2976 // /* private vars */
2977 // };
2978 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
2979 RD->startDefinition();
2980 for (auto &&Pair : Privates) {
Alexey Bataevc71a4092015-09-11 10:29:41 +00002981 auto *VD = Pair.second.Original;
2982 auto Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002983 Type = Type.getNonReferenceType();
Alexey Bataevc71a4092015-09-11 10:29:41 +00002984 auto *FD = addFieldToRecordDecl(C, RD, Type);
2985 if (VD->hasAttrs()) {
2986 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
2987 E(VD->getAttrs().end());
2988 I != E; ++I)
2989 FD->addAttr(*I);
2990 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002991 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002992 RD->completeDefinition();
2993 return RD;
2994 }
2995 return nullptr;
2996}
2997
Alexey Bataev9e034042015-05-05 04:05:12 +00002998static RecordDecl *
2999createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003000 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003001 auto &C = CGM.getContext();
3002 // Build struct kmp_task_t {
3003 // void * shareds;
3004 // kmp_routine_entry_t routine;
3005 // kmp_int32 part_id;
3006 // kmp_routine_entry_t destructors;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003007 // };
3008 auto *RD = C.buildImplicitRecord("kmp_task_t");
3009 RD->startDefinition();
3010 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3011 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
3012 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3013 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003014 RD->completeDefinition();
3015 return RD;
3016}
3017
3018static RecordDecl *
3019createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003020 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003021 auto &C = CGM.getContext();
3022 // Build struct kmp_task_t_with_privates {
3023 // kmp_task_t task_data;
3024 // .kmp_privates_t. privates;
3025 // };
3026 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
3027 RD->startDefinition();
3028 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003029 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
3030 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
3031 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003032 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003033 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003034}
3035
3036/// \brief Emit a proxy function which accepts kmp_task_t as the second
3037/// argument.
3038/// \code
3039/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003040/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003041/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003042/// return 0;
3043/// }
3044/// \endcode
3045static llvm::Value *
3046emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003047 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
3048 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003049 QualType SharedsPtrTy, llvm::Value *TaskFunction,
3050 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003051 auto &C = CGM.getContext();
3052 FunctionArgList Args;
3053 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3054 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003055 /*Id=*/nullptr,
3056 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003057 Args.push_back(&GtidArg);
3058 Args.push_back(&TaskTypeArg);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003059 auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003060 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003061 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
3062 auto *TaskEntry =
3063 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
3064 ".omp_task_entry.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003065 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003066 CodeGenFunction CGF(CGM);
3067 CGF.disableDebugInfo();
3068 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
3069
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003070 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev48591dd2016-04-20 04:01:36 +00003071 // tt, tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003072 auto *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00003073 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00003074 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3075 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3076 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003077 auto *KmpTaskTWithPrivatesQTyRD =
3078 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003079 LValue Base =
3080 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003081 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
3082 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3083 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003084 auto *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003085
3086 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3087 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003088 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003089 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003090 CGF.ConvertTypeForMem(SharedsPtrTy));
3091
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003092 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3093 llvm::Value *PrivatesParam;
3094 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3095 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
3096 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003097 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003098 } else {
3099 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3100 }
3101
3102 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam,
Alexey Bataev48591dd2016-04-20 04:01:36 +00003103 TaskPrivatesMap,
3104 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3105 TDBase.getAddress(), CGF.VoidPtrTy)
3106 .getPointer(),
3107 SharedsParam};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003108 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
3109 CGF.EmitStoreThroughLValue(
3110 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
John McCall7f416cc2015-09-08 08:05:57 +00003111 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00003112 CGF.FinishFunction();
3113 return TaskEntry;
3114}
3115
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003116static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
3117 SourceLocation Loc,
3118 QualType KmpInt32Ty,
3119 QualType KmpTaskTWithPrivatesPtrQTy,
3120 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003121 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003122 FunctionArgList Args;
3123 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3124 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003125 /*Id=*/nullptr,
3126 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003127 Args.push_back(&GtidArg);
3128 Args.push_back(&TaskTypeArg);
3129 FunctionType::ExtInfo Info;
3130 auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003131 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003132 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
3133 auto *DestructorFn =
3134 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3135 ".omp_task_destructor.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003136 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
3137 DestructorFnInfo);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003138 CodeGenFunction CGF(CGM);
3139 CGF.disableDebugInfo();
3140 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
3141 Args);
3142
Alexey Bataev31300ed2016-02-04 11:27:03 +00003143 LValue Base = CGF.EmitLoadOfPointerLValue(
3144 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3145 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003146 auto *KmpTaskTWithPrivatesQTyRD =
3147 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3148 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003149 Base = CGF.EmitLValueForField(Base, *FI);
3150 for (auto *Field :
3151 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3152 if (auto DtorKind = Field->getType().isDestructedType()) {
3153 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
3154 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3155 }
3156 }
3157 CGF.FinishFunction();
3158 return DestructorFn;
3159}
3160
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003161/// \brief Emit a privates mapping function for correct handling of private and
3162/// firstprivate variables.
3163/// \code
3164/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
3165/// **noalias priv1,..., <tyn> **noalias privn) {
3166/// *priv1 = &.privates.priv1;
3167/// ...;
3168/// *privn = &.privates.privn;
3169/// }
3170/// \endcode
3171static llvm::Value *
3172emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00003173 ArrayRef<const Expr *> PrivateVars,
3174 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003175 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003176 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003177 auto &C = CGM.getContext();
3178 FunctionArgList Args;
3179 ImplicitParamDecl TaskPrivatesArg(
3180 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3181 C.getPointerType(PrivatesQTy).withConst().withRestrict());
3182 Args.push_back(&TaskPrivatesArg);
3183 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
3184 unsigned Counter = 1;
3185 for (auto *E: PrivateVars) {
3186 Args.push_back(ImplicitParamDecl::Create(
3187 C, /*DC=*/nullptr, Loc,
3188 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3189 .withConst()
3190 .withRestrict()));
3191 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3192 PrivateVarsPos[VD] = Counter;
3193 ++Counter;
3194 }
3195 for (auto *E : FirstprivateVars) {
3196 Args.push_back(ImplicitParamDecl::Create(
3197 C, /*DC=*/nullptr, Loc,
3198 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3199 .withConst()
3200 .withRestrict()));
3201 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3202 PrivateVarsPos[VD] = Counter;
3203 ++Counter;
3204 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003205 auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003206 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003207 auto *TaskPrivatesMapTy =
3208 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
3209 auto *TaskPrivatesMap = llvm::Function::Create(
3210 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
3211 ".omp_task_privates_map.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003212 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
3213 TaskPrivatesMapFnInfo);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00003214 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003215 CodeGenFunction CGF(CGM);
3216 CGF.disableDebugInfo();
3217 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
3218 TaskPrivatesMapFnInfo, Args);
3219
3220 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00003221 LValue Base = CGF.EmitLoadOfPointerLValue(
3222 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
3223 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003224 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
3225 Counter = 0;
3226 for (auto *Field : PrivatesQTyRD->fields()) {
3227 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
3228 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
John McCall7f416cc2015-09-08 08:05:57 +00003229 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
Alexey Bataev31300ed2016-02-04 11:27:03 +00003230 auto RefLoadLVal = CGF.EmitLoadOfPointerLValue(
3231 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003232 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003233 ++Counter;
3234 }
3235 CGF.FinishFunction();
3236 return TaskPrivatesMap;
3237}
3238
Alexey Bataev9e034042015-05-05 04:05:12 +00003239static int array_pod_sort_comparator(const PrivateDataTy *P1,
3240 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003241 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
3242}
3243
3244void CGOpenMPRuntime::emitTaskCall(
3245 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
3246 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
Alexey Bataev48591dd2016-04-20 04:01:36 +00003247 unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy,
3248 Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003249 ArrayRef<const Expr *> PrivateCopies,
3250 ArrayRef<const Expr *> FirstprivateVars,
3251 ArrayRef<const Expr *> FirstprivateCopies,
3252 ArrayRef<const Expr *> FirstprivateInits,
3253 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003254 if (!CGF.HaveInsertPoint())
3255 return;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003256 auto &C = CGM.getContext();
Alexey Bataev9e034042015-05-05 04:05:12 +00003257 llvm::SmallVector<PrivateDataTy, 8> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003258 // Aggregate privates and sort them by the alignment.
Alexey Bataev9e034042015-05-05 04:05:12 +00003259 auto I = PrivateCopies.begin();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003260 for (auto *E : PrivateVars) {
3261 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3262 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003263 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003264 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3265 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003266 ++I;
3267 }
Alexey Bataev9e034042015-05-05 04:05:12 +00003268 I = FirstprivateCopies.begin();
3269 auto IElemInitRef = FirstprivateInits.begin();
3270 for (auto *E : FirstprivateVars) {
3271 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3272 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003273 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003274 PrivateHelpersTy(
3275 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3276 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
Richard Trieucc3949d2016-02-18 22:34:54 +00003277 ++I;
3278 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00003279 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003280 llvm::array_pod_sort(Privates.begin(), Privates.end(),
3281 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003282 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
3283 // Build type kmp_routine_entry_t (if not built yet).
3284 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003285 // Build type kmp_task_t (if not built yet).
3286 if (KmpTaskTQTy.isNull()) {
3287 KmpTaskTQTy = C.getRecordType(
3288 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
3289 }
3290 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003291 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003292 auto *KmpTaskTWithPrivatesQTyRD =
3293 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
3294 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
3295 QualType KmpTaskTWithPrivatesPtrQTy =
3296 C.getPointerType(KmpTaskTWithPrivatesQTy);
3297 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
3298 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003299 auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003300 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
3301
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003302 // Emit initial values for private copies (if any).
3303 llvm::Value *TaskPrivatesMap = nullptr;
3304 auto *TaskPrivatesMapTy =
3305 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
3306 3)
3307 ->getType();
3308 if (!Privates.empty()) {
3309 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3310 TaskPrivatesMap = emitTaskPrivateMappingFunction(
3311 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
3312 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3313 TaskPrivatesMap, TaskPrivatesMapTy);
3314 } else {
3315 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3316 cast<llvm::PointerType>(TaskPrivatesMapTy));
3317 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003318 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
3319 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003320 auto *TaskEntry = emitProxyTaskFunction(
3321 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003322 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003323
3324 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
3325 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
3326 // kmp_routine_entry_t *task_entry);
3327 // Task flags. Format is taken from
3328 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
3329 // description of kmp_tasking_flags struct.
3330 const unsigned TiedFlag = 0x1;
3331 const unsigned FinalFlag = 0x2;
3332 unsigned Flags = Tied ? TiedFlag : 0;
3333 auto *TaskFlags =
3334 Final.getPointer()
3335 ? CGF.Builder.CreateSelect(Final.getPointer(),
3336 CGF.Builder.getInt32(FinalFlag),
3337 CGF.Builder.getInt32(/*C=*/0))
3338 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
3339 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataev40e36f12015-11-24 13:01:44 +00003340 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003341 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
3342 getThreadID(CGF, Loc), TaskFlags,
3343 KmpTaskTWithPrivatesTySize, SharedsSize,
3344 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3345 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003346 auto *NewTask = CGF.EmitRuntimeCall(
3347 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003348 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3349 NewTask, KmpTaskTWithPrivatesPtrTy);
3350 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
3351 KmpTaskTWithPrivatesQTy);
3352 LValue TDBase =
3353 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003354 // Fill the data in the resulting kmp_task_t record.
3355 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00003356 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003357 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003358 KmpTaskSharedsPtr =
3359 Address(CGF.EmitLoadOfScalar(
3360 CGF.EmitLValueForField(
3361 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
3362 KmpTaskTShareds)),
3363 Loc),
3364 CGF.getNaturalTypeAlignment(SharedsTy));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003365 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003366 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003367 // Emit initial values for private copies (if any).
3368 bool NeedsCleanup = false;
3369 if (!Privates.empty()) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003370 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3371 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003372 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003373 LValue SharedsBase;
3374 if (!FirstprivateVars.empty()) {
John McCall7f416cc2015-09-08 08:05:57 +00003375 SharedsBase = CGF.MakeAddrLValue(
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003376 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3377 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
3378 SharedsTy);
3379 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003380 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
3381 cast<CapturedStmt>(*D.getAssociatedStmt()));
3382 for (auto &&Pair : Privates) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003383 auto *VD = Pair.second.PrivateCopy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003384 auto *Init = VD->getAnyInitializer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003385 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003386 if (Init) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003387 if (auto *Elem = Pair.second.PrivateElemInit) {
3388 auto *OriginalVD = Pair.second.Original;
3389 auto *SharedField = CapturesInfo.lookup(OriginalVD);
3390 auto SharedRefLValue =
3391 CGF.EmitLValueForField(SharedsBase, SharedField);
Alexey Bataevc71a4092015-09-11 10:29:41 +00003392 SharedRefLValue = CGF.MakeAddrLValue(
3393 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
3394 SharedRefLValue.getType(), AlignmentSource::Decl);
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003395 QualType Type = OriginalVD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003396 if (Type->isArrayType()) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003397 // Initialize firstprivate array.
3398 if (!isa<CXXConstructExpr>(Init) ||
3399 CGF.isTrivialInitializer(Init)) {
3400 // Perform simple memcpy.
3401 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003402 SharedRefLValue.getAddress(), Type);
Alexey Bataev9e034042015-05-05 04:05:12 +00003403 } else {
3404 // Initialize firstprivate array using element-by-element
3405 // intialization.
3406 CGF.EmitOMPAggregateAssign(
3407 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003408 Type, [&CGF, Elem, Init, &CapturesInfo](
John McCall7f416cc2015-09-08 08:05:57 +00003409 Address DestElement, Address SrcElement) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003410 // Clean up any temporaries needed by the initialization.
3411 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003412 InitScope.addPrivate(Elem, [SrcElement]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003413 return SrcElement;
3414 });
3415 (void)InitScope.Privatize();
3416 // Emit initialization for single element.
Alexey Bataevd157d472015-06-24 03:35:38 +00003417 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3418 CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003419 CGF.EmitAnyExprToMem(Init, DestElement,
3420 Init->getType().getQualifiers(),
3421 /*IsInitializer=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003422 });
3423 }
3424 } else {
3425 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003426 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003427 return SharedRefLValue.getAddress();
3428 });
3429 (void)InitScope.Privatize();
Alexey Bataevd157d472015-06-24 03:35:38 +00003430 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003431 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
3432 /*capturedByInit=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003433 }
3434 } else {
3435 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
3436 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003437 }
3438 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003439 ++FI;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003440 }
3441 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003442 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003443 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003444 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
3445 KmpTaskTWithPrivatesPtrQTy,
3446 KmpTaskTWithPrivatesQTy)
3447 : llvm::ConstantPointerNull::get(
3448 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
3449 LValue Destructor = CGF.EmitLValueForField(
3450 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
3451 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3452 DestructorFn, KmpRoutineEntryPtrTy),
3453 Destructor);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003454
3455 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00003456 Address DependenciesArray = Address::invalid();
3457 unsigned NumDependencies = Dependences.size();
3458 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003459 // Dependence kind for RTL.
Alexey Bataev92e82f92015-11-23 13:33:42 +00003460 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003461 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
3462 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003463 QualType FlagsTy =
3464 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003465 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
3466 if (KmpDependInfoTy.isNull()) {
3467 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
3468 KmpDependInfoRD->startDefinition();
3469 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
3470 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
3471 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
3472 KmpDependInfoRD->completeDefinition();
3473 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
3474 } else {
3475 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
3476 }
John McCall7f416cc2015-09-08 08:05:57 +00003477 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003478 // Define type kmp_depend_info[<Dependences.size()>];
3479 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00003480 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003481 ArrayType::Normal, /*IndexTypeQuals=*/0);
3482 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00003483 DependenciesArray =
3484 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
John McCall7f416cc2015-09-08 08:05:57 +00003485 for (unsigned i = 0; i < NumDependencies; ++i) {
3486 const Expr *E = Dependences[i].second;
3487 auto Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003488 llvm::Value *Size;
3489 QualType Ty = E->getType();
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003490 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
3491 LValue UpAddrLVal =
3492 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
3493 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00003494 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003495 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00003496 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003497 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
3498 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003499 } else
Alexey Bataev1189bd02016-01-26 12:20:39 +00003500 Size = CGF.getTypeSize(Ty);
John McCall7f416cc2015-09-08 08:05:57 +00003501 auto Base = CGF.MakeAddrLValue(
3502 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003503 KmpDependInfoTy);
3504 // deps[i].base_addr = &<Dependences[i].second>;
3505 auto BaseAddrLVal = CGF.EmitLValueForField(
3506 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00003507 CGF.EmitStoreOfScalar(
3508 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
3509 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003510 // deps[i].len = sizeof(<Dependences[i].second>);
3511 auto LenLVal = CGF.EmitLValueForField(
3512 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
3513 CGF.EmitStoreOfScalar(Size, LenLVal);
3514 // deps[i].flags = <Dependences[i].first>;
3515 RTLDependenceKindTy DepKind;
3516 switch (Dependences[i].first) {
3517 case OMPC_DEPEND_in:
3518 DepKind = DepIn;
3519 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00003520 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003521 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003522 case OMPC_DEPEND_inout:
3523 DepKind = DepInOut;
3524 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00003525 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00003526 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003527 case OMPC_DEPEND_unknown:
3528 llvm_unreachable("Unknown task dependence type");
3529 }
3530 auto FlagsLVal = CGF.EmitLValueForField(
3531 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
3532 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
3533 FlagsLVal);
3534 }
John McCall7f416cc2015-09-08 08:05:57 +00003535 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3536 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003537 CGF.VoidPtrTy);
3538 }
3539
Alexey Bataev62b63b12015-03-10 07:28:44 +00003540 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
3541 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003542 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
3543 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
3544 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
3545 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00003546 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003547 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00003548 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
3549 llvm::Value *DepTaskArgs[7];
3550 if (NumDependencies) {
3551 DepTaskArgs[0] = UpLoc;
3552 DepTaskArgs[1] = ThreadID;
3553 DepTaskArgs[2] = NewTask;
3554 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
3555 DepTaskArgs[4] = DependenciesArray.getPointer();
3556 DepTaskArgs[5] = CGF.Builder.getInt32(0);
3557 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3558 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00003559 auto &&ThenCodeGen = [this, Tied, Loc, NumberOfParts, TDBase, KmpTaskTQTyRD,
3560 NumDependencies, &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003561 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003562 if (!Tied) {
3563 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3564 auto PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
3565 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
3566 }
John McCall7f416cc2015-09-08 08:05:57 +00003567 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003568 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00003569 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00003570 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003571 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00003572 TaskArgs);
3573 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00003574 // Check if parent region is untied and build return for untied task;
3575 if (auto *Region =
3576 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3577 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003578 };
John McCall7f416cc2015-09-08 08:05:57 +00003579
3580 llvm::Value *DepWaitTaskArgs[6];
3581 if (NumDependencies) {
3582 DepWaitTaskArgs[0] = UpLoc;
3583 DepWaitTaskArgs[1] = ThreadID;
3584 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
3585 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
3586 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
3587 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3588 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003589 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
3590 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF,
3591 PrePostActionTy &) {
3592 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003593 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
3594 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
3595 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
3596 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
3597 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00003598 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003599 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003600 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003601 // Call proxy_task_entry(gtid, new_task);
3602 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy](
3603 CodeGenFunction &CGF, PrePostActionTy &Action) {
3604 Action.Enter(CGF);
3605 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
3606 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
3607 };
3608
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003609 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
3610 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003611 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
3612 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003613 RegionCodeGenTy RCG(CodeGen);
3614 CommonActionTy Action(
3615 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
3616 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
3617 RCG.setAction(Action);
3618 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003619 };
John McCall7f416cc2015-09-08 08:05:57 +00003620
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003621 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00003622 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003623 else {
3624 RegionCodeGenTy ThenRCG(ThenCodeGen);
3625 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003626 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003627}
3628
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003629/// \brief Emit reduction operation for each element of array (required for
3630/// array sections) LHS op = RHS.
3631/// \param Type Type of array.
3632/// \param LHSVar Variable on the left side of the reduction operation
3633/// (references element of array in original variable).
3634/// \param RHSVar Variable on the right side of the reduction operation
3635/// (references element of array in original variable).
3636/// \param RedOpGen Generator of reduction operation with use of LHSVar and
3637/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00003638static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003639 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
3640 const VarDecl *RHSVar,
3641 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
3642 const Expr *, const Expr *)> &RedOpGen,
3643 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
3644 const Expr *UpExpr = nullptr) {
3645 // Perform element-by-element initialization.
3646 QualType ElementTy;
3647 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
3648 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
3649
3650 // Drill down to the base element type on both arrays.
3651 auto ArrayTy = Type->getAsArrayTypeUnsafe();
3652 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
3653
3654 auto RHSBegin = RHSAddr.getPointer();
3655 auto LHSBegin = LHSAddr.getPointer();
3656 // Cast from pointer to array type to pointer to single element.
3657 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
3658 // The basic structure here is a while-do loop.
3659 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
3660 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
3661 auto IsEmpty =
3662 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
3663 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
3664
3665 // Enter the loop body, making that address the current address.
3666 auto EntryBB = CGF.Builder.GetInsertBlock();
3667 CGF.EmitBlock(BodyBB);
3668
3669 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
3670
3671 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
3672 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
3673 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
3674 Address RHSElementCurrent =
3675 Address(RHSElementPHI,
3676 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3677
3678 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
3679 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
3680 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
3681 Address LHSElementCurrent =
3682 Address(LHSElementPHI,
3683 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3684
3685 // Emit copy.
3686 CodeGenFunction::OMPPrivateScope Scope(CGF);
3687 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
3688 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
3689 Scope.Privatize();
3690 RedOpGen(CGF, XExpr, EExpr, UpExpr);
3691 Scope.ForceCleanup();
3692
3693 // Shift the address forward by one element.
3694 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
3695 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
3696 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
3697 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
3698 // Check whether we've reached the end.
3699 auto Done =
3700 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
3701 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
3702 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
3703 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
3704
3705 // Done.
3706 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
3707}
3708
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003709/// Emit reduction combiner. If the combiner is a simple expression emit it as
3710/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
3711/// UDR combiner function.
3712static void emitReductionCombiner(CodeGenFunction &CGF,
3713 const Expr *ReductionOp) {
3714 if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
3715 if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
3716 if (auto *DRE =
3717 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
3718 if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
3719 std::pair<llvm::Function *, llvm::Function *> Reduction =
3720 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
3721 RValue Func = RValue::get(Reduction.first);
3722 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
3723 CGF.EmitIgnoredExpr(ReductionOp);
3724 return;
3725 }
3726 CGF.EmitIgnoredExpr(ReductionOp);
3727}
3728
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003729static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
3730 llvm::Type *ArgsType,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003731 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003732 ArrayRef<const Expr *> LHSExprs,
3733 ArrayRef<const Expr *> RHSExprs,
3734 ArrayRef<const Expr *> ReductionOps) {
3735 auto &C = CGM.getContext();
3736
3737 // void reduction_func(void *LHSArg, void *RHSArg);
3738 FunctionArgList Args;
3739 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3740 C.VoidPtrTy);
3741 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3742 C.VoidPtrTy);
3743 Args.push_back(&LHSArg);
3744 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00003745 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003746 auto *Fn = llvm::Function::Create(
3747 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
3748 ".omp.reduction.reduction_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003749 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003750 CodeGenFunction CGF(CGM);
3751 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
3752
3753 // Dst = (void*[n])(LHSArg);
3754 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003755 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3756 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3757 ArgsType), CGF.getPointerAlign());
3758 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3759 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3760 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003761
3762 // ...
3763 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
3764 // ...
3765 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003766 auto IPriv = Privates.begin();
3767 unsigned Idx = 0;
3768 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003769 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
3770 Scope.addPrivate(RHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003771 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003772 });
3773 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
3774 Scope.addPrivate(LHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003775 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003776 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003777 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003778 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003779 // Get array size and emit VLA type.
3780 ++Idx;
3781 Address Elem =
3782 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
3783 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003784 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy);
3785 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003786 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00003787 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003788 CGF.EmitVariablyModifiedType(PrivTy);
3789 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003790 }
3791 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003792 IPriv = Privates.begin();
3793 auto ILHS = LHSExprs.begin();
3794 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003795 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003796 if ((*IPriv)->getType()->isArrayType()) {
3797 // Emit reduction for array section.
3798 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3799 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003800 EmitOMPAggregateReduction(
3801 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3802 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
3803 emitReductionCombiner(CGF, E);
3804 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003805 } else
3806 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003807 emitReductionCombiner(CGF, E);
Richard Trieucc3949d2016-02-18 22:34:54 +00003808 ++IPriv;
3809 ++ILHS;
3810 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003811 }
3812 Scope.ForceCleanup();
3813 CGF.FinishFunction();
3814 return Fn;
3815}
3816
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003817static void emitSingleReductionCombiner(CodeGenFunction &CGF,
3818 const Expr *ReductionOp,
3819 const Expr *PrivateRef,
3820 const DeclRefExpr *LHS,
3821 const DeclRefExpr *RHS) {
3822 if (PrivateRef->getType()->isArrayType()) {
3823 // Emit reduction for array section.
3824 auto *LHSVar = cast<VarDecl>(LHS->getDecl());
3825 auto *RHSVar = cast<VarDecl>(RHS->getDecl());
3826 EmitOMPAggregateReduction(
3827 CGF, PrivateRef->getType(), LHSVar, RHSVar,
3828 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
3829 emitReductionCombiner(CGF, ReductionOp);
3830 });
3831 } else
3832 // Emit reduction for array subscript or single variable.
3833 emitReductionCombiner(CGF, ReductionOp);
3834}
3835
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003836void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003837 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003838 ArrayRef<const Expr *> LHSExprs,
3839 ArrayRef<const Expr *> RHSExprs,
3840 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003841 bool WithNowait, bool SimpleReduction) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003842 if (!CGF.HaveInsertPoint())
3843 return;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003844 // Next code should be emitted for reduction:
3845 //
3846 // static kmp_critical_name lock = { 0 };
3847 //
3848 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
3849 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
3850 // ...
3851 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
3852 // *(Type<n>-1*)rhs[<n>-1]);
3853 // }
3854 //
3855 // ...
3856 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
3857 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
3858 // RedList, reduce_func, &<lock>)) {
3859 // case 1:
3860 // ...
3861 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3862 // ...
3863 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3864 // break;
3865 // case 2:
3866 // ...
3867 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
3868 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00003869 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003870 // break;
3871 // default:;
3872 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003873 //
3874 // if SimpleReduction is true, only the next code is generated:
3875 // ...
3876 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3877 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003878
3879 auto &C = CGM.getContext();
3880
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003881 if (SimpleReduction) {
3882 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003883 auto IPriv = Privates.begin();
3884 auto ILHS = LHSExprs.begin();
3885 auto IRHS = RHSExprs.begin();
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003886 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003887 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
3888 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00003889 ++IPriv;
3890 ++ILHS;
3891 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003892 }
3893 return;
3894 }
3895
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003896 // 1. Build a list of reduction variables.
3897 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003898 auto Size = RHSExprs.size();
3899 for (auto *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00003900 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003901 // Reserve place for array size.
3902 ++Size;
3903 }
3904 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003905 QualType ReductionArrayTy =
3906 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
3907 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00003908 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003909 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003910 auto IPriv = Privates.begin();
3911 unsigned Idx = 0;
3912 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003913 Address Elem =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003914 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00003915 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003916 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003917 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
3918 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003919 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003920 // Store array size.
3921 ++Idx;
3922 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
3923 CGF.getPointerSize());
Alexey Bataev1189bd02016-01-26 12:20:39 +00003924 llvm::Value *Size = CGF.Builder.CreateIntCast(
3925 CGF.getVLASize(
3926 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
3927 .first,
3928 CGF.SizeTy, /*isSigned=*/false);
3929 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
3930 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003931 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003932 }
3933
3934 // 2. Emit reduce_func().
3935 auto *ReductionFn = emitReductionFunction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003936 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
3937 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003938
3939 // 3. Create static kmp_critical_name lock = { 0 };
3940 auto *Lock = getCriticalRegionLock(".reduction");
3941
3942 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
3943 // RedList, reduce_func, &<lock>);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003944 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003945 auto *ThreadId = getThreadID(CGF, Loc);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003946 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003947 auto *RL =
3948 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
3949 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003950 llvm::Value *Args[] = {
3951 IdentTLoc, // ident_t *<loc>
3952 ThreadId, // i32 <gtid>
3953 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
3954 ReductionArrayTySize, // size_type sizeof(RedList)
3955 RL, // void *RedList
3956 ReductionFn, // void (*) (void *, void *) <reduce_func>
3957 Lock // kmp_critical_name *&<lock>
3958 };
3959 auto Res = CGF.EmitRuntimeCall(
3960 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
3961 : OMPRTL__kmpc_reduce),
3962 Args);
3963
3964 // 5. Build switch(res)
3965 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
3966 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
3967
3968 // 6. Build case 1:
3969 // ...
3970 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3971 // ...
3972 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3973 // break;
3974 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
3975 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
3976 CGF.EmitBlock(Case1BB);
3977
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003978 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3979 llvm::Value *EndArgs[] = {
3980 IdentTLoc, // ident_t *<loc>
3981 ThreadId, // i32 <gtid>
3982 Lock // kmp_critical_name *&<lock>
3983 };
3984 auto &&CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps](
3985 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003986 auto IPriv = Privates.begin();
3987 auto ILHS = LHSExprs.begin();
3988 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003989 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003990 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
3991 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00003992 ++IPriv;
3993 ++ILHS;
3994 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003995 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003996 };
3997 RegionCodeGenTy RCG(CodeGen);
3998 CommonActionTy Action(
3999 nullptr, llvm::None,
4000 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
4001 : OMPRTL__kmpc_end_reduce),
4002 EndArgs);
4003 RCG.setAction(Action);
4004 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004005
4006 CGF.EmitBranch(DefaultBB);
4007
4008 // 7. Build case 2:
4009 // ...
4010 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
4011 // ...
4012 // break;
4013 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
4014 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
4015 CGF.EmitBlock(Case2BB);
4016
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004017 auto &&AtomicCodeGen = [Loc, &Privates, &LHSExprs, &RHSExprs, &ReductionOps](
4018 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004019 auto ILHS = LHSExprs.begin();
4020 auto IRHS = RHSExprs.begin();
4021 auto IPriv = Privates.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004022 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004023 const Expr *XExpr = nullptr;
4024 const Expr *EExpr = nullptr;
4025 const Expr *UpExpr = nullptr;
4026 BinaryOperatorKind BO = BO_Comma;
4027 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
4028 if (BO->getOpcode() == BO_Assign) {
4029 XExpr = BO->getLHS();
4030 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004031 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004032 }
4033 // Try to emit update expression as a simple atomic.
4034 auto *RHSExpr = UpExpr;
4035 if (RHSExpr) {
4036 // Analyze RHS part of the whole expression.
4037 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
4038 RHSExpr->IgnoreParenImpCasts())) {
4039 // If this is a conditional operator, analyze its condition for
4040 // min/max reduction operator.
4041 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00004042 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004043 if (auto *BORHS =
4044 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
4045 EExpr = BORHS->getRHS();
4046 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004047 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004048 }
4049 if (XExpr) {
4050 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4051 auto &&AtomicRedGen = [BO, VD, IPriv,
4052 Loc](CodeGenFunction &CGF, const Expr *XExpr,
4053 const Expr *EExpr, const Expr *UpExpr) {
4054 LValue X = CGF.EmitLValue(XExpr);
4055 RValue E;
4056 if (EExpr)
4057 E = CGF.EmitAnyExpr(EExpr);
4058 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00004059 X, E, BO, /*IsXLHSInRHSPart=*/true,
4060 llvm::AtomicOrdering::Monotonic, Loc,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004061 [&CGF, UpExpr, VD, IPriv, Loc](RValue XRValue) {
4062 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4063 PrivateScope.addPrivate(
4064 VD, [&CGF, VD, XRValue, Loc]() -> Address {
4065 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
4066 CGF.emitOMPSimpleStore(
4067 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
4068 VD->getType().getNonReferenceType(), Loc);
4069 return LHSTemp;
4070 });
4071 (void)PrivateScope.Privatize();
4072 return CGF.EmitAnyExpr(UpExpr);
4073 });
4074 };
4075 if ((*IPriv)->getType()->isArrayType()) {
4076 // Emit atomic reduction for array section.
4077 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4078 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
4079 AtomicRedGen, XExpr, EExpr, UpExpr);
4080 } else
4081 // Emit atomic reduction for array subscript or single variable.
4082 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
4083 } else {
4084 // Emit as a critical region.
4085 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
4086 const Expr *, const Expr *) {
4087 auto &RT = CGF.CGM.getOpenMPRuntime();
4088 RT.emitCriticalRegion(
4089 CGF, ".atomic_reduction",
4090 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
4091 Action.Enter(CGF);
4092 emitReductionCombiner(CGF, E);
4093 },
4094 Loc);
4095 };
4096 if ((*IPriv)->getType()->isArrayType()) {
4097 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4098 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4099 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4100 CritRedGen);
4101 } else
4102 CritRedGen(CGF, nullptr, nullptr, nullptr);
4103 }
Richard Trieucc3949d2016-02-18 22:34:54 +00004104 ++ILHS;
4105 ++IRHS;
4106 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004107 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004108 };
4109 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
4110 if (!WithNowait) {
4111 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
4112 llvm::Value *EndArgs[] = {
4113 IdentTLoc, // ident_t *<loc>
4114 ThreadId, // i32 <gtid>
4115 Lock // kmp_critical_name *&<lock>
4116 };
4117 CommonActionTy Action(nullptr, llvm::None,
4118 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
4119 EndArgs);
4120 AtomicRCG.setAction(Action);
4121 AtomicRCG(CGF);
4122 } else
4123 AtomicRCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004124
4125 CGF.EmitBranch(DefaultBB);
4126 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
4127}
4128
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004129void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
4130 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004131 if (!CGF.HaveInsertPoint())
4132 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004133 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
4134 // global_tid);
4135 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
4136 // Ignore return result until untied tasks are supported.
4137 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00004138 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
4139 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004140}
4141
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004142void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004143 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00004144 const RegionCodeGenTy &CodeGen,
4145 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004146 if (!CGF.HaveInsertPoint())
4147 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004148 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004149 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00004150}
4151
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004152namespace {
4153enum RTCancelKind {
4154 CancelNoreq = 0,
4155 CancelParallel = 1,
4156 CancelLoop = 2,
4157 CancelSections = 3,
4158 CancelTaskgroup = 4
4159};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004160} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004161
4162static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
4163 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00004164 if (CancelRegion == OMPD_parallel)
4165 CancelKind = CancelParallel;
4166 else if (CancelRegion == OMPD_for)
4167 CancelKind = CancelLoop;
4168 else if (CancelRegion == OMPD_sections)
4169 CancelKind = CancelSections;
4170 else {
4171 assert(CancelRegion == OMPD_taskgroup);
4172 CancelKind = CancelTaskgroup;
4173 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004174 return CancelKind;
4175}
4176
4177void CGOpenMPRuntime::emitCancellationPointCall(
4178 CodeGenFunction &CGF, SourceLocation Loc,
4179 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004180 if (!CGF.HaveInsertPoint())
4181 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004182 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
4183 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004184 if (auto *OMPRegionInfo =
4185 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00004186 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004187 llvm::Value *Args[] = {
4188 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
4189 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004190 // Ignore return result until untied tasks are supported.
4191 auto *Result = CGF.EmitRuntimeCall(
4192 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
4193 // if (__kmpc_cancellationpoint()) {
4194 // __kmpc_cancel_barrier();
4195 // exit from construct;
4196 // }
4197 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4198 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4199 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4200 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4201 CGF.EmitBlock(ExitBB);
4202 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00004203 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004204 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004205 auto CancelDest =
4206 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004207 CGF.EmitBranchThroughCleanup(CancelDest);
4208 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4209 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004210 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004211}
4212
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004213void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00004214 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004215 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004216 if (!CGF.HaveInsertPoint())
4217 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004218 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
4219 // kmp_int32 cncl_kind);
4220 if (auto *OMPRegionInfo =
4221 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004222 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
4223 PrePostActionTy &) {
4224 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00004225 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004226 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00004227 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
4228 // Ignore return result until untied tasks are supported.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004229 auto *Result = CGF.EmitRuntimeCall(
4230 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00004231 // if (__kmpc_cancel()) {
4232 // __kmpc_cancel_barrier();
4233 // exit from construct;
4234 // }
4235 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4236 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4237 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4238 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4239 CGF.EmitBlock(ExitBB);
4240 // __kmpc_cancel_barrier();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004241 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev87933c72015-09-18 08:07:34 +00004242 // exit from construct;
4243 auto CancelDest =
4244 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
4245 CGF.EmitBranchThroughCleanup(CancelDest);
4246 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4247 };
4248 if (IfCond)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004249 emitOMPIfClause(CGF, IfCond, ThenGen,
4250 [](CodeGenFunction &, PrePostActionTy &) {});
4251 else {
4252 RegionCodeGenTy ThenRCG(ThenGen);
4253 ThenRCG(CGF);
4254 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004255 }
4256}
Samuel Antaobed3c462015-10-02 16:14:20 +00004257
Samuel Antaoee8fb302016-01-06 13:42:12 +00004258/// \brief Obtain information that uniquely identifies a target entry. This
Samuel Antao2de62b02016-02-13 23:35:10 +00004259/// consists of the file and device IDs as well as line number associated with
4260/// the relevant entry source location.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004261static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
4262 unsigned &DeviceID, unsigned &FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004263 unsigned &LineNum) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004264
4265 auto &SM = C.getSourceManager();
4266
4267 // The loc should be always valid and have a file ID (the user cannot use
4268 // #pragma directives in macros)
4269
4270 assert(Loc.isValid() && "Source location is expected to be always valid.");
4271 assert(Loc.isFileID() && "Source location is expected to refer to a file.");
4272
4273 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
4274 assert(PLoc.isValid() && "Source location is expected to be always valid.");
4275
4276 llvm::sys::fs::UniqueID ID;
4277 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
4278 llvm_unreachable("Source file with target region no longer exists!");
4279
4280 DeviceID = ID.getDevice();
4281 FileID = ID.getFile();
4282 LineNum = PLoc.getLine();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004283}
4284
4285void CGOpenMPRuntime::emitTargetOutlinedFunction(
4286 const OMPExecutableDirective &D, StringRef ParentName,
4287 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004288 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004289 assert(!ParentName.empty() && "Invalid target region parent name!");
4290
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004291 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
4292 IsOffloadEntry, CodeGen);
4293}
4294
4295void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
4296 const OMPExecutableDirective &D, StringRef ParentName,
4297 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
4298 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004299 // Create a unique name for the entry function using the source location
4300 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004301 //
Samuel Antao2de62b02016-02-13 23:35:10 +00004302 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00004303 //
4304 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00004305 // mangled name of the function that encloses the target region and BB is the
4306 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004307
4308 unsigned DeviceID;
4309 unsigned FileID;
4310 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004311 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004312 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004313 SmallString<64> EntryFnName;
4314 {
4315 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00004316 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
4317 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004318 }
4319
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004320 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4321
Samuel Antaobed3c462015-10-02 16:14:20 +00004322 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004323 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00004324 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004325
4326 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
4327
4328 // If this target outline function is not an offload entry, we don't need to
4329 // register it.
4330 if (!IsOffloadEntry)
4331 return;
4332
4333 // The target region ID is used by the runtime library to identify the current
4334 // target region, so it only has to be unique and not necessarily point to
4335 // anything. It could be the pointer to the outlined function that implements
4336 // the target region, but we aren't using that so that the compiler doesn't
4337 // need to keep that, and could therefore inline the host function if proven
4338 // worthwhile during optimization. In the other hand, if emitting code for the
4339 // device, the ID has to be the function address so that it can retrieved from
4340 // the offloading entry and launched by the runtime library. We also mark the
4341 // outlined function to have external linkage in case we are emitting code for
4342 // the device, because these functions will be entry points to the device.
4343
4344 if (CGM.getLangOpts().OpenMPIsDevice) {
4345 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
4346 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage);
4347 } else
4348 OutlinedFnID = new llvm::GlobalVariable(
4349 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
4350 llvm::GlobalValue::PrivateLinkage,
4351 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id");
4352
4353 // Register the information for the entry associated with this target region.
4354 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00004355 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID);
Samuel Antaobed3c462015-10-02 16:14:20 +00004356}
4357
Samuel Antaob68e2db2016-03-03 16:20:23 +00004358/// \brief Emit the num_teams clause of an enclosed teams directive at the
4359/// target region scope. If there is no teams directive associated with the
4360/// target directive, or if there is no num_teams clause associated with the
4361/// enclosed teams directive, return nullptr.
4362static llvm::Value *
4363emitNumTeamsClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4364 CodeGenFunction &CGF,
4365 const OMPExecutableDirective &D) {
4366
4367 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4368 "teams directive expected to be "
4369 "emitted only for the host!");
4370
4371 // FIXME: For the moment we do not support combined directives with target and
4372 // teams, so we do not expect to get any num_teams clause in the provided
4373 // directive. Once we support that, this assertion can be replaced by the
4374 // actual emission of the clause expression.
4375 assert(D.getSingleClause<OMPNumTeamsClause>() == nullptr &&
4376 "Not expecting clause in directive.");
4377
4378 // If the current target region has a teams region enclosed, we need to get
4379 // the number of teams to pass to the runtime function call. This is done
4380 // by generating the expression in a inlined region. This is required because
4381 // the expression is captured in the enclosing target environment when the
4382 // teams directive is not combined with target.
4383
4384 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4385
4386 // FIXME: Accommodate other combined directives with teams when they become
4387 // available.
4388 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) {
4389 if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) {
4390 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4391 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4392 llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams());
4393 return CGF.Builder.CreateIntCast(NumTeams, CGF.Int32Ty,
4394 /*IsSigned=*/true);
4395 }
4396
4397 // If we have an enclosed teams directive but no num_teams clause we use
4398 // the default value 0.
4399 return CGF.Builder.getInt32(0);
4400 }
4401
4402 // No teams associated with the directive.
4403 return nullptr;
4404}
4405
4406/// \brief Emit the thread_limit clause of an enclosed teams directive at the
4407/// target region scope. If there is no teams directive associated with the
4408/// target directive, or if there is no thread_limit clause associated with the
4409/// enclosed teams directive, return nullptr.
4410static llvm::Value *
4411emitThreadLimitClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4412 CodeGenFunction &CGF,
4413 const OMPExecutableDirective &D) {
4414
4415 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4416 "teams directive expected to be "
4417 "emitted only for the host!");
4418
4419 // FIXME: For the moment we do not support combined directives with target and
4420 // teams, so we do not expect to get any thread_limit clause in the provided
4421 // directive. Once we support that, this assertion can be replaced by the
4422 // actual emission of the clause expression.
4423 assert(D.getSingleClause<OMPThreadLimitClause>() == nullptr &&
4424 "Not expecting clause in directive.");
4425
4426 // If the current target region has a teams region enclosed, we need to get
4427 // the thread limit to pass to the runtime function call. This is done
4428 // by generating the expression in a inlined region. This is required because
4429 // the expression is captured in the enclosing target environment when the
4430 // teams directive is not combined with target.
4431
4432 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4433
4434 // FIXME: Accommodate other combined directives with teams when they become
4435 // available.
4436 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) {
4437 if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) {
4438 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4439 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4440 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit());
4441 return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty,
4442 /*IsSigned=*/true);
4443 }
4444
4445 // If we have an enclosed teams directive but no thread_limit clause we use
4446 // the default value 0.
4447 return CGF.Builder.getInt32(0);
4448 }
4449
4450 // No teams associated with the directive.
4451 return nullptr;
4452}
4453
Samuel Antaobed3c462015-10-02 16:14:20 +00004454void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
4455 const OMPExecutableDirective &D,
4456 llvm::Value *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00004457 llvm::Value *OutlinedFnID,
Samuel Antaobed3c462015-10-02 16:14:20 +00004458 const Expr *IfCond, const Expr *Device,
4459 ArrayRef<llvm::Value *> CapturedVars) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004460 if (!CGF.HaveInsertPoint())
4461 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00004462 /// \brief Values for bit flags used to specify the mapping type for
4463 /// offloading.
4464 enum OpenMPOffloadMappingFlags {
4465 /// \brief Allocate memory on the device and move data from host to device.
4466 OMP_MAP_TO = 0x01,
4467 /// \brief Allocate memory on the device and move data from device to host.
4468 OMP_MAP_FROM = 0x02,
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004469 /// \brief The element passed to the device is a pointer.
4470 OMP_MAP_PTR = 0x20,
4471 /// \brief Pass the element to the device by value.
4472 OMP_MAP_BYCOPY = 0x80,
Samuel Antaobed3c462015-10-02 16:14:20 +00004473 };
4474
4475 enum OpenMPOffloadingReservedDeviceIDs {
4476 /// \brief Device ID if the device was not defined, runtime should get it
4477 /// from environment variables in the spec.
4478 OMP_DEVICEID_UNDEF = -1,
4479 };
4480
Samuel Antaoee8fb302016-01-06 13:42:12 +00004481 assert(OutlinedFn && "Invalid outlined function!");
4482
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004483 auto &Ctx = CGF.getContext();
4484
Samuel Antaobed3c462015-10-02 16:14:20 +00004485 // Fill up the arrays with the all the captured variables.
4486 SmallVector<llvm::Value *, 16> BasePointers;
4487 SmallVector<llvm::Value *, 16> Pointers;
4488 SmallVector<llvm::Value *, 16> Sizes;
4489 SmallVector<unsigned, 16> MapTypes;
4490
4491 bool hasVLACaptures = false;
4492
4493 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4494 auto RI = CS.getCapturedRecordDecl()->field_begin();
4495 // auto II = CS.capture_init_begin();
4496 auto CV = CapturedVars.begin();
4497 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
4498 CE = CS.capture_end();
4499 CI != CE; ++CI, ++RI, ++CV) {
4500 StringRef Name;
4501 QualType Ty;
4502 llvm::Value *BasePointer;
4503 llvm::Value *Pointer;
4504 llvm::Value *Size;
4505 unsigned MapType;
4506
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004507 // VLA sizes are passed to the outlined region by copy.
Samuel Antaobed3c462015-10-02 16:14:20 +00004508 if (CI->capturesVariableArrayType()) {
4509 BasePointer = Pointer = *CV;
Alexey Bataev1189bd02016-01-26 12:20:39 +00004510 Size = CGF.getTypeSize(RI->getType());
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004511 // Copy to the device as an argument. No need to retrieve it.
4512 MapType = OMP_MAP_BYCOPY;
Samuel Antaobed3c462015-10-02 16:14:20 +00004513 hasVLACaptures = true;
Samuel Antaobed3c462015-10-02 16:14:20 +00004514 } else if (CI->capturesThis()) {
4515 BasePointer = Pointer = *CV;
4516 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr());
Alexey Bataev1189bd02016-01-26 12:20:39 +00004517 Size = CGF.getTypeSize(PtrTy->getPointeeType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004518 // Default map type.
4519 MapType = OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004520 } else if (CI->capturesVariableByCopy()) {
4521 MapType = OMP_MAP_BYCOPY;
4522 if (!RI->getType()->isAnyPointerType()) {
4523 // If the field is not a pointer, we need to save the actual value and
4524 // load it as a void pointer.
4525 auto DstAddr = CGF.CreateMemTemp(
4526 Ctx.getUIntPtrType(),
4527 Twine(CI->getCapturedVar()->getName()) + ".casted");
4528 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
4529
4530 auto *SrcAddrVal = CGF.EmitScalarConversion(
4531 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
4532 Ctx.getPointerType(RI->getType()), SourceLocation());
4533 LValue SrcLV =
4534 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType());
4535
4536 // Store the value using the source type pointer.
4537 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV);
4538
4539 // Load the value using the destination type pointer.
4540 BasePointer = Pointer =
4541 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
4542 } else {
4543 MapType |= OMP_MAP_PTR;
4544 BasePointer = Pointer = *CV;
4545 }
Alexey Bataev1189bd02016-01-26 12:20:39 +00004546 Size = CGF.getTypeSize(RI->getType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004547 } else {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004548 assert(CI->capturesVariable() && "Expected captured reference.");
Samuel Antaobed3c462015-10-02 16:14:20 +00004549 BasePointer = Pointer = *CV;
4550
4551 const ReferenceType *PtrTy =
4552 cast<ReferenceType>(RI->getType().getTypePtr());
4553 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00004554 Size = CGF.getTypeSize(ElementType);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004555 // The default map type for a scalar/complex type is 'to' because by
4556 // default the value doesn't have to be retrieved. For an aggregate type,
4557 // the default is 'tofrom'.
4558 MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
4559 : OMP_MAP_TO;
4560 if (ElementType->isAnyPointerType())
4561 MapType |= OMP_MAP_PTR;
Samuel Antaobed3c462015-10-02 16:14:20 +00004562 }
4563
4564 BasePointers.push_back(BasePointer);
4565 Pointers.push_back(Pointer);
4566 Sizes.push_back(Size);
4567 MapTypes.push_back(MapType);
4568 }
4569
4570 // Keep track on whether the host function has to be executed.
4571 auto OffloadErrorQType =
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004572 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004573 auto OffloadError = CGF.MakeAddrLValue(
4574 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
4575 OffloadErrorQType);
4576 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
4577 OffloadError);
4578
4579 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004580 auto &&ThenGen = [&Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes,
Alexey Bataevf539faa2016-03-28 12:58:34 +00004581 hasVLACaptures, Device, OutlinedFnID, OffloadError,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004582 OffloadErrorQType,
4583 &D](CodeGenFunction &CGF, PrePostActionTy &) {
4584 auto &RT = CGF.CGM.getOpenMPRuntime();
Samuel Antaobed3c462015-10-02 16:14:20 +00004585 unsigned PointerNumVal = BasePointers.size();
4586 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal);
4587 llvm::Value *BasePointersArray;
4588 llvm::Value *PointersArray;
4589 llvm::Value *SizesArray;
4590 llvm::Value *MapTypesArray;
4591
4592 if (PointerNumVal) {
4593 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004594 QualType PointerArrayType = Ctx.getConstantArrayType(
4595 Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004596 /*IndexTypeQuals=*/0);
4597
4598 BasePointersArray =
4599 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
4600 PointersArray =
4601 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
4602
4603 // If we don't have any VLA types, we can use a constant array for the map
4604 // sizes, otherwise we need to fill up the arrays as we do for the
4605 // pointers.
4606 if (hasVLACaptures) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004607 QualType SizeArrayType = Ctx.getConstantArrayType(
4608 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004609 /*IndexTypeQuals=*/0);
4610 SizesArray =
4611 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
4612 } else {
4613 // We expect all the sizes to be constant, so we collect them to create
4614 // a constant array.
4615 SmallVector<llvm::Constant *, 16> ConstSizes;
4616 for (auto S : Sizes)
4617 ConstSizes.push_back(cast<llvm::Constant>(S));
4618
4619 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004620 llvm::ArrayType::get(CGF.CGM.SizeTy, ConstSizes.size()),
4621 ConstSizes);
Samuel Antaobed3c462015-10-02 16:14:20 +00004622 auto *SizesArrayGbl = new llvm::GlobalVariable(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004623 CGF.CGM.getModule(), SizesArrayInit->getType(),
Samuel Antaobed3c462015-10-02 16:14:20 +00004624 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4625 SizesArrayInit, ".offload_sizes");
4626 SizesArrayGbl->setUnnamedAddr(true);
4627 SizesArray = SizesArrayGbl;
4628 }
4629
4630 // The map types are always constant so we don't need to generate code to
4631 // fill arrays. Instead, we create an array constant.
4632 llvm::Constant *MapTypesArrayInit =
4633 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
4634 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004635 CGF.CGM.getModule(), MapTypesArrayInit->getType(),
Samuel Antaobed3c462015-10-02 16:14:20 +00004636 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4637 MapTypesArrayInit, ".offload_maptypes");
4638 MapTypesArrayGbl->setUnnamedAddr(true);
4639 MapTypesArray = MapTypesArrayGbl;
4640
4641 for (unsigned i = 0; i < PointerNumVal; ++i) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004642 llvm::Value *BPVal = BasePointers[i];
4643 if (BPVal->getType()->isPointerTy())
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004644 BPVal = CGF.Builder.CreateBitCast(BPVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004645 else {
4646 assert(BPVal->getType()->isIntegerTy() &&
4647 "If not a pointer, the value type must be an integer.");
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004648 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004649 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004650 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004651 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal),
Samuel Antaobed3c462015-10-02 16:14:20 +00004652 BasePointersArray, 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004653 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4654 CGF.Builder.CreateStore(BPVal, BPAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004655
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004656 llvm::Value *PVal = Pointers[i];
4657 if (PVal->getType()->isPointerTy())
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004658 PVal = CGF.Builder.CreateBitCast(PVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004659 else {
4660 assert(PVal->getType()->isIntegerTy() &&
4661 "If not a pointer, the value type must be an integer.");
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004662 PVal = CGF.Builder.CreateIntToPtr(PVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004663 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004664 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004665 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), PointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004666 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004667 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4668 CGF.Builder.CreateStore(PVal, PAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004669
4670 if (hasVLACaptures) {
4671 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004672 llvm::ArrayType::get(CGF.SizeTy, PointerNumVal), SizesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004673 /*Idx0=*/0,
4674 /*Idx1=*/i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004675 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
Samuel Antaobed3c462015-10-02 16:14:20 +00004676 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004677 Sizes[i], CGF.SizeTy, /*isSigned=*/true),
Samuel Antaobed3c462015-10-02 16:14:20 +00004678 SAddr);
4679 }
4680 }
4681
4682 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004683 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), BasePointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004684 /*Idx0=*/0, /*Idx1=*/0);
4685 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004686 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), PointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004687 /*Idx0=*/0,
4688 /*Idx1=*/0);
4689 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004690 llvm::ArrayType::get(CGF.SizeTy, PointerNumVal), SizesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004691 /*Idx0=*/0, /*Idx1=*/0);
4692 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004693 llvm::ArrayType::get(CGF.Int32Ty, PointerNumVal), MapTypesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004694 /*Idx0=*/0,
4695 /*Idx1=*/0);
4696
4697 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004698 BasePointersArray = llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy);
4699 PointersArray = llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy);
4700 SizesArray = llvm::ConstantPointerNull::get(CGF.SizeTy->getPointerTo());
Samuel Antaobed3c462015-10-02 16:14:20 +00004701 MapTypesArray =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004702 llvm::ConstantPointerNull::get(CGF.Int32Ty->getPointerTo());
Samuel Antaobed3c462015-10-02 16:14:20 +00004703 }
4704
4705 // On top of the arrays that were filled up, the target offloading call
4706 // takes as arguments the device id as well as the host pointer. The host
4707 // pointer is used by the runtime library to identify the current target
4708 // region, so it only has to be unique and not necessarily point to
4709 // anything. It could be the pointer to the outlined function that
4710 // implements the target region, but we aren't using that so that the
4711 // compiler doesn't need to keep that, and could therefore inline the host
4712 // function if proven worthwhile during optimization.
4713
Samuel Antaoee8fb302016-01-06 13:42:12 +00004714 // From this point on, we need to have an ID of the target region defined.
4715 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00004716
4717 // Emit device ID if any.
4718 llvm::Value *DeviceID;
4719 if (Device)
4720 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004721 CGF.Int32Ty, /*isSigned=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004722 else
4723 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
4724
Samuel Antaob68e2db2016-03-03 16:20:23 +00004725 // Return value of the runtime offloading call.
4726 llvm::Value *Return;
4727
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004728 auto *NumTeams = emitNumTeamsClauseForTargetDirective(RT, CGF, D);
4729 auto *ThreadLimit = emitThreadLimitClauseForTargetDirective(RT, CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004730
4731 // If we have NumTeams defined this means that we have an enclosed teams
4732 // region. Therefore we also expect to have ThreadLimit defined. These two
4733 // values should be defined in the presence of a teams directive, regardless
4734 // of having any clauses associated. If the user is using teams but no
4735 // clauses, these two values will be the default that should be passed to
4736 // the runtime library - a 32-bit integer with the value zero.
4737 if (NumTeams) {
4738 assert(ThreadLimit && "Thread limit expression should be available along "
4739 "with number of teams.");
4740 llvm::Value *OffloadingArgs[] = {
4741 DeviceID, OutlinedFnID, PointerNum,
4742 BasePointersArray, PointersArray, SizesArray,
4743 MapTypesArray, NumTeams, ThreadLimit};
4744 Return = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004745 RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004746 } else {
4747 llvm::Value *OffloadingArgs[] = {
4748 DeviceID, OutlinedFnID, PointerNum, BasePointersArray,
4749 PointersArray, SizesArray, MapTypesArray};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004750 Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target),
Samuel Antaob68e2db2016-03-03 16:20:23 +00004751 OffloadingArgs);
4752 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004753
4754 CGF.EmitStoreOfScalar(Return, OffloadError);
4755 };
4756
Samuel Antaoee8fb302016-01-06 13:42:12 +00004757 // Notify that the host version must be executed.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004758 auto &&ElseGen = [OffloadError](CodeGenFunction &CGF, PrePostActionTy &) {
4759 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/-1u),
Samuel Antaoee8fb302016-01-06 13:42:12 +00004760 OffloadError);
4761 };
4762
4763 // If we have a target function ID it means that we need to support
4764 // offloading, otherwise, just execute on the host. We need to execute on host
4765 // regardless of the conditional in the if clause if, e.g., the user do not
4766 // specify target triples.
4767 if (OutlinedFnID) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004768 if (IfCond)
Samuel Antaoee8fb302016-01-06 13:42:12 +00004769 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004770 else {
4771 RegionCodeGenTy ThenRCG(ThenGen);
4772 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00004773 }
4774 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004775 RegionCodeGenTy ElseRCG(ElseGen);
4776 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00004777 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004778
4779 // Check the error code and execute the host version if required.
4780 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
4781 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
4782 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
4783 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
4784 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
4785
4786 CGF.EmitBlock(OffloadFailedBlock);
4787 CGF.Builder.CreateCall(OutlinedFn, BasePointers);
4788 CGF.EmitBranch(OffloadContBlock);
4789
4790 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004791}
Samuel Antaoee8fb302016-01-06 13:42:12 +00004792
4793void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
4794 StringRef ParentName) {
4795 if (!S)
4796 return;
4797
4798 // If we find a OMP target directive, codegen the outline function and
4799 // register the result.
4800 // FIXME: Add other directives with target when they become supported.
4801 bool isTargetDirective = isa<OMPTargetDirective>(S);
4802
4803 if (isTargetDirective) {
4804 auto *E = cast<OMPExecutableDirective>(S);
4805 unsigned DeviceID;
4806 unsigned FileID;
4807 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004808 getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004809 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004810
4811 // Is this a target region that should not be emitted as an entry point? If
4812 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00004813 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
4814 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004815 return;
4816
4817 llvm::Function *Fn;
4818 llvm::Constant *Addr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004819 std::tie(Fn, Addr) =
4820 CodeGenFunction::EmitOMPTargetDirectiveOutlinedFunction(
4821 CGM, cast<OMPTargetDirective>(*E), ParentName,
4822 /*isOffloadEntry=*/true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004823 assert(Fn && Addr && "Target region emission failed.");
4824 return;
4825 }
4826
4827 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) {
4828 if (!E->getAssociatedStmt())
4829 return;
4830
4831 scanForTargetRegionsFunctions(
4832 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(),
4833 ParentName);
4834 return;
4835 }
4836
4837 // If this is a lambda function, look into its body.
4838 if (auto *L = dyn_cast<LambdaExpr>(S))
4839 S = L->getBody();
4840
4841 // Keep looking for target regions recursively.
4842 for (auto *II : S->children())
4843 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004844}
4845
4846bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
4847 auto &FD = *cast<FunctionDecl>(GD.getDecl());
4848
4849 // If emitting code for the host, we do not process FD here. Instead we do
4850 // the normal code generation.
4851 if (!CGM.getLangOpts().OpenMPIsDevice)
4852 return false;
4853
4854 // Try to detect target regions in the function.
4855 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
4856
4857 // We should not emit any function othen that the ones created during the
4858 // scanning. Therefore, we signal that this function is completely dealt
4859 // with.
4860 return true;
4861}
4862
4863bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
4864 if (!CGM.getLangOpts().OpenMPIsDevice)
4865 return false;
4866
4867 // Check if there are Ctors/Dtors in this declaration and look for target
4868 // regions in it. We use the complete variant to produce the kernel name
4869 // mangling.
4870 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
4871 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
4872 for (auto *Ctor : RD->ctors()) {
4873 StringRef ParentName =
4874 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
4875 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
4876 }
4877 auto *Dtor = RD->getDestructor();
4878 if (Dtor) {
4879 StringRef ParentName =
4880 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
4881 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
4882 }
4883 }
4884
4885 // If we are in target mode we do not emit any global (declare target is not
4886 // implemented yet). Therefore we signal that GD was processed in this case.
4887 return true;
4888}
4889
4890bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
4891 auto *VD = GD.getDecl();
4892 if (isa<FunctionDecl>(VD))
4893 return emitTargetFunctions(GD);
4894
4895 return emitTargetGlobalVariable(GD);
4896}
4897
4898llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
4899 // If we have offloading in the current module, we need to emit the entries
4900 // now and register the offloading descriptor.
4901 createOffloadEntriesAndInfoMetadata();
4902
4903 // Create and register the offloading binary descriptors. This is the main
4904 // entity that captures all the information about offloading in the current
4905 // compilation unit.
4906 return createOffloadingBinaryDescriptorRegistration();
4907}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004908
4909void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
4910 const OMPExecutableDirective &D,
4911 SourceLocation Loc,
4912 llvm::Value *OutlinedFn,
4913 ArrayRef<llvm::Value *> CapturedVars) {
4914 if (!CGF.HaveInsertPoint())
4915 return;
4916
4917 auto *RTLoc = emitUpdateLocation(CGF, Loc);
4918 CodeGenFunction::RunCleanupsScope Scope(CGF);
4919
4920 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
4921 llvm::Value *Args[] = {
4922 RTLoc,
4923 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
4924 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
4925 llvm::SmallVector<llvm::Value *, 16> RealArgs;
4926 RealArgs.append(std::begin(Args), std::end(Args));
4927 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
4928
4929 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
4930 CGF.EmitRuntimeCall(RTLFn, RealArgs);
4931}
4932
4933void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00004934 const Expr *NumTeams,
4935 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004936 SourceLocation Loc) {
4937 if (!CGF.HaveInsertPoint())
4938 return;
4939
4940 auto *RTLoc = emitUpdateLocation(CGF, Loc);
4941
Carlo Bertollic6872252016-04-04 15:55:02 +00004942 llvm::Value *NumTeamsVal =
4943 (NumTeams)
4944 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
4945 CGF.CGM.Int32Ty, /* isSigned = */ true)
4946 : CGF.Builder.getInt32(0);
4947
4948 llvm::Value *ThreadLimitVal =
4949 (ThreadLimit)
4950 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
4951 CGF.CGM.Int32Ty, /* isSigned = */ true)
4952 : CGF.Builder.getInt32(0);
4953
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004954 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00004955 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
4956 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004957 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
4958 PushNumTeamsArgs);
4959}