blob: fb511ed3cd2731dd7fec891cffc97df74f402d16 [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;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000387 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
388 FieldDecl *LambdaThisCaptureField = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000389
390public:
391 /// \brief Constructs region for combined constructs.
392 /// \param CodeGen Code generation sequence for combined directives. Includes
393 /// a list of functions used for code generation of implicitly inlined
394 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000395 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000396 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000397 : CGF(CGF) {
398 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000399 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
400 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000401 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
402 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
403 CGF.LambdaThisCaptureField = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000404 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000405
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000406 ~InlinedOpenMPRegionRAII() {
407 // Restore original CapturedStmtInfo only if we're done with code emission.
408 auto *OldCSI =
409 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
410 delete CGF.CapturedStmtInfo;
411 CGF.CapturedStmtInfo = OldCSI;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000412 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
413 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000414 }
415};
416
Alexey Bataev50b3c952016-02-19 10:38:26 +0000417/// \brief Values for bit flags used in the ident_t to describe the fields.
418/// All enumeric elements are named and described in accordance with the code
419/// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
420enum OpenMPLocationFlags {
421 /// \brief Use trampoline for internal microtask.
422 OMP_IDENT_IMD = 0x01,
423 /// \brief Use c-style ident structure.
424 OMP_IDENT_KMPC = 0x02,
425 /// \brief Atomic reduction option for kmpc_reduce.
426 OMP_ATOMIC_REDUCE = 0x10,
427 /// \brief Explicit 'barrier' directive.
428 OMP_IDENT_BARRIER_EXPL = 0x20,
429 /// \brief Implicit barrier in code.
430 OMP_IDENT_BARRIER_IMPL = 0x40,
431 /// \brief Implicit barrier in 'for' directive.
432 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
433 /// \brief Implicit barrier in 'sections' directive.
434 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
435 /// \brief Implicit barrier in 'single' directive.
436 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140
437};
438
439/// \brief Describes ident structure that describes a source location.
440/// All descriptions are taken from
441/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
442/// Original structure:
443/// typedef struct ident {
444/// kmp_int32 reserved_1; /**< might be used in Fortran;
445/// see above */
446/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
447/// KMP_IDENT_KMPC identifies this union
448/// member */
449/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
450/// see above */
451///#if USE_ITT_BUILD
452/// /* but currently used for storing
453/// region-specific ITT */
454/// /* contextual information. */
455///#endif /* USE_ITT_BUILD */
456/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
457/// C++ */
458/// char const *psource; /**< String describing the source location.
459/// The string is composed of semi-colon separated
460// fields which describe the source file,
461/// the function and a pair of line numbers that
462/// delimit the construct.
463/// */
464/// } ident_t;
465enum IdentFieldIndex {
466 /// \brief might be used in Fortran
467 IdentField_Reserved_1,
468 /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
469 IdentField_Flags,
470 /// \brief Not really used in Fortran any more
471 IdentField_Reserved_2,
472 /// \brief Source[4] in Fortran, do not use for C++
473 IdentField_Reserved_3,
474 /// \brief String describing the source location. The string is composed of
475 /// semi-colon separated fields which describe the source file, the function
476 /// and a pair of line numbers that delimit the construct.
477 IdentField_PSource
478};
479
480/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
481/// the enum sched_type in kmp.h).
482enum OpenMPSchedType {
483 /// \brief Lower bound for default (unordered) versions.
484 OMP_sch_lower = 32,
485 OMP_sch_static_chunked = 33,
486 OMP_sch_static = 34,
487 OMP_sch_dynamic_chunked = 35,
488 OMP_sch_guided_chunked = 36,
489 OMP_sch_runtime = 37,
490 OMP_sch_auto = 38,
491 /// \brief Lower bound for 'ordered' versions.
492 OMP_ord_lower = 64,
493 OMP_ord_static_chunked = 65,
494 OMP_ord_static = 66,
495 OMP_ord_dynamic_chunked = 67,
496 OMP_ord_guided_chunked = 68,
497 OMP_ord_runtime = 69,
498 OMP_ord_auto = 70,
499 OMP_sch_default = OMP_sch_static,
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000500 /// \brief dist_schedule types
501 OMP_dist_sch_static_chunked = 91,
502 OMP_dist_sch_static = 92,
Alexey Bataev9ebd7422016-05-10 09:57:36 +0000503 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
504 /// Set if the monotonic schedule modifier was present.
505 OMP_sch_modifier_monotonic = (1 << 29),
506 /// Set if the nonmonotonic schedule modifier was present.
507 OMP_sch_modifier_nonmonotonic = (1 << 30),
Alexey Bataev50b3c952016-02-19 10:38:26 +0000508};
509
510enum OpenMPRTLFunction {
511 /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
512 /// kmpc_micro microtask, ...);
513 OMPRTL__kmpc_fork_call,
514 /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc,
515 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
516 OMPRTL__kmpc_threadprivate_cached,
517 /// \brief Call to void __kmpc_threadprivate_register( ident_t *,
518 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
519 OMPRTL__kmpc_threadprivate_register,
520 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
521 OMPRTL__kmpc_global_thread_num,
522 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
523 // kmp_critical_name *crit);
524 OMPRTL__kmpc_critical,
525 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
526 // global_tid, kmp_critical_name *crit, uintptr_t hint);
527 OMPRTL__kmpc_critical_with_hint,
528 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
529 // kmp_critical_name *crit);
530 OMPRTL__kmpc_end_critical,
531 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
532 // global_tid);
533 OMPRTL__kmpc_cancel_barrier,
534 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
535 OMPRTL__kmpc_barrier,
536 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
537 OMPRTL__kmpc_for_static_fini,
538 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
539 // global_tid);
540 OMPRTL__kmpc_serialized_parallel,
541 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
542 // global_tid);
543 OMPRTL__kmpc_end_serialized_parallel,
544 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
545 // kmp_int32 num_threads);
546 OMPRTL__kmpc_push_num_threads,
547 // Call to void __kmpc_flush(ident_t *loc);
548 OMPRTL__kmpc_flush,
549 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
550 OMPRTL__kmpc_master,
551 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
552 OMPRTL__kmpc_end_master,
553 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
554 // int end_part);
555 OMPRTL__kmpc_omp_taskyield,
556 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
557 OMPRTL__kmpc_single,
558 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
559 OMPRTL__kmpc_end_single,
560 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
561 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
562 // kmp_routine_entry_t *task_entry);
563 OMPRTL__kmpc_omp_task_alloc,
564 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
565 // new_task);
566 OMPRTL__kmpc_omp_task,
567 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
568 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
569 // kmp_int32 didit);
570 OMPRTL__kmpc_copyprivate,
571 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
572 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
573 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
574 OMPRTL__kmpc_reduce,
575 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
576 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
577 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
578 // *lck);
579 OMPRTL__kmpc_reduce_nowait,
580 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
581 // kmp_critical_name *lck);
582 OMPRTL__kmpc_end_reduce,
583 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
584 // kmp_critical_name *lck);
585 OMPRTL__kmpc_end_reduce_nowait,
586 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
587 // kmp_task_t * new_task);
588 OMPRTL__kmpc_omp_task_begin_if0,
589 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
590 // kmp_task_t * new_task);
591 OMPRTL__kmpc_omp_task_complete_if0,
592 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
593 OMPRTL__kmpc_ordered,
594 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
595 OMPRTL__kmpc_end_ordered,
596 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
597 // global_tid);
598 OMPRTL__kmpc_omp_taskwait,
599 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
600 OMPRTL__kmpc_taskgroup,
601 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
602 OMPRTL__kmpc_end_taskgroup,
603 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
604 // int proc_bind);
605 OMPRTL__kmpc_push_proc_bind,
606 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
607 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
608 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
609 OMPRTL__kmpc_omp_task_with_deps,
610 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
611 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
612 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
613 OMPRTL__kmpc_omp_wait_deps,
614 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
615 // global_tid, kmp_int32 cncl_kind);
616 OMPRTL__kmpc_cancellationpoint,
617 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
618 // kmp_int32 cncl_kind);
619 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000620 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
621 // kmp_int32 num_teams, kmp_int32 thread_limit);
622 OMPRTL__kmpc_push_num_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000623 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
624 // microtask, ...);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000625 OMPRTL__kmpc_fork_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000626 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
627 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
628 // sched, kmp_uint64 grainsize, void *task_dup);
629 OMPRTL__kmpc_taskloop,
Alexey Bataev8b427062016-05-25 12:36:08 +0000630 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
631 // num_dims, struct kmp_dim *dims);
632 OMPRTL__kmpc_doacross_init,
633 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
634 OMPRTL__kmpc_doacross_fini,
635 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
636 // *vec);
637 OMPRTL__kmpc_doacross_post,
638 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
639 // *vec);
640 OMPRTL__kmpc_doacross_wait,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000641
642 //
643 // Offloading related calls
644 //
645 // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
646 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
647 // *arg_types);
648 OMPRTL__tgt_target,
Samuel Antaob68e2db2016-03-03 16:20:23 +0000649 // Call to int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
650 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
651 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
652 OMPRTL__tgt_target_teams,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000653 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
654 OMPRTL__tgt_register_lib,
655 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
656 OMPRTL__tgt_unregister_lib,
Samuel Antaodf158d52016-04-27 22:58:19 +0000657 // Call to void __tgt_target_data_begin(int32_t device_id, int32_t arg_num,
658 // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types);
659 OMPRTL__tgt_target_data_begin,
660 // Call to void __tgt_target_data_end(int32_t device_id, int32_t arg_num,
661 // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types);
662 OMPRTL__tgt_target_data_end,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000663};
664
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000665/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
666/// region.
667class CleanupTy final : public EHScopeStack::Cleanup {
668 PrePostActionTy *Action;
669
670public:
671 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
672 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
673 if (!CGF.HaveInsertPoint())
674 return;
675 Action->Exit(CGF);
676 }
677};
678
Hans Wennborg7eb54642015-09-10 17:07:54 +0000679} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000680
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000681void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
682 CodeGenFunction::RunCleanupsScope Scope(CGF);
683 if (PrePostAction) {
684 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
685 Callback(CodeGen, CGF, *PrePostAction);
686 } else {
687 PrePostActionTy Action;
688 Callback(CodeGen, CGF, Action);
689 }
690}
691
Alexey Bataev18095712014-10-10 12:19:54 +0000692LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +0000693 return CGF.EmitLoadOfPointerLValue(
694 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
695 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +0000696}
697
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000698void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000699 if (!CGF.HaveInsertPoint())
700 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000701 // 1.2.2 OpenMP Language Terminology
702 // Structured block - An executable statement with a single entry at the
703 // top and a single exit at the bottom.
704 // The point of exit cannot be a branch out of the structured block.
705 // longjmp() and throw() must not violate the entry/exit criteria.
706 CGF.EHStack.pushTerminate();
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000707 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000708 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000709}
710
Alexey Bataev62b63b12015-03-10 07:28:44 +0000711LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
712 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000713 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
714 getThreadIDVariable()->getType(),
715 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000716}
717
Alexey Bataev9959db52014-05-06 10:08:46 +0000718CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000719 : CGM(CGM), OffloadEntriesInfoManager(CGM) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000720 IdentTy = llvm::StructType::create(
721 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
722 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000723 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000724 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +0000725
726 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +0000727}
728
Alexey Bataev91797552015-03-18 04:13:55 +0000729void CGOpenMPRuntime::clear() {
730 InternalVars.clear();
731}
732
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000733static llvm::Function *
734emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
735 const Expr *CombinerInitializer, const VarDecl *In,
736 const VarDecl *Out, bool IsCombiner) {
737 // void .omp_combiner.(Ty *in, Ty *out);
738 auto &C = CGM.getContext();
739 QualType PtrTy = C.getPointerType(Ty).withRestrict();
740 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000741 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
742 /*Id=*/nullptr, PtrTy);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000743 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
744 /*Id=*/nullptr, PtrTy);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000745 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000746 Args.push_back(&OmpInParm);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000747 auto &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +0000748 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000749 auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
750 auto *Fn = llvm::Function::Create(
751 FnTy, llvm::GlobalValue::InternalLinkage,
752 IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
753 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000754 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000755 CodeGenFunction CGF(CGM);
756 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
757 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
758 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args);
759 CodeGenFunction::OMPPrivateScope Scope(CGF);
760 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
761 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() -> Address {
762 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
763 .getAddress();
764 });
765 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
766 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() -> Address {
767 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
768 .getAddress();
769 });
770 (void)Scope.Privatize();
771 CGF.EmitIgnoredExpr(CombinerInitializer);
772 Scope.ForceCleanup();
773 CGF.FinishFunction();
774 return Fn;
775}
776
777void CGOpenMPRuntime::emitUserDefinedReduction(
778 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
779 if (UDRMap.count(D) > 0)
780 return;
781 auto &C = CGM.getContext();
782 if (!In || !Out) {
783 In = &C.Idents.get("omp_in");
784 Out = &C.Idents.get("omp_out");
785 }
786 llvm::Function *Combiner = emitCombinerOrInitializer(
787 CGM, D->getType(), D->getCombiner(), cast<VarDecl>(D->lookup(In).front()),
788 cast<VarDecl>(D->lookup(Out).front()),
789 /*IsCombiner=*/true);
790 llvm::Function *Initializer = nullptr;
791 if (auto *Init = D->getInitializer()) {
792 if (!Priv || !Orig) {
793 Priv = &C.Idents.get("omp_priv");
794 Orig = &C.Idents.get("omp_orig");
795 }
796 Initializer = emitCombinerOrInitializer(
797 CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()),
798 cast<VarDecl>(D->lookup(Priv).front()),
799 /*IsCombiner=*/false);
800 }
801 UDRMap.insert(std::make_pair(D, std::make_pair(Combiner, Initializer)));
802 if (CGF) {
803 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
804 Decls.second.push_back(D);
805 }
806}
807
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000808std::pair<llvm::Function *, llvm::Function *>
809CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
810 auto I = UDRMap.find(D);
811 if (I != UDRMap.end())
812 return I->second;
813 emitUserDefinedReduction(/*CGF=*/nullptr, D);
814 return UDRMap.lookup(D);
815}
816
John McCall7f416cc2015-09-08 08:05:57 +0000817// Layout information for ident_t.
818static CharUnits getIdentAlign(CodeGenModule &CGM) {
819 return CGM.getPointerAlign();
820}
821static CharUnits getIdentSize(CodeGenModule &CGM) {
822 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign()));
823 return CharUnits::fromQuantity(16) + CGM.getPointerSize();
824}
Alexey Bataev50b3c952016-02-19 10:38:26 +0000825static CharUnits getOffsetOfIdentField(IdentFieldIndex Field) {
John McCall7f416cc2015-09-08 08:05:57 +0000826 // All the fields except the last are i32, so this works beautifully.
827 return unsigned(Field) * CharUnits::fromQuantity(4);
828}
829static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000830 IdentFieldIndex Field,
John McCall7f416cc2015-09-08 08:05:57 +0000831 const llvm::Twine &Name = "") {
832 auto Offset = getOffsetOfIdentField(Field);
833 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
834}
835
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000836llvm::Value *CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000837 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
838 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000839 assert(ThreadIDVar->getType()->isPointerType() &&
840 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +0000841 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
842 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +0000843 bool HasCancel = false;
844 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
845 HasCancel = OPD->hasCancel();
846 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
847 HasCancel = OPSD->hasCancel();
848 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
849 HasCancel = OPFD->hasCancel();
850 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
851 HasCancel);
Alexey Bataevd157d472015-06-24 03:35:38 +0000852 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000853 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +0000854}
855
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000856llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
857 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000858 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
859 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
860 bool Tied, unsigned &NumberOfParts) {
861 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
862 PrePostActionTy &) {
863 auto *ThreadID = getThreadID(CGF, D.getLocStart());
864 auto *UpLoc = emitUpdateLocation(CGF, D.getLocStart());
865 llvm::Value *TaskArgs[] = {
866 UpLoc, ThreadID,
867 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
868 TaskTVar->getType()->castAs<PointerType>())
869 .getPointer()};
870 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
871 };
872 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
873 UntiedCodeGen);
874 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000875 assert(!ThreadIDVar->getType()->isPointerType() &&
876 "thread id variable must be of type kmp_int32 for tasks");
877 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
Alexey Bataev7292c292016-04-25 12:22:29 +0000878 auto *TD = dyn_cast<OMPTaskDirective>(&D);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000879 CodeGenFunction CGF(CGM, true);
Alexey Bataev7292c292016-04-25 12:22:29 +0000880 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
881 InnermostKind,
882 TD ? TD->hasCancel() : false, Action);
Alexey Bataevd157d472015-06-24 03:35:38 +0000883 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev48591dd2016-04-20 04:01:36 +0000884 auto *Res = CGF.GenerateCapturedStmtFunction(*CS);
885 if (!Tied)
886 NumberOfParts = Action.getNumberOfParts();
887 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000888}
889
Alexey Bataev50b3c952016-02-19 10:38:26 +0000890Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
John McCall7f416cc2015-09-08 08:05:57 +0000891 CharUnits Align = getIdentAlign(CGM);
Alexey Bataev15007ba2014-05-07 06:18:01 +0000892 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000893 if (!Entry) {
894 if (!DefaultOpenMPPSource) {
895 // Initialize default location for psource field of ident_t structure of
896 // all ident_t objects. Format is ";file;function;line;column;;".
897 // Taken from
898 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
899 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +0000900 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000901 DefaultOpenMPPSource =
902 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
903 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000904 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
905 CGM.getModule(), IdentTy, /*isConstant*/ true,
906 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000907 DefaultOpenMPLocation->setUnnamedAddr(true);
John McCall7f416cc2015-09-08 08:05:57 +0000908 DefaultOpenMPLocation->setAlignment(Align.getQuantity());
Alexey Bataev9959db52014-05-06 10:08:46 +0000909
910 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000911 llvm::Constant *Values[] = {Zero,
912 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
913 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000914 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
915 DefaultOpenMPLocation->setInitializer(Init);
John McCall7f416cc2015-09-08 08:05:57 +0000916 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000917 }
John McCall7f416cc2015-09-08 08:05:57 +0000918 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +0000919}
920
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000921llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
922 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000923 unsigned Flags) {
924 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +0000925 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +0000926 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +0000927 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +0000928 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000929
930 assert(CGF.CurFn && "No function in current CodeGenFunction.");
931
John McCall7f416cc2015-09-08 08:05:57 +0000932 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000933 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
934 if (I != OpenMPLocThreadIDMap.end())
John McCall7f416cc2015-09-08 08:05:57 +0000935 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
936
Alexander Musmanc6388682014-12-15 07:07:06 +0000937 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
938 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +0000939 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000940 // Generate "ident_t .kmpc_loc.addr;"
John McCall7f416cc2015-09-08 08:05:57 +0000941 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
942 ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +0000943 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +0000944 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000945 LocValue = AI;
946
947 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
948 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000949 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
John McCall7f416cc2015-09-08 08:05:57 +0000950 CGM.getSize(getIdentSize(CGF.CGM)));
Alexey Bataev9959db52014-05-06 10:08:46 +0000951 }
952
953 // char **psource = &.kmpc_loc_<flags>.addr.psource;
John McCall7f416cc2015-09-08 08:05:57 +0000954 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000955
Alexey Bataevf002aca2014-05-30 05:48:40 +0000956 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
957 if (OMPDebugLoc == nullptr) {
958 SmallString<128> Buffer2;
959 llvm::raw_svector_ostream OS2(Buffer2);
960 // Build debug location
961 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
962 OS2 << ";" << PLoc.getFilename() << ";";
963 if (const FunctionDecl *FD =
964 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
965 OS2 << FD->getQualifiedNameAsString();
966 }
967 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
968 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
969 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000970 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000971 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000972 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
973
John McCall7f416cc2015-09-08 08:05:57 +0000974 // Our callers always pass this to a runtime function, so for
975 // convenience, go ahead and return a naked pointer.
976 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000977}
978
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000979llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
980 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000981 assert(CGF.CurFn && "No function in current CodeGenFunction.");
982
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000983 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000984 // Check whether we've already cached a load of the thread id in this
985 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000986 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000987 if (I != OpenMPLocThreadIDMap.end()) {
988 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000989 if (ThreadID != nullptr)
990 return ThreadID;
991 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +0000992 if (auto *OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000993 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000994 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000995 // Check if this an outlined function with thread id passed as argument.
996 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000997 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
998 // If value loaded in entry block, cache it and use it everywhere in
999 // function.
1000 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
1001 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1002 Elem.second.ThreadID = ThreadID;
1003 }
1004 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +00001005 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001006 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001007
1008 // This is not an outlined function region - need to call __kmpc_int32
1009 // kmpc_global_thread_num(ident_t *loc).
1010 // Generate thread id value and cache this value for use across the
1011 // function.
1012 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1013 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
1014 ThreadID =
1015 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1016 emitUpdateLocation(CGF, Loc));
1017 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1018 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001019 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +00001020}
1021
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001022void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001023 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +00001024 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
1025 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001026 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
1027 for(auto *D : FunctionUDRMap[CGF.CurFn]) {
1028 UDRMap.erase(D);
1029 }
1030 FunctionUDRMap.erase(CGF.CurFn);
1031 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001032}
1033
1034llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001035 if (!IdentTy) {
1036 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001037 return llvm::PointerType::getUnqual(IdentTy);
1038}
1039
1040llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001041 if (!Kmpc_MicroTy) {
1042 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1043 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1044 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1045 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1046 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001047 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1048}
1049
1050llvm::Constant *
Alexey Bataev50b3c952016-02-19 10:38:26 +00001051CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001052 llvm::Constant *RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001053 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001054 case OMPRTL__kmpc_fork_call: {
1055 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1056 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001057 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1058 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +00001059 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001060 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001061 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
1062 break;
1063 }
1064 case OMPRTL__kmpc_global_thread_num: {
1065 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001066 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +00001067 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001068 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001069 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1070 break;
1071 }
Alexey Bataev97720002014-11-11 04:05:39 +00001072 case OMPRTL__kmpc_threadprivate_cached: {
1073 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1074 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1075 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1076 CGM.VoidPtrTy, CGM.SizeTy,
1077 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
1078 llvm::FunctionType *FnTy =
1079 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1080 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1081 break;
1082 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001083 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001084 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1085 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001086 llvm::Type *TypeParams[] = {
1087 getIdentTyPointerTy(), CGM.Int32Ty,
1088 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1089 llvm::FunctionType *FnTy =
1090 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1091 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1092 break;
1093 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001094 case OMPRTL__kmpc_critical_with_hint: {
1095 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1096 // kmp_critical_name *crit, uintptr_t hint);
1097 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1098 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1099 CGM.IntPtrTy};
1100 llvm::FunctionType *FnTy =
1101 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1102 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1103 break;
1104 }
Alexey Bataev97720002014-11-11 04:05:39 +00001105 case OMPRTL__kmpc_threadprivate_register: {
1106 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1107 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1108 // typedef void *(*kmpc_ctor)(void *);
1109 auto KmpcCtorTy =
1110 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1111 /*isVarArg*/ false)->getPointerTo();
1112 // typedef void *(*kmpc_cctor)(void *, void *);
1113 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1114 auto KmpcCopyCtorTy =
1115 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
1116 /*isVarArg*/ false)->getPointerTo();
1117 // typedef void (*kmpc_dtor)(void *);
1118 auto KmpcDtorTy =
1119 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1120 ->getPointerTo();
1121 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1122 KmpcCopyCtorTy, KmpcDtorTy};
1123 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
1124 /*isVarArg*/ false);
1125 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1126 break;
1127 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001128 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001129 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1130 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001131 llvm::Type *TypeParams[] = {
1132 getIdentTyPointerTy(), CGM.Int32Ty,
1133 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1134 llvm::FunctionType *FnTy =
1135 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1136 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1137 break;
1138 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001139 case OMPRTL__kmpc_cancel_barrier: {
1140 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1141 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001142 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1143 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001144 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1145 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001146 break;
1147 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001148 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001149 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001150 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1151 llvm::FunctionType *FnTy =
1152 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1153 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1154 break;
1155 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001156 case OMPRTL__kmpc_for_static_fini: {
1157 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1158 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1159 llvm::FunctionType *FnTy =
1160 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1161 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1162 break;
1163 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001164 case OMPRTL__kmpc_push_num_threads: {
1165 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1166 // kmp_int32 num_threads)
1167 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1168 CGM.Int32Ty};
1169 llvm::FunctionType *FnTy =
1170 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1171 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1172 break;
1173 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001174 case OMPRTL__kmpc_serialized_parallel: {
1175 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1176 // global_tid);
1177 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1178 llvm::FunctionType *FnTy =
1179 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1180 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1181 break;
1182 }
1183 case OMPRTL__kmpc_end_serialized_parallel: {
1184 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1185 // global_tid);
1186 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1187 llvm::FunctionType *FnTy =
1188 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1189 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1190 break;
1191 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001192 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001193 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001194 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
1195 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001196 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001197 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1198 break;
1199 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001200 case OMPRTL__kmpc_master: {
1201 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1202 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1203 llvm::FunctionType *FnTy =
1204 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1205 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1206 break;
1207 }
1208 case OMPRTL__kmpc_end_master: {
1209 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1210 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1211 llvm::FunctionType *FnTy =
1212 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1213 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1214 break;
1215 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001216 case OMPRTL__kmpc_omp_taskyield: {
1217 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1218 // int end_part);
1219 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1220 llvm::FunctionType *FnTy =
1221 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1222 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1223 break;
1224 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001225 case OMPRTL__kmpc_single: {
1226 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1227 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1228 llvm::FunctionType *FnTy =
1229 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1230 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1231 break;
1232 }
1233 case OMPRTL__kmpc_end_single: {
1234 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1235 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1236 llvm::FunctionType *FnTy =
1237 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1238 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1239 break;
1240 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001241 case OMPRTL__kmpc_omp_task_alloc: {
1242 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1243 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1244 // kmp_routine_entry_t *task_entry);
1245 assert(KmpRoutineEntryPtrTy != nullptr &&
1246 "Type kmp_routine_entry_t must be created.");
1247 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1248 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1249 // Return void * and then cast to particular kmp_task_t type.
1250 llvm::FunctionType *FnTy =
1251 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1252 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1253 break;
1254 }
1255 case OMPRTL__kmpc_omp_task: {
1256 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1257 // *new_task);
1258 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1259 CGM.VoidPtrTy};
1260 llvm::FunctionType *FnTy =
1261 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1262 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
1263 break;
1264 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001265 case OMPRTL__kmpc_copyprivate: {
1266 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00001267 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001268 // kmp_int32 didit);
1269 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1270 auto *CpyFnTy =
1271 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001272 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001273 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
1274 CGM.Int32Ty};
1275 llvm::FunctionType *FnTy =
1276 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1277 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
1278 break;
1279 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001280 case OMPRTL__kmpc_reduce: {
1281 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
1282 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
1283 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
1284 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1285 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1286 /*isVarArg=*/false);
1287 llvm::Type *TypeParams[] = {
1288 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1289 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1290 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1291 llvm::FunctionType *FnTy =
1292 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1293 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
1294 break;
1295 }
1296 case OMPRTL__kmpc_reduce_nowait: {
1297 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
1298 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
1299 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
1300 // *lck);
1301 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1302 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1303 /*isVarArg=*/false);
1304 llvm::Type *TypeParams[] = {
1305 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1306 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1307 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1308 llvm::FunctionType *FnTy =
1309 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1310 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
1311 break;
1312 }
1313 case OMPRTL__kmpc_end_reduce: {
1314 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
1315 // kmp_critical_name *lck);
1316 llvm::Type *TypeParams[] = {
1317 getIdentTyPointerTy(), CGM.Int32Ty,
1318 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1319 llvm::FunctionType *FnTy =
1320 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1321 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
1322 break;
1323 }
1324 case OMPRTL__kmpc_end_reduce_nowait: {
1325 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
1326 // kmp_critical_name *lck);
1327 llvm::Type *TypeParams[] = {
1328 getIdentTyPointerTy(), CGM.Int32Ty,
1329 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1330 llvm::FunctionType *FnTy =
1331 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1332 RTLFn =
1333 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
1334 break;
1335 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001336 case OMPRTL__kmpc_omp_task_begin_if0: {
1337 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1338 // *new_task);
1339 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1340 CGM.VoidPtrTy};
1341 llvm::FunctionType *FnTy =
1342 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1343 RTLFn =
1344 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
1345 break;
1346 }
1347 case OMPRTL__kmpc_omp_task_complete_if0: {
1348 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1349 // *new_task);
1350 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1351 CGM.VoidPtrTy};
1352 llvm::FunctionType *FnTy =
1353 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1354 RTLFn = CGM.CreateRuntimeFunction(FnTy,
1355 /*Name=*/"__kmpc_omp_task_complete_if0");
1356 break;
1357 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001358 case OMPRTL__kmpc_ordered: {
1359 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
1360 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1361 llvm::FunctionType *FnTy =
1362 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1363 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
1364 break;
1365 }
1366 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001367 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001368 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1369 llvm::FunctionType *FnTy =
1370 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1371 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
1372 break;
1373 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00001374 case OMPRTL__kmpc_omp_taskwait: {
1375 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
1376 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1377 llvm::FunctionType *FnTy =
1378 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1379 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
1380 break;
1381 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001382 case OMPRTL__kmpc_taskgroup: {
1383 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
1384 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1385 llvm::FunctionType *FnTy =
1386 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1387 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
1388 break;
1389 }
1390 case OMPRTL__kmpc_end_taskgroup: {
1391 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
1392 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1393 llvm::FunctionType *FnTy =
1394 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1395 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
1396 break;
1397 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00001398 case OMPRTL__kmpc_push_proc_bind: {
1399 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
1400 // int proc_bind)
1401 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1402 llvm::FunctionType *FnTy =
1403 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1404 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
1405 break;
1406 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00001407 case OMPRTL__kmpc_omp_task_with_deps: {
1408 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
1409 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
1410 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
1411 llvm::Type *TypeParams[] = {
1412 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
1413 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
1414 llvm::FunctionType *FnTy =
1415 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1416 RTLFn =
1417 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
1418 break;
1419 }
1420 case OMPRTL__kmpc_omp_wait_deps: {
1421 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
1422 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
1423 // kmp_depend_info_t *noalias_dep_list);
1424 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1425 CGM.Int32Ty, CGM.VoidPtrTy,
1426 CGM.Int32Ty, CGM.VoidPtrTy};
1427 llvm::FunctionType *FnTy =
1428 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1429 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
1430 break;
1431 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00001432 case OMPRTL__kmpc_cancellationpoint: {
1433 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
1434 // global_tid, kmp_int32 cncl_kind)
1435 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1436 llvm::FunctionType *FnTy =
1437 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1438 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
1439 break;
1440 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001441 case OMPRTL__kmpc_cancel: {
1442 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
1443 // kmp_int32 cncl_kind)
1444 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1445 llvm::FunctionType *FnTy =
1446 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1447 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
1448 break;
1449 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00001450 case OMPRTL__kmpc_push_num_teams: {
1451 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
1452 // kmp_int32 num_teams, kmp_int32 num_threads)
1453 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1454 CGM.Int32Ty};
1455 llvm::FunctionType *FnTy =
1456 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1457 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
1458 break;
1459 }
1460 case OMPRTL__kmpc_fork_teams: {
1461 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
1462 // microtask, ...);
1463 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1464 getKmpc_MicroPointerTy()};
1465 llvm::FunctionType *FnTy =
1466 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
1467 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
1468 break;
1469 }
Alexey Bataev7292c292016-04-25 12:22:29 +00001470 case OMPRTL__kmpc_taskloop: {
1471 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
1472 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
1473 // sched, kmp_uint64 grainsize, void *task_dup);
1474 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
1475 CGM.IntTy,
1476 CGM.VoidPtrTy,
1477 CGM.IntTy,
1478 CGM.Int64Ty->getPointerTo(),
1479 CGM.Int64Ty->getPointerTo(),
1480 CGM.Int64Ty,
1481 CGM.IntTy,
1482 CGM.IntTy,
1483 CGM.Int64Ty,
1484 CGM.VoidPtrTy};
1485 llvm::FunctionType *FnTy =
1486 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1487 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
1488 break;
1489 }
Alexey Bataev8b427062016-05-25 12:36:08 +00001490 case OMPRTL__kmpc_doacross_init: {
1491 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
1492 // num_dims, struct kmp_dim *dims);
1493 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
1494 CGM.Int32Ty,
1495 CGM.Int32Ty,
1496 CGM.VoidPtrTy};
1497 llvm::FunctionType *FnTy =
1498 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1499 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
1500 break;
1501 }
1502 case OMPRTL__kmpc_doacross_fini: {
1503 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
1504 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1505 llvm::FunctionType *FnTy =
1506 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1507 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
1508 break;
1509 }
1510 case OMPRTL__kmpc_doacross_post: {
1511 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
1512 // *vec);
1513 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1514 CGM.Int64Ty->getPointerTo()};
1515 llvm::FunctionType *FnTy =
1516 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1517 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
1518 break;
1519 }
1520 case OMPRTL__kmpc_doacross_wait: {
1521 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
1522 // *vec);
1523 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1524 CGM.Int64Ty->getPointerTo()};
1525 llvm::FunctionType *FnTy =
1526 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1527 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
1528 break;
1529 }
Samuel Antaobed3c462015-10-02 16:14:20 +00001530 case OMPRTL__tgt_target: {
1531 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
1532 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
1533 // *arg_types);
1534 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1535 CGM.VoidPtrTy,
1536 CGM.Int32Ty,
1537 CGM.VoidPtrPtrTy,
1538 CGM.VoidPtrPtrTy,
1539 CGM.SizeTy->getPointerTo(),
1540 CGM.Int32Ty->getPointerTo()};
1541 llvm::FunctionType *FnTy =
1542 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1543 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
1544 break;
1545 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00001546 case OMPRTL__tgt_target_teams: {
1547 // Build int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
1548 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
1549 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
1550 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1551 CGM.VoidPtrTy,
1552 CGM.Int32Ty,
1553 CGM.VoidPtrPtrTy,
1554 CGM.VoidPtrPtrTy,
1555 CGM.SizeTy->getPointerTo(),
1556 CGM.Int32Ty->getPointerTo(),
1557 CGM.Int32Ty,
1558 CGM.Int32Ty};
1559 llvm::FunctionType *FnTy =
1560 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1561 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
1562 break;
1563 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00001564 case OMPRTL__tgt_register_lib: {
1565 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
1566 QualType ParamTy =
1567 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1568 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1569 llvm::FunctionType *FnTy =
1570 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1571 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
1572 break;
1573 }
1574 case OMPRTL__tgt_unregister_lib: {
1575 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
1576 QualType ParamTy =
1577 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1578 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1579 llvm::FunctionType *FnTy =
1580 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1581 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
1582 break;
1583 }
Samuel Antaodf158d52016-04-27 22:58:19 +00001584 case OMPRTL__tgt_target_data_begin: {
1585 // Build void __tgt_target_data_begin(int32_t device_id, int32_t arg_num,
1586 // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types);
1587 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1588 CGM.Int32Ty,
1589 CGM.VoidPtrPtrTy,
1590 CGM.VoidPtrPtrTy,
1591 CGM.SizeTy->getPointerTo(),
1592 CGM.Int32Ty->getPointerTo()};
1593 llvm::FunctionType *FnTy =
1594 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1595 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
1596 break;
1597 }
1598 case OMPRTL__tgt_target_data_end: {
1599 // Build void __tgt_target_data_end(int32_t device_id, int32_t arg_num,
1600 // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types);
1601 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1602 CGM.Int32Ty,
1603 CGM.VoidPtrPtrTy,
1604 CGM.VoidPtrPtrTy,
1605 CGM.SizeTy->getPointerTo(),
1606 CGM.Int32Ty->getPointerTo()};
1607 llvm::FunctionType *FnTy =
1608 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1609 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
1610 break;
1611 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001612 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00001613 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00001614 return RTLFn;
1615}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001616
Alexander Musman21212e42015-03-13 10:38:23 +00001617llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
1618 bool IVSigned) {
1619 assert((IVSize == 32 || IVSize == 64) &&
1620 "IV size is not compatible with the omp runtime");
1621 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
1622 : "__kmpc_for_static_init_4u")
1623 : (IVSigned ? "__kmpc_for_static_init_8"
1624 : "__kmpc_for_static_init_8u");
1625 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1626 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1627 llvm::Type *TypeParams[] = {
1628 getIdentTyPointerTy(), // loc
1629 CGM.Int32Ty, // tid
1630 CGM.Int32Ty, // schedtype
1631 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1632 PtrTy, // p_lower
1633 PtrTy, // p_upper
1634 PtrTy, // p_stride
1635 ITy, // incr
1636 ITy // chunk
1637 };
1638 llvm::FunctionType *FnTy =
1639 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1640 return CGM.CreateRuntimeFunction(FnTy, Name);
1641}
1642
Alexander Musman92bdaab2015-03-12 13:37:50 +00001643llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
1644 bool IVSigned) {
1645 assert((IVSize == 32 || IVSize == 64) &&
1646 "IV size is not compatible with the omp runtime");
1647 auto Name =
1648 IVSize == 32
1649 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
1650 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
1651 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1652 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
1653 CGM.Int32Ty, // tid
1654 CGM.Int32Ty, // schedtype
1655 ITy, // lower
1656 ITy, // upper
1657 ITy, // stride
1658 ITy // chunk
1659 };
1660 llvm::FunctionType *FnTy =
1661 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1662 return CGM.CreateRuntimeFunction(FnTy, Name);
1663}
1664
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001665llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
1666 bool IVSigned) {
1667 assert((IVSize == 32 || IVSize == 64) &&
1668 "IV size is not compatible with the omp runtime");
1669 auto Name =
1670 IVSize == 32
1671 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1672 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1673 llvm::Type *TypeParams[] = {
1674 getIdentTyPointerTy(), // loc
1675 CGM.Int32Ty, // tid
1676 };
1677 llvm::FunctionType *FnTy =
1678 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1679 return CGM.CreateRuntimeFunction(FnTy, Name);
1680}
1681
Alexander Musman92bdaab2015-03-12 13:37:50 +00001682llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
1683 bool IVSigned) {
1684 assert((IVSize == 32 || IVSize == 64) &&
1685 "IV size is not compatible with the omp runtime");
1686 auto Name =
1687 IVSize == 32
1688 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1689 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1690 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1691 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1692 llvm::Type *TypeParams[] = {
1693 getIdentTyPointerTy(), // loc
1694 CGM.Int32Ty, // tid
1695 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1696 PtrTy, // p_lower
1697 PtrTy, // p_upper
1698 PtrTy // p_stride
1699 };
1700 llvm::FunctionType *FnTy =
1701 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1702 return CGM.CreateRuntimeFunction(FnTy, Name);
1703}
1704
Alexey Bataev97720002014-11-11 04:05:39 +00001705llvm::Constant *
1706CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001707 assert(!CGM.getLangOpts().OpenMPUseTLS ||
1708 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00001709 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001710 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001711 Twine(CGM.getMangledName(VD)) + ".cache.");
1712}
1713
John McCall7f416cc2015-09-08 08:05:57 +00001714Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1715 const VarDecl *VD,
1716 Address VDAddr,
1717 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001718 if (CGM.getLangOpts().OpenMPUseTLS &&
1719 CGM.getContext().getTargetInfo().isTLSSupported())
1720 return VDAddr;
1721
John McCall7f416cc2015-09-08 08:05:57 +00001722 auto VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001723 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001724 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1725 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001726 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1727 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00001728 return Address(CGF.EmitRuntimeCall(
1729 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
1730 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00001731}
1732
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001733void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00001734 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00001735 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1736 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1737 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001738 auto OMPLoc = emitUpdateLocation(CGF, Loc);
1739 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00001740 OMPLoc);
1741 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1742 // to register constructor/destructor for variable.
1743 llvm::Value *Args[] = {OMPLoc,
John McCall7f416cc2015-09-08 08:05:57 +00001744 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1745 CGM.VoidPtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001746 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001747 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001748 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001749}
1750
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001751llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00001752 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00001753 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001754 if (CGM.getLangOpts().OpenMPUseTLS &&
1755 CGM.getContext().getTargetInfo().isTLSSupported())
1756 return nullptr;
1757
Alexey Bataev97720002014-11-11 04:05:39 +00001758 VD = VD->getDefinition(CGM.getContext());
1759 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
1760 ThreadPrivateWithDefinition.insert(VD);
1761 QualType ASTTy = VD->getType();
1762
1763 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1764 auto Init = VD->getAnyInitializer();
1765 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1766 // Generate function that re-emits the declaration's initializer into the
1767 // threadprivate copy of the variable VD
1768 CodeGenFunction CtorCGF(CGM);
1769 FunctionArgList Args;
1770 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1771 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1772 Args.push_back(&Dst);
1773
John McCallc56a8b32016-03-11 04:30:31 +00001774 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1775 CGM.getContext().VoidPtrTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001776 auto FTy = CGM.getTypes().GetFunctionType(FI);
1777 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001778 FTy, ".__kmpc_global_ctor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001779 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1780 Args, SourceLocation());
1781 auto ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001782 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001783 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00001784 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1785 Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
1786 CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00001787 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1788 /*IsInitializer=*/true);
1789 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001790 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001791 CGM.getContext().VoidPtrTy, Dst.getLocation());
1792 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1793 CtorCGF.FinishFunction();
1794 Ctor = Fn;
1795 }
1796 if (VD->getType().isDestructedType() != QualType::DK_none) {
1797 // Generate function that emits destructor call for the threadprivate copy
1798 // of the variable VD
1799 CodeGenFunction DtorCGF(CGM);
1800 FunctionArgList Args;
1801 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1802 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1803 Args.push_back(&Dst);
1804
John McCallc56a8b32016-03-11 04:30:31 +00001805 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1806 CGM.getContext().VoidTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001807 auto FTy = CGM.getTypes().GetFunctionType(FI);
1808 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001809 FTy, ".__kmpc_global_dtor_.", FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00001810 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00001811 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1812 SourceLocation());
Adrian Prantl1858c662016-04-24 22:22:29 +00001813 // Create a scope with an artificial location for the body of this function.
1814 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00001815 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1816 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00001817 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1818 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001819 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1820 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1821 DtorCGF.FinishFunction();
1822 Dtor = Fn;
1823 }
1824 // Do not emit init function if it is not required.
1825 if (!Ctor && !Dtor)
1826 return nullptr;
1827
1828 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1829 auto CopyCtorTy =
1830 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1831 /*isVarArg=*/false)->getPointerTo();
1832 // Copying constructor for the threadprivate variable.
1833 // Must be NULL - reserved by runtime, but currently it requires that this
1834 // parameter is always NULL. Otherwise it fires assertion.
1835 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1836 if (Ctor == nullptr) {
1837 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1838 /*isVarArg=*/false)->getPointerTo();
1839 Ctor = llvm::Constant::getNullValue(CtorTy);
1840 }
1841 if (Dtor == nullptr) {
1842 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1843 /*isVarArg=*/false)->getPointerTo();
1844 Dtor = llvm::Constant::getNullValue(DtorTy);
1845 }
1846 if (!CGF) {
1847 auto InitFunctionTy =
1848 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1849 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001850 InitFunctionTy, ".__omp_threadprivate_init_.",
1851 CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00001852 CodeGenFunction InitCGF(CGM);
1853 FunctionArgList ArgList;
1854 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1855 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1856 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001857 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001858 InitCGF.FinishFunction();
1859 return InitFunction;
1860 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001861 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001862 }
1863 return nullptr;
1864}
1865
Alexey Bataev1d677132015-04-22 13:57:31 +00001866/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1867/// function. Here is the logic:
1868/// if (Cond) {
1869/// ThenGen();
1870/// } else {
1871/// ElseGen();
1872/// }
1873static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1874 const RegionCodeGenTy &ThenGen,
1875 const RegionCodeGenTy &ElseGen) {
1876 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1877
1878 // If the condition constant folds and can be elided, try to avoid emitting
1879 // the condition and the dead arm of the if/else.
1880 bool CondConstant;
1881 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001882 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00001883 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001884 else
Alexey Bataev1d677132015-04-22 13:57:31 +00001885 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001886 return;
1887 }
1888
1889 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1890 // emit the conditional branch.
1891 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1892 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1893 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1894 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1895
1896 // Emit the 'then' code.
1897 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001898 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001899 CGF.EmitBranch(ContBlock);
1900 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001901 // There is no need to emit line number for unconditional branch.
1902 (void)ApplyDebugLocation::CreateEmpty(CGF);
1903 CGF.EmitBlock(ElseBlock);
1904 ElseGen(CGF);
1905 // There is no need to emit line number for unconditional branch.
1906 (void)ApplyDebugLocation::CreateEmpty(CGF);
1907 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00001908 // Emit the continuation block for code after the if.
1909 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001910}
1911
Alexey Bataev1d677132015-04-22 13:57:31 +00001912void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1913 llvm::Value *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001914 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00001915 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001916 if (!CGF.HaveInsertPoint())
1917 return;
Alexey Bataev1d677132015-04-22 13:57:31 +00001918 auto *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001919 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
1920 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001921 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001922 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00001923 llvm::Value *Args[] = {
1924 RTLoc,
1925 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001926 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00001927 llvm::SmallVector<llvm::Value *, 16> RealArgs;
1928 RealArgs.append(std::begin(Args), std::end(Args));
1929 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1930
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001931 auto RTLFn = RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001932 CGF.EmitRuntimeCall(RTLFn, RealArgs);
1933 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001934 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
1935 PrePostActionTy &) {
1936 auto &RT = CGF.CGM.getOpenMPRuntime();
1937 auto ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00001938 // Build calls:
1939 // __kmpc_serialized_parallel(&Loc, GTid);
1940 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001941 CGF.EmitRuntimeCall(
1942 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001943
Alexey Bataev1d677132015-04-22 13:57:31 +00001944 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001945 auto ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00001946 Address ZeroAddr =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001947 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
1948 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00001949 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00001950 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
1951 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
1952 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1953 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev1d677132015-04-22 13:57:31 +00001954 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001955
Alexey Bataev1d677132015-04-22 13:57:31 +00001956 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001957 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00001958 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001959 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
1960 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00001961 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001962 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00001963 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001964 else {
1965 RegionCodeGenTy ThenRCG(ThenGen);
1966 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00001967 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001968}
1969
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001970// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001971// thread-ID variable (it is passed in a first argument of the outlined function
1972// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1973// regular serial code region, get thread ID by calling kmp_int32
1974// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1975// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00001976Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
1977 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00001978 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001979 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001980 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001981 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001982
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001983 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001984 auto Int32Ty =
1985 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1986 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1987 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00001988 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00001989
1990 return ThreadIDTemp;
1991}
1992
Alexey Bataev97720002014-11-11 04:05:39 +00001993llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001994CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001995 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001996 SmallString<256> Buffer;
1997 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001998 Out << Name;
1999 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00002000 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
2001 if (Elem.second) {
2002 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00002003 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00002004 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00002005 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002006
David Blaikie13156b62014-11-19 03:06:06 +00002007 return Elem.second = new llvm::GlobalVariable(
2008 CGM.getModule(), Ty, /*IsConstant*/ false,
2009 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
2010 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00002011}
2012
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002013llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00002014 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002015 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002016}
2017
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002018namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002019/// Common pre(post)-action for different OpenMP constructs.
2020class CommonActionTy final : public PrePostActionTy {
2021 llvm::Value *EnterCallee;
2022 ArrayRef<llvm::Value *> EnterArgs;
2023 llvm::Value *ExitCallee;
2024 ArrayRef<llvm::Value *> ExitArgs;
2025 bool Conditional;
2026 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002027
2028public:
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002029 CommonActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs,
2030 llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs,
2031 bool Conditional = false)
2032 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
2033 ExitArgs(ExitArgs), Conditional(Conditional) {}
2034 void Enter(CodeGenFunction &CGF) override {
2035 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
2036 if (Conditional) {
2037 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
2038 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
2039 ContBlock = CGF.createBasicBlock("omp_if.end");
2040 // Generate the branch (If-stmt)
2041 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
2042 CGF.EmitBlock(ThenBlock);
2043 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00002044 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002045 void Done(CodeGenFunction &CGF) {
2046 // Emit the rest of blocks/branches
2047 CGF.EmitBranch(ContBlock);
2048 CGF.EmitBlock(ContBlock, true);
2049 }
2050 void Exit(CodeGenFunction &CGF) override {
2051 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00002052 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002053};
Hans Wennborg7eb54642015-09-10 17:07:54 +00002054} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002055
2056void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
2057 StringRef CriticalName,
2058 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00002059 SourceLocation Loc, const Expr *Hint) {
2060 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00002061 // CriticalOpGen();
2062 // __kmpc_end_critical(ident_t *, gtid, Lock);
2063 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00002064 if (!CGF.HaveInsertPoint())
2065 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00002066 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2067 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002068 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
2069 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00002070 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002071 EnterArgs.push_back(CGF.Builder.CreateIntCast(
2072 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
2073 }
2074 CommonActionTy Action(
2075 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
2076 : OMPRTL__kmpc_critical),
2077 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
2078 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00002079 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002080}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002081
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002082void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002083 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002084 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002085 if (!CGF.HaveInsertPoint())
2086 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00002087 // if(__kmpc_master(ident_t *, gtid)) {
2088 // MasterOpGen();
2089 // __kmpc_end_master(ident_t *, gtid);
2090 // }
2091 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00002092 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002093 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
2094 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
2095 /*Conditional=*/true);
2096 MasterOpGen.setAction(Action);
2097 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
2098 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00002099}
2100
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002101void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
2102 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002103 if (!CGF.HaveInsertPoint())
2104 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00002105 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
2106 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002107 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00002108 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002109 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00002110 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
2111 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00002112}
2113
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002114void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
2115 const RegionCodeGenTy &TaskgroupOpGen,
2116 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002117 if (!CGF.HaveInsertPoint())
2118 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002119 // __kmpc_taskgroup(ident_t *, gtid);
2120 // TaskgroupOpGen();
2121 // __kmpc_end_taskgroup(ident_t *, gtid);
2122 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002123 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2124 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
2125 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
2126 Args);
2127 TaskgroupOpGen.setAction(Action);
2128 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002129}
2130
John McCall7f416cc2015-09-08 08:05:57 +00002131/// Given an array of pointers to variables, project the address of a
2132/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002133static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
2134 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00002135 // Pull out the pointer to the variable.
2136 Address PtrAddr =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002137 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00002138 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
2139
2140 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002141 Addr = CGF.Builder.CreateElementBitCast(
2142 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00002143 return Addr;
2144}
2145
Alexey Bataeva63048e2015-03-23 06:18:07 +00002146static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00002147 CodeGenModule &CGM, llvm::Type *ArgsType,
2148 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
2149 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002150 auto &C = CGM.getContext();
2151 // void copy_func(void *LHSArg, void *RHSArg);
2152 FunctionArgList Args;
2153 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2154 C.VoidPtrTy);
2155 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2156 C.VoidPtrTy);
2157 Args.push_back(&LHSArg);
2158 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00002159 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002160 auto *Fn = llvm::Function::Create(
2161 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
2162 ".omp.copyprivate.copy_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002163 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002164 CodeGenFunction CGF(CGM);
2165 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00002166 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002167 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00002168 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2169 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2170 ArgsType), CGF.getPointerAlign());
2171 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2172 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2173 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00002174 // *(Type0*)Dst[0] = *(Type0*)Src[0];
2175 // *(Type1*)Dst[1] = *(Type1*)Src[1];
2176 // ...
2177 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00002178 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002179 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2180 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
2181
2182 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2183 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
2184
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002185 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2186 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00002187 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002188 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002189 CGF.FinishFunction();
2190 return Fn;
2191}
2192
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002193void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002194 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002195 SourceLocation Loc,
2196 ArrayRef<const Expr *> CopyprivateVars,
2197 ArrayRef<const Expr *> SrcExprs,
2198 ArrayRef<const Expr *> DstExprs,
2199 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002200 if (!CGF.HaveInsertPoint())
2201 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00002202 assert(CopyprivateVars.size() == SrcExprs.size() &&
2203 CopyprivateVars.size() == DstExprs.size() &&
2204 CopyprivateVars.size() == AssignmentOps.size());
2205 auto &C = CGM.getContext();
2206 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002207 // if(__kmpc_single(ident_t *, gtid)) {
2208 // SingleOpGen();
2209 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002210 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002211 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002212 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2213 // <copy_func>, did_it);
2214
John McCall7f416cc2015-09-08 08:05:57 +00002215 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00002216 if (!CopyprivateVars.empty()) {
2217 // int32 did_it = 0;
2218 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2219 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00002220 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002221 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002222 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00002223 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002224 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
2225 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
2226 /*Conditional=*/true);
2227 SingleOpGen.setAction(Action);
2228 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
2229 if (DidIt.isValid()) {
2230 // did_it = 1;
2231 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
2232 }
2233 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002234 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2235 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00002236 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002237 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
2238 auto CopyprivateArrayTy =
2239 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2240 /*IndexTypeQuals=*/0);
2241 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00002242 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002243 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
2244 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002245 Address Elem = CGF.Builder.CreateConstArrayGEP(
2246 CopyprivateList, I, CGF.getPointerSize());
2247 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00002248 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002249 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
2250 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002251 }
2252 // Build function that copies private values from single region to all other
2253 // threads in the corresponding parallel region.
2254 auto *CpyFn = emitCopyprivateCopyFunction(
2255 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00002256 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataev1189bd02016-01-26 12:20:39 +00002257 auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00002258 Address CL =
2259 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
2260 CGF.VoidPtrTy);
2261 auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002262 llvm::Value *Args[] = {
2263 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
2264 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00002265 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00002266 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00002267 CpyFn, // void (*) (void *, void *) <copy_func>
2268 DidItVal // i32 did_it
2269 };
2270 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
2271 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002272}
2273
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002274void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
2275 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00002276 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002277 if (!CGF.HaveInsertPoint())
2278 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002279 // __kmpc_ordered(ident_t *, gtid);
2280 // OrderedOpGen();
2281 // __kmpc_end_ordered(ident_t *, gtid);
2282 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00002283 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002284 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002285 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
2286 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
2287 Args);
2288 OrderedOpGen.setAction(Action);
2289 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2290 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002291 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00002292 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002293}
2294
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002295void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev25e5b442015-09-15 12:52:43 +00002296 OpenMPDirectiveKind Kind, bool EmitChecks,
2297 bool ForceSimpleCall) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002298 if (!CGF.HaveInsertPoint())
2299 return;
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00002300 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002301 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002302 unsigned Flags;
2303 if (Kind == OMPD_for)
2304 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2305 else if (Kind == OMPD_sections)
2306 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2307 else if (Kind == OMPD_single)
2308 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2309 else if (Kind == OMPD_barrier)
2310 Flags = OMP_IDENT_BARRIER_EXPL;
2311 else
2312 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002313 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
2314 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002315 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
2316 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002317 if (auto *OMPRegionInfo =
2318 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00002319 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002320 auto *Result = CGF.EmitRuntimeCall(
2321 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00002322 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002323 // if (__kmpc_cancel_barrier()) {
2324 // exit from construct;
2325 // }
2326 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
2327 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
2328 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
2329 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2330 CGF.EmitBlock(ExitBB);
2331 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00002332 auto CancelDestination =
2333 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002334 CGF.EmitBranchThroughCleanup(CancelDestination);
2335 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2336 }
2337 return;
2338 }
2339 }
2340 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002341}
2342
Alexander Musmanc6388682014-12-15 07:07:06 +00002343/// \brief Map the OpenMP loop schedule to the runtime enumeration.
2344static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002345 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002346 switch (ScheduleKind) {
2347 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002348 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2349 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00002350 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002351 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002352 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002353 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002354 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002355 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2356 case OMPC_SCHEDULE_auto:
2357 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00002358 case OMPC_SCHEDULE_unknown:
2359 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002360 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00002361 }
2362 llvm_unreachable("Unexpected runtime schedule");
2363}
2364
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002365/// \brief Map the OpenMP distribute schedule to the runtime enumeration.
2366static OpenMPSchedType
2367getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
2368 // only static is allowed for dist_schedule
2369 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2370}
2371
Alexander Musmanc6388682014-12-15 07:07:06 +00002372bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
2373 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002374 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00002375 return Schedule == OMP_sch_static;
2376}
2377
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002378bool CGOpenMPRuntime::isStaticNonchunked(
2379 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2380 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2381 return Schedule == OMP_dist_sch_static;
2382}
2383
2384
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002385bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002386 auto Schedule =
2387 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002388 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
2389 return Schedule != OMP_sch_static;
2390}
2391
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002392static int addMonoNonMonoModifier(OpenMPSchedType Schedule,
2393 OpenMPScheduleClauseModifier M1,
2394 OpenMPScheduleClauseModifier M2) {
2395 switch (M1) {
2396 case OMPC_SCHEDULE_MODIFIER_monotonic:
2397 return Schedule | OMP_sch_modifier_monotonic;
2398 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2399 return Schedule | OMP_sch_modifier_nonmonotonic;
2400 case OMPC_SCHEDULE_MODIFIER_simd:
2401 case OMPC_SCHEDULE_MODIFIER_last:
2402 case OMPC_SCHEDULE_MODIFIER_unknown:
2403 break;
2404 }
2405 switch (M2) {
2406 case OMPC_SCHEDULE_MODIFIER_monotonic:
2407 return Schedule | OMP_sch_modifier_monotonic;
2408 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2409 return Schedule | OMP_sch_modifier_nonmonotonic;
2410 case OMPC_SCHEDULE_MODIFIER_simd:
2411 case OMPC_SCHEDULE_MODIFIER_last:
2412 case OMPC_SCHEDULE_MODIFIER_unknown:
2413 break;
2414 }
2415 return Schedule;
2416}
2417
John McCall7f416cc2015-09-08 08:05:57 +00002418void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
2419 SourceLocation Loc,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002420 const OpenMPScheduleTy &ScheduleKind,
John McCall7f416cc2015-09-08 08:05:57 +00002421 unsigned IVSize, bool IVSigned,
2422 bool Ordered, llvm::Value *UB,
2423 llvm::Value *Chunk) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002424 if (!CGF.HaveInsertPoint())
2425 return;
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002426 OpenMPSchedType Schedule =
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002427 getRuntimeSchedule(ScheduleKind.Schedule, Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00002428 assert(Ordered ||
2429 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2430 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
2431 // Call __kmpc_dispatch_init(
2432 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
2433 // kmp_int[32|64] lower, kmp_int[32|64] upper,
2434 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002435
John McCall7f416cc2015-09-08 08:05:57 +00002436 // If the Chunk was not specified in the clause - use default value 1.
2437 if (Chunk == nullptr)
2438 Chunk = CGF.Builder.getIntN(IVSize, 1);
2439 llvm::Value *Args[] = {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002440 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2441 CGF.Builder.getInt32(addMonoNonMonoModifier(
2442 Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
2443 CGF.Builder.getIntN(IVSize, 0), // Lower
2444 UB, // Upper
2445 CGF.Builder.getIntN(IVSize, 1), // Stride
2446 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00002447 };
2448 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
2449}
2450
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002451static void emitForStaticInitCall(
2452 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2453 llvm::Constant *ForStaticInitFunction, OpenMPSchedType Schedule,
2454 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
2455 unsigned IVSize, bool Ordered, Address IL, Address LB, Address UB,
2456 Address ST, llvm::Value *Chunk) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002457 if (!CGF.HaveInsertPoint())
2458 return;
2459
2460 assert(!Ordered);
2461 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2462 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2463 Schedule == OMP_dist_sch_static ||
2464 Schedule == OMP_dist_sch_static_chunked);
2465
2466 // Call __kmpc_for_static_init(
2467 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
2468 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
2469 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
2470 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
2471 if (Chunk == nullptr) {
2472 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2473 Schedule == OMP_dist_sch_static) &&
2474 "expected static non-chunked schedule");
2475 // If the Chunk was not specified in the clause - use default value 1.
2476 Chunk = CGF.Builder.getIntN(IVSize, 1);
2477 } else {
2478 assert((Schedule == OMP_sch_static_chunked ||
2479 Schedule == OMP_ord_static_chunked ||
2480 Schedule == OMP_dist_sch_static_chunked) &&
2481 "expected static chunked schedule");
2482 }
2483 llvm::Value *Args[] = {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002484 UpdateLocation, ThreadId, CGF.Builder.getInt32(addMonoNonMonoModifier(
2485 Schedule, M1, M2)), // Schedule type
2486 IL.getPointer(), // &isLastIter
2487 LB.getPointer(), // &LB
2488 UB.getPointer(), // &UB
2489 ST.getPointer(), // &Stride
2490 CGF.Builder.getIntN(IVSize, 1), // Incr
2491 Chunk // Chunk
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002492 };
2493 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
2494}
2495
John McCall7f416cc2015-09-08 08:05:57 +00002496void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
2497 SourceLocation Loc,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002498 const OpenMPScheduleTy &ScheduleKind,
John McCall7f416cc2015-09-08 08:05:57 +00002499 unsigned IVSize, bool IVSigned,
2500 bool Ordered, Address IL, Address LB,
2501 Address UB, Address ST,
2502 llvm::Value *Chunk) {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002503 OpenMPSchedType ScheduleNum =
2504 getRuntimeSchedule(ScheduleKind.Schedule, Chunk != nullptr, Ordered);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002505 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2506 auto *ThreadId = getThreadID(CGF, Loc);
2507 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002508 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
2509 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, IVSize,
2510 Ordered, IL, LB, UB, ST, Chunk);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002511}
John McCall7f416cc2015-09-08 08:05:57 +00002512
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002513void CGOpenMPRuntime::emitDistributeStaticInit(
2514 CodeGenFunction &CGF, SourceLocation Loc,
2515 OpenMPDistScheduleClauseKind SchedKind, unsigned IVSize, bool IVSigned,
2516 bool Ordered, Address IL, Address LB, Address UB, Address ST,
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002517 llvm::Value *Chunk) {
2518 OpenMPSchedType ScheduleNum = getRuntimeSchedule(SchedKind, Chunk != nullptr);
2519 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2520 auto *ThreadId = getThreadID(CGF, Loc);
2521 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002522 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
2523 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
2524 OMPC_SCHEDULE_MODIFIER_unknown, IVSize, Ordered, IL, LB,
2525 UB, ST, Chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002526}
2527
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002528void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
2529 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002530 if (!CGF.HaveInsertPoint())
2531 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00002532 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002533 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002534 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
2535 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00002536}
2537
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002538void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
2539 SourceLocation Loc,
2540 unsigned IVSize,
2541 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002542 if (!CGF.HaveInsertPoint())
2543 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002544 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002545 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002546 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
2547}
2548
Alexander Musman92bdaab2015-03-12 13:37:50 +00002549llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
2550 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00002551 bool IVSigned, Address IL,
2552 Address LB, Address UB,
2553 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002554 // Call __kmpc_dispatch_next(
2555 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2556 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2557 // kmp_int[32|64] *p_stride);
2558 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002559 emitUpdateLocation(CGF, Loc),
2560 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002561 IL.getPointer(), // &isLastIter
2562 LB.getPointer(), // &Lower
2563 UB.getPointer(), // &Upper
2564 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00002565 };
2566 llvm::Value *Call =
2567 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
2568 return CGF.EmitScalarConversion(
2569 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00002570 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002571}
2572
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002573void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
2574 llvm::Value *NumThreads,
2575 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002576 if (!CGF.HaveInsertPoint())
2577 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00002578 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
2579 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002580 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00002581 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002582 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
2583 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00002584}
2585
Alexey Bataev7f210c62015-06-18 13:40:03 +00002586void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
2587 OpenMPProcBindClauseKind ProcBind,
2588 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002589 if (!CGF.HaveInsertPoint())
2590 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00002591 // Constants for proc bind value accepted by the runtime.
2592 enum ProcBindTy {
2593 ProcBindFalse = 0,
2594 ProcBindTrue,
2595 ProcBindMaster,
2596 ProcBindClose,
2597 ProcBindSpread,
2598 ProcBindIntel,
2599 ProcBindDefault
2600 } RuntimeProcBind;
2601 switch (ProcBind) {
2602 case OMPC_PROC_BIND_master:
2603 RuntimeProcBind = ProcBindMaster;
2604 break;
2605 case OMPC_PROC_BIND_close:
2606 RuntimeProcBind = ProcBindClose;
2607 break;
2608 case OMPC_PROC_BIND_spread:
2609 RuntimeProcBind = ProcBindSpread;
2610 break;
2611 case OMPC_PROC_BIND_unknown:
2612 llvm_unreachable("Unsupported proc_bind value.");
2613 }
2614 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
2615 llvm::Value *Args[] = {
2616 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2617 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
2618 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
2619}
2620
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002621void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
2622 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002623 if (!CGF.HaveInsertPoint())
2624 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00002625 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002626 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
2627 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00002628}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002629
Alexey Bataev62b63b12015-03-10 07:28:44 +00002630namespace {
2631/// \brief Indexes of fields for type kmp_task_t.
2632enum KmpTaskTFields {
2633 /// \brief List of shared variables.
2634 KmpTaskTShareds,
2635 /// \brief Task routine.
2636 KmpTaskTRoutine,
2637 /// \brief Partition id for the untied tasks.
2638 KmpTaskTPartId,
2639 /// \brief Function with call of destructors for private variables.
2640 KmpTaskTDestructors,
Alexey Bataev7292c292016-04-25 12:22:29 +00002641 /// (Taskloops only) Lower bound.
2642 KmpTaskTLowerBound,
2643 /// (Taskloops only) Upper bound.
2644 KmpTaskTUpperBound,
2645 /// (Taskloops only) Stride.
2646 KmpTaskTStride,
2647 /// (Taskloops only) Is last iteration flag.
2648 KmpTaskTLastIter,
Alexey Bataev62b63b12015-03-10 07:28:44 +00002649};
Hans Wennborg7eb54642015-09-10 17:07:54 +00002650} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00002651
Samuel Antaoee8fb302016-01-06 13:42:12 +00002652bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
2653 // FIXME: Add other entries type when they become supported.
2654 return OffloadEntriesTargetRegion.empty();
2655}
2656
2657/// \brief Initialize target region entry.
2658void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2659 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2660 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002661 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002662 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
2663 "only required for the device "
2664 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002665 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002666 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr);
2667 ++OffloadingEntriesNum;
2668}
2669
2670void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2671 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2672 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002673 llvm::Constant *Addr, llvm::Constant *ID) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002674 // If we are emitting code for a target, the entry is already initialized,
2675 // only has to be registered.
2676 if (CGM.getLangOpts().OpenMPIsDevice) {
Samuel Antao2de62b02016-02-13 23:35:10 +00002677 assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) &&
Samuel Antaoee8fb302016-01-06 13:42:12 +00002678 "Entry must exist.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002679 auto &Entry =
2680 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00002681 assert(Entry.isValid() && "Entry not initialized!");
2682 Entry.setAddress(Addr);
2683 Entry.setID(ID);
2684 return;
2685 } else {
2686 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID);
Samuel Antao2de62b02016-02-13 23:35:10 +00002687 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002688 }
2689}
2690
2691bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00002692 unsigned DeviceID, unsigned FileID, StringRef ParentName,
2693 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002694 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
2695 if (PerDevice == OffloadEntriesTargetRegion.end())
2696 return false;
2697 auto PerFile = PerDevice->second.find(FileID);
2698 if (PerFile == PerDevice->second.end())
2699 return false;
2700 auto PerParentName = PerFile->second.find(ParentName);
2701 if (PerParentName == PerFile->second.end())
2702 return false;
2703 auto PerLine = PerParentName->second.find(LineNum);
2704 if (PerLine == PerParentName->second.end())
2705 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002706 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00002707 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00002708 return false;
2709 return true;
2710}
2711
2712void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
2713 const OffloadTargetRegionEntryInfoActTy &Action) {
2714 // Scan all target region entries and perform the provided action.
2715 for (auto &D : OffloadEntriesTargetRegion)
2716 for (auto &F : D.second)
2717 for (auto &P : F.second)
2718 for (auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00002719 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002720}
2721
2722/// \brief Create a Ctor/Dtor-like function whose body is emitted through
2723/// \a Codegen. This is used to emit the two functions that register and
2724/// unregister the descriptor of the current compilation unit.
2725static llvm::Function *
2726createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
2727 const RegionCodeGenTy &Codegen) {
2728 auto &C = CGM.getContext();
2729 FunctionArgList Args;
2730 ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(),
2731 /*Id=*/nullptr, C.VoidPtrTy);
2732 Args.push_back(&DummyPtr);
2733
2734 CodeGenFunction CGF(CGM);
2735 GlobalDecl();
John McCallc56a8b32016-03-11 04:30:31 +00002736 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002737 auto FTy = CGM.getTypes().GetFunctionType(FI);
2738 auto *Fn =
2739 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation());
2740 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation());
2741 Codegen(CGF);
2742 CGF.FinishFunction();
2743 return Fn;
2744}
2745
2746llvm::Function *
2747CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
2748
2749 // If we don't have entries or if we are emitting code for the device, we
2750 // don't need to do anything.
2751 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
2752 return nullptr;
2753
2754 auto &M = CGM.getModule();
2755 auto &C = CGM.getContext();
2756
2757 // Get list of devices we care about
2758 auto &Devices = CGM.getLangOpts().OMPTargetTriples;
2759
2760 // We should be creating an offloading descriptor only if there are devices
2761 // specified.
2762 assert(!Devices.empty() && "No OpenMP offloading devices??");
2763
2764 // Create the external variables that will point to the begin and end of the
2765 // host entries section. These will be defined by the linker.
2766 auto *OffloadEntryTy =
2767 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
2768 llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable(
2769 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002770 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002771 ".omp_offloading.entries_begin");
2772 llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable(
2773 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002774 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002775 ".omp_offloading.entries_end");
2776
2777 // Create all device images
2778 llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires;
2779 auto *DeviceImageTy = cast<llvm::StructType>(
2780 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
2781
2782 for (unsigned i = 0; i < Devices.size(); ++i) {
2783 StringRef T = Devices[i].getTriple();
2784 auto *ImgBegin = new llvm::GlobalVariable(
2785 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002786 /*Initializer=*/nullptr,
2787 Twine(".omp_offloading.img_start.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002788 auto *ImgEnd = new llvm::GlobalVariable(
2789 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002790 /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002791
2792 llvm::Constant *Dev =
2793 llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd,
2794 HostEntriesBegin, HostEntriesEnd, nullptr);
2795 DeviceImagesEntires.push_back(Dev);
2796 }
2797
2798 // Create device images global array.
2799 llvm::ArrayType *DeviceImagesInitTy =
2800 llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size());
2801 llvm::Constant *DeviceImagesInit =
2802 llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires);
2803
2804 llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable(
2805 M, DeviceImagesInitTy, /*isConstant=*/true,
2806 llvm::GlobalValue::InternalLinkage, DeviceImagesInit,
2807 ".omp_offloading.device_images");
2808 DeviceImages->setUnnamedAddr(true);
2809
2810 // This is a Zero array to be used in the creation of the constant expressions
2811 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
2812 llvm::Constant::getNullValue(CGM.Int32Ty)};
2813
2814 // Create the target region descriptor.
2815 auto *BinaryDescriptorTy = cast<llvm::StructType>(
2816 CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
2817 llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get(
2818 BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
2819 llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages,
2820 Index),
2821 HostEntriesBegin, HostEntriesEnd, nullptr);
2822
2823 auto *Desc = new llvm::GlobalVariable(
2824 M, BinaryDescriptorTy, /*isConstant=*/true,
2825 llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit,
2826 ".omp_offloading.descriptor");
2827
2828 // Emit code to register or unregister the descriptor at execution
2829 // startup or closing, respectively.
2830
2831 // Create a variable to drive the registration and unregistration of the
2832 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
2833 auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var");
2834 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(),
2835 IdentInfo, C.CharTy);
2836
2837 auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002838 CGM, ".omp_offloading.descriptor_unreg",
2839 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002840 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
2841 Desc);
2842 });
2843 auto *RegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002844 CGM, ".omp_offloading.descriptor_reg",
2845 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002846 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib),
2847 Desc);
2848 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
2849 });
2850 return RegFn;
2851}
2852
Samuel Antao2de62b02016-02-13 23:35:10 +00002853void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID,
2854 llvm::Constant *Addr, uint64_t Size) {
2855 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00002856 auto *TgtOffloadEntryType = cast<llvm::StructType>(
2857 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()));
2858 llvm::LLVMContext &C = CGM.getModule().getContext();
2859 llvm::Module &M = CGM.getModule();
2860
2861 // Make sure the address has the right type.
Samuel Antao2de62b02016-02-13 23:35:10 +00002862 llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002863
2864 // Create constant string with the name.
2865 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
2866
2867 llvm::GlobalVariable *Str =
2868 new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true,
2869 llvm::GlobalValue::InternalLinkage, StrPtrInit,
2870 ".omp_offloading.entry_name");
2871 Str->setUnnamedAddr(true);
2872 llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy);
2873
2874 // Create the entry struct.
2875 llvm::Constant *EntryInit = llvm::ConstantStruct::get(
2876 TgtOffloadEntryType, AddrPtr, StrPtr,
2877 llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr);
2878 llvm::GlobalVariable *Entry = new llvm::GlobalVariable(
2879 M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage,
2880 EntryInit, ".omp_offloading.entry");
2881
2882 // The entry has to be created in the section the linker expects it to be.
2883 Entry->setSection(".omp_offloading.entries");
2884 // We can't have any padding between symbols, so we need to have 1-byte
2885 // alignment.
2886 Entry->setAlignment(1);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002887}
2888
2889void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
2890 // Emit the offloading entries and metadata so that the device codegen side
2891 // can
2892 // easily figure out what to emit. The produced metadata looks like this:
2893 //
2894 // !omp_offload.info = !{!1, ...}
2895 //
2896 // Right now we only generate metadata for function that contain target
2897 // regions.
2898
2899 // If we do not have entries, we dont need to do anything.
2900 if (OffloadEntriesInfoManager.empty())
2901 return;
2902
2903 llvm::Module &M = CGM.getModule();
2904 llvm::LLVMContext &C = M.getContext();
2905 SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
2906 OrderedEntries(OffloadEntriesInfoManager.size());
2907
2908 // Create the offloading info metadata node.
2909 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
2910
2911 // Auxiliar methods to create metadata values and strings.
2912 auto getMDInt = [&](unsigned v) {
2913 return llvm::ConstantAsMetadata::get(
2914 llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v));
2915 };
2916
2917 auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); };
2918
2919 // Create function that emits metadata for each target region entry;
2920 auto &&TargetRegionMetadataEmitter = [&](
2921 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002922 OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
2923 llvm::SmallVector<llvm::Metadata *, 32> Ops;
2924 // Generate metadata for target regions. Each entry of this metadata
2925 // contains:
2926 // - Entry 0 -> Kind of this type of metadata (0).
2927 // - Entry 1 -> Device ID of the file where the entry was identified.
2928 // - Entry 2 -> File ID of the file where the entry was identified.
2929 // - Entry 3 -> Mangled name of the function where the entry was identified.
2930 // - Entry 4 -> Line in the file where the entry was identified.
Samuel Antao2de62b02016-02-13 23:35:10 +00002931 // - Entry 5 -> Order the entry was created.
Samuel Antaoee8fb302016-01-06 13:42:12 +00002932 // The first element of the metadata node is the kind.
2933 Ops.push_back(getMDInt(E.getKind()));
2934 Ops.push_back(getMDInt(DeviceID));
2935 Ops.push_back(getMDInt(FileID));
2936 Ops.push_back(getMDString(ParentName));
2937 Ops.push_back(getMDInt(Line));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002938 Ops.push_back(getMDInt(E.getOrder()));
2939
2940 // Save this entry in the right position of the ordered entries array.
2941 OrderedEntries[E.getOrder()] = &E;
2942
2943 // Add metadata to the named metadata node.
2944 MD->addOperand(llvm::MDNode::get(C, Ops));
2945 };
2946
2947 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
2948 TargetRegionMetadataEmitter);
2949
2950 for (auto *E : OrderedEntries) {
2951 assert(E && "All ordered entries must exist!");
2952 if (auto *CE =
2953 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
2954 E)) {
2955 assert(CE->getID() && CE->getAddress() &&
2956 "Entry ID and Addr are invalid!");
Samuel Antao2de62b02016-02-13 23:35:10 +00002957 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002958 } else
2959 llvm_unreachable("Unsupported entry kind.");
2960 }
2961}
2962
2963/// \brief Loads all the offload entries information from the host IR
2964/// metadata.
2965void CGOpenMPRuntime::loadOffloadInfoMetadata() {
2966 // If we are in target mode, load the metadata from the host IR. This code has
2967 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
2968
2969 if (!CGM.getLangOpts().OpenMPIsDevice)
2970 return;
2971
2972 if (CGM.getLangOpts().OMPHostIRFile.empty())
2973 return;
2974
2975 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
2976 if (Buf.getError())
2977 return;
2978
2979 llvm::LLVMContext C;
2980 auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C);
2981
2982 if (ME.getError())
2983 return;
2984
2985 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
2986 if (!MD)
2987 return;
2988
2989 for (auto I : MD->operands()) {
2990 llvm::MDNode *MN = cast<llvm::MDNode>(I);
2991
2992 auto getMDInt = [&](unsigned Idx) {
2993 llvm::ConstantAsMetadata *V =
2994 cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
2995 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
2996 };
2997
2998 auto getMDString = [&](unsigned Idx) {
2999 llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx));
3000 return V->getString();
3001 };
3002
3003 switch (getMDInt(0)) {
3004 default:
3005 llvm_unreachable("Unexpected metadata!");
3006 break;
3007 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
3008 OFFLOAD_ENTRY_INFO_TARGET_REGION:
3009 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
3010 /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2),
3011 /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4),
Samuel Antao2de62b02016-02-13 23:35:10 +00003012 /*Order=*/getMDInt(5));
Samuel Antaoee8fb302016-01-06 13:42:12 +00003013 break;
3014 }
3015 }
3016}
3017
Alexey Bataev62b63b12015-03-10 07:28:44 +00003018void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
3019 if (!KmpRoutineEntryPtrTy) {
3020 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
3021 auto &C = CGM.getContext();
3022 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
3023 FunctionProtoType::ExtProtoInfo EPI;
3024 KmpRoutineEntryPtrQTy = C.getPointerType(
3025 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
3026 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
3027 }
3028}
3029
Alexey Bataevc71a4092015-09-11 10:29:41 +00003030static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
3031 QualType FieldTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003032 auto *Field = FieldDecl::Create(
3033 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
3034 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
3035 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
3036 Field->setAccess(AS_public);
3037 DC->addDecl(Field);
Alexey Bataevc71a4092015-09-11 10:29:41 +00003038 return Field;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003039}
3040
Samuel Antaoee8fb302016-01-06 13:42:12 +00003041QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
3042
3043 // Make sure the type of the entry is already created. This is the type we
3044 // have to create:
3045 // struct __tgt_offload_entry{
3046 // void *addr; // Pointer to the offload entry info.
3047 // // (function or global)
3048 // char *name; // Name of the function or global.
3049 // size_t size; // Size of the entry info (0 if it a function).
3050 // };
3051 if (TgtOffloadEntryQTy.isNull()) {
3052 ASTContext &C = CGM.getContext();
3053 auto *RD = C.buildImplicitRecord("__tgt_offload_entry");
3054 RD->startDefinition();
3055 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3056 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
3057 addFieldToRecordDecl(C, RD, C.getSizeType());
3058 RD->completeDefinition();
3059 TgtOffloadEntryQTy = C.getRecordType(RD);
3060 }
3061 return TgtOffloadEntryQTy;
3062}
3063
3064QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
3065 // These are the types we need to build:
3066 // struct __tgt_device_image{
3067 // void *ImageStart; // Pointer to the target code start.
3068 // void *ImageEnd; // Pointer to the target code end.
3069 // // We also add the host entries to the device image, as it may be useful
3070 // // for the target runtime to have access to that information.
3071 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
3072 // // the entries.
3073 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
3074 // // entries (non inclusive).
3075 // };
3076 if (TgtDeviceImageQTy.isNull()) {
3077 ASTContext &C = CGM.getContext();
3078 auto *RD = C.buildImplicitRecord("__tgt_device_image");
3079 RD->startDefinition();
3080 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3081 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3082 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
3083 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
3084 RD->completeDefinition();
3085 TgtDeviceImageQTy = C.getRecordType(RD);
3086 }
3087 return TgtDeviceImageQTy;
3088}
3089
3090QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
3091 // struct __tgt_bin_desc{
3092 // int32_t NumDevices; // Number of devices supported.
3093 // __tgt_device_image *DeviceImages; // Arrays of device images
3094 // // (one per device).
3095 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
3096 // // entries.
3097 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
3098 // // entries (non inclusive).
3099 // };
3100 if (TgtBinaryDescriptorQTy.isNull()) {
3101 ASTContext &C = CGM.getContext();
3102 auto *RD = C.buildImplicitRecord("__tgt_bin_desc");
3103 RD->startDefinition();
3104 addFieldToRecordDecl(
3105 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
3106 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
3107 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
3108 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
3109 RD->completeDefinition();
3110 TgtBinaryDescriptorQTy = C.getRecordType(RD);
3111 }
3112 return TgtBinaryDescriptorQTy;
3113}
3114
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003115namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00003116struct PrivateHelpersTy {
3117 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
3118 const VarDecl *PrivateElemInit)
3119 : Original(Original), PrivateCopy(PrivateCopy),
3120 PrivateElemInit(PrivateElemInit) {}
3121 const VarDecl *Original;
3122 const VarDecl *PrivateCopy;
3123 const VarDecl *PrivateElemInit;
3124};
3125typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00003126} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003127
Alexey Bataev9e034042015-05-05 04:05:12 +00003128static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00003129createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003130 if (!Privates.empty()) {
3131 auto &C = CGM.getContext();
3132 // Build struct .kmp_privates_t. {
3133 // /* private vars */
3134 // };
3135 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
3136 RD->startDefinition();
3137 for (auto &&Pair : Privates) {
Alexey Bataevc71a4092015-09-11 10:29:41 +00003138 auto *VD = Pair.second.Original;
3139 auto Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003140 Type = Type.getNonReferenceType();
Alexey Bataevc71a4092015-09-11 10:29:41 +00003141 auto *FD = addFieldToRecordDecl(C, RD, Type);
3142 if (VD->hasAttrs()) {
3143 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
3144 E(VD->getAttrs().end());
3145 I != E; ++I)
3146 FD->addAttr(*I);
3147 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003148 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003149 RD->completeDefinition();
3150 return RD;
3151 }
3152 return nullptr;
3153}
3154
Alexey Bataev9e034042015-05-05 04:05:12 +00003155static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00003156createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
3157 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003158 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003159 auto &C = CGM.getContext();
3160 // Build struct kmp_task_t {
3161 // void * shareds;
3162 // kmp_routine_entry_t routine;
3163 // kmp_int32 part_id;
3164 // kmp_routine_entry_t destructors;
Alexey Bataev7292c292016-04-25 12:22:29 +00003165 // For taskloops additional fields:
3166 // kmp_uint64 lb;
3167 // kmp_uint64 ub;
3168 // kmp_int64 st;
3169 // kmp_int32 liter;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003170 // };
3171 auto *RD = C.buildImplicitRecord("kmp_task_t");
3172 RD->startDefinition();
3173 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3174 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
3175 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3176 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00003177 if (isOpenMPTaskLoopDirective(Kind)) {
3178 QualType KmpUInt64Ty =
3179 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
3180 QualType KmpInt64Ty =
3181 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
3182 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
3183 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
3184 addFieldToRecordDecl(C, RD, KmpInt64Ty);
3185 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3186 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003187 RD->completeDefinition();
3188 return RD;
3189}
3190
3191static RecordDecl *
3192createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003193 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003194 auto &C = CGM.getContext();
3195 // Build struct kmp_task_t_with_privates {
3196 // kmp_task_t task_data;
3197 // .kmp_privates_t. privates;
3198 // };
3199 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
3200 RD->startDefinition();
3201 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003202 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
3203 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
3204 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003205 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003206 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003207}
3208
3209/// \brief Emit a proxy function which accepts kmp_task_t as the second
3210/// argument.
3211/// \code
3212/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003213/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00003214/// For taskloops:
3215/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003216/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003217/// return 0;
3218/// }
3219/// \endcode
3220static llvm::Value *
3221emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00003222 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
3223 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003224 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003225 QualType SharedsPtrTy, llvm::Value *TaskFunction,
3226 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003227 auto &C = CGM.getContext();
3228 FunctionArgList Args;
3229 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3230 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003231 /*Id=*/nullptr,
3232 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003233 Args.push_back(&GtidArg);
3234 Args.push_back(&TaskTypeArg);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003235 auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003236 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003237 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
3238 auto *TaskEntry =
3239 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
3240 ".omp_task_entry.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003241 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003242 CodeGenFunction CGF(CGM);
3243 CGF.disableDebugInfo();
3244 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
3245
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003246 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00003247 // tt,
3248 // For taskloops:
3249 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
3250 // tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003251 auto *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00003252 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00003253 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3254 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3255 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003256 auto *KmpTaskTWithPrivatesQTyRD =
3257 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003258 LValue Base =
3259 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003260 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
3261 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3262 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003263 auto *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003264
3265 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3266 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003267 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003268 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003269 CGF.ConvertTypeForMem(SharedsPtrTy));
3270
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003271 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3272 llvm::Value *PrivatesParam;
3273 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3274 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
3275 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003276 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00003277 } else
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003278 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003279
Alexey Bataev7292c292016-04-25 12:22:29 +00003280 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
3281 TaskPrivatesMap,
3282 CGF.Builder
3283 .CreatePointerBitCastOrAddrSpaceCast(
3284 TDBase.getAddress(), CGF.VoidPtrTy)
3285 .getPointer()};
3286 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
3287 std::end(CommonArgs));
3288 if (isOpenMPTaskLoopDirective(Kind)) {
3289 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3290 auto LBLVal = CGF.EmitLValueForField(Base, *LBFI);
3291 auto *LBParam = CGF.EmitLoadOfLValue(LBLVal, Loc).getScalarVal();
3292 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3293 auto UBLVal = CGF.EmitLValueForField(Base, *UBFI);
3294 auto *UBParam = CGF.EmitLoadOfLValue(UBLVal, Loc).getScalarVal();
3295 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3296 auto StLVal = CGF.EmitLValueForField(Base, *StFI);
3297 auto *StParam = CGF.EmitLoadOfLValue(StLVal, Loc).getScalarVal();
3298 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3299 auto LILVal = CGF.EmitLValueForField(Base, *LIFI);
3300 auto *LIParam = CGF.EmitLoadOfLValue(LILVal, Loc).getScalarVal();
3301 CallArgs.push_back(LBParam);
3302 CallArgs.push_back(UBParam);
3303 CallArgs.push_back(StParam);
3304 CallArgs.push_back(LIParam);
3305 }
3306 CallArgs.push_back(SharedsParam);
3307
Alexey Bataev62b63b12015-03-10 07:28:44 +00003308 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
3309 CGF.EmitStoreThroughLValue(
3310 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
John McCall7f416cc2015-09-08 08:05:57 +00003311 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00003312 CGF.FinishFunction();
3313 return TaskEntry;
3314}
3315
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003316static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
3317 SourceLocation Loc,
3318 QualType KmpInt32Ty,
3319 QualType KmpTaskTWithPrivatesPtrQTy,
3320 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003321 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003322 FunctionArgList Args;
3323 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3324 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003325 /*Id=*/nullptr,
3326 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003327 Args.push_back(&GtidArg);
3328 Args.push_back(&TaskTypeArg);
3329 FunctionType::ExtInfo Info;
3330 auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003331 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003332 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
3333 auto *DestructorFn =
3334 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3335 ".omp_task_destructor.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003336 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
3337 DestructorFnInfo);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003338 CodeGenFunction CGF(CGM);
3339 CGF.disableDebugInfo();
3340 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
3341 Args);
3342
Alexey Bataev31300ed2016-02-04 11:27:03 +00003343 LValue Base = CGF.EmitLoadOfPointerLValue(
3344 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3345 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003346 auto *KmpTaskTWithPrivatesQTyRD =
3347 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3348 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003349 Base = CGF.EmitLValueForField(Base, *FI);
3350 for (auto *Field :
3351 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3352 if (auto DtorKind = Field->getType().isDestructedType()) {
3353 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
3354 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3355 }
3356 }
3357 CGF.FinishFunction();
3358 return DestructorFn;
3359}
3360
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003361/// \brief Emit a privates mapping function for correct handling of private and
3362/// firstprivate variables.
3363/// \code
3364/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
3365/// **noalias priv1,..., <tyn> **noalias privn) {
3366/// *priv1 = &.privates.priv1;
3367/// ...;
3368/// *privn = &.privates.privn;
3369/// }
3370/// \endcode
3371static llvm::Value *
3372emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00003373 ArrayRef<const Expr *> PrivateVars,
3374 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00003375 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003376 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003377 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003378 auto &C = CGM.getContext();
3379 FunctionArgList Args;
3380 ImplicitParamDecl TaskPrivatesArg(
3381 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3382 C.getPointerType(PrivatesQTy).withConst().withRestrict());
3383 Args.push_back(&TaskPrivatesArg);
3384 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
3385 unsigned Counter = 1;
3386 for (auto *E: PrivateVars) {
3387 Args.push_back(ImplicitParamDecl::Create(
3388 C, /*DC=*/nullptr, Loc,
3389 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3390 .withConst()
3391 .withRestrict()));
3392 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3393 PrivateVarsPos[VD] = Counter;
3394 ++Counter;
3395 }
3396 for (auto *E : FirstprivateVars) {
3397 Args.push_back(ImplicitParamDecl::Create(
3398 C, /*DC=*/nullptr, Loc,
3399 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3400 .withConst()
3401 .withRestrict()));
3402 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3403 PrivateVarsPos[VD] = Counter;
3404 ++Counter;
3405 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00003406 for (auto *E: LastprivateVars) {
3407 Args.push_back(ImplicitParamDecl::Create(
3408 C, /*DC=*/nullptr, Loc,
3409 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3410 .withConst()
3411 .withRestrict()));
3412 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3413 PrivateVarsPos[VD] = Counter;
3414 ++Counter;
3415 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003416 auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003417 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003418 auto *TaskPrivatesMapTy =
3419 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
3420 auto *TaskPrivatesMap = llvm::Function::Create(
3421 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
3422 ".omp_task_privates_map.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003423 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
3424 TaskPrivatesMapFnInfo);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00003425 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003426 CodeGenFunction CGF(CGM);
3427 CGF.disableDebugInfo();
3428 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
3429 TaskPrivatesMapFnInfo, Args);
3430
3431 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00003432 LValue Base = CGF.EmitLoadOfPointerLValue(
3433 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
3434 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003435 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
3436 Counter = 0;
3437 for (auto *Field : PrivatesQTyRD->fields()) {
3438 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
3439 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
John McCall7f416cc2015-09-08 08:05:57 +00003440 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
Alexey Bataev31300ed2016-02-04 11:27:03 +00003441 auto RefLoadLVal = CGF.EmitLoadOfPointerLValue(
3442 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003443 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003444 ++Counter;
3445 }
3446 CGF.FinishFunction();
3447 return TaskPrivatesMap;
3448}
3449
Alexey Bataev9e034042015-05-05 04:05:12 +00003450static int array_pod_sort_comparator(const PrivateDataTy *P1,
3451 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003452 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
3453}
3454
Alexey Bataevf93095a2016-05-05 08:46:22 +00003455/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00003456static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00003457 const OMPExecutableDirective &D,
3458 Address KmpTaskSharedsPtr, LValue TDBase,
3459 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
3460 QualType SharedsTy, QualType SharedsPtrTy,
3461 const OMPTaskDataTy &Data,
3462 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
3463 auto &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00003464 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3465 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
3466 LValue SrcBase;
3467 if (!Data.FirstprivateVars.empty()) {
3468 SrcBase = CGF.MakeAddrLValue(
3469 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3470 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
3471 SharedsTy);
3472 }
3473 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
3474 cast<CapturedStmt>(*D.getAssociatedStmt()));
3475 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
3476 for (auto &&Pair : Privates) {
3477 auto *VD = Pair.second.PrivateCopy;
3478 auto *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00003479 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
3480 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00003481 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003482 if (auto *Elem = Pair.second.PrivateElemInit) {
3483 auto *OriginalVD = Pair.second.Original;
3484 auto *SharedField = CapturesInfo.lookup(OriginalVD);
3485 auto SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
3486 SharedRefLValue = CGF.MakeAddrLValue(
3487 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
3488 SharedRefLValue.getType(), AlignmentSource::Decl);
3489 QualType Type = OriginalVD->getType();
3490 if (Type->isArrayType()) {
3491 // Initialize firstprivate array.
3492 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
3493 // Perform simple memcpy.
3494 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
3495 SharedRefLValue.getAddress(), Type);
3496 } else {
3497 // Initialize firstprivate array using element-by-element
3498 // intialization.
3499 CGF.EmitOMPAggregateAssign(
3500 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
3501 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
3502 Address SrcElement) {
3503 // Clean up any temporaries needed by the initialization.
3504 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3505 InitScope.addPrivate(
3506 Elem, [SrcElement]() -> Address { return SrcElement; });
3507 (void)InitScope.Privatize();
3508 // Emit initialization for single element.
3509 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3510 CGF, &CapturesInfo);
3511 CGF.EmitAnyExprToMem(Init, DestElement,
3512 Init->getType().getQualifiers(),
3513 /*IsInitializer=*/false);
3514 });
3515 }
3516 } else {
3517 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3518 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
3519 return SharedRefLValue.getAddress();
3520 });
3521 (void)InitScope.Privatize();
3522 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
3523 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
3524 /*capturedByInit=*/false);
3525 }
3526 } else
3527 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
3528 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00003529 ++FI;
3530 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00003531}
3532
3533/// Check if duplication function is required for taskloops.
3534static bool checkInitIsRequired(CodeGenFunction &CGF,
3535 ArrayRef<PrivateDataTy> Privates) {
3536 bool InitRequired = false;
3537 for (auto &&Pair : Privates) {
3538 auto *VD = Pair.second.PrivateCopy;
3539 auto *Init = VD->getAnyInitializer();
3540 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
3541 !CGF.isTrivialInitializer(Init));
3542 }
3543 return InitRequired;
3544}
3545
3546
3547/// Emit task_dup function (for initialization of
3548/// private/firstprivate/lastprivate vars and last_iter flag)
3549/// \code
3550/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
3551/// lastpriv) {
3552/// // setup lastprivate flag
3553/// task_dst->last = lastpriv;
3554/// // could be constructor calls here...
3555/// }
3556/// \endcode
3557static llvm::Value *
3558emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
3559 const OMPExecutableDirective &D,
3560 QualType KmpTaskTWithPrivatesPtrQTy,
3561 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
3562 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
3563 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
3564 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
3565 auto &C = CGM.getContext();
3566 FunctionArgList Args;
3567 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc,
3568 /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
3569 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc,
3570 /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
3571 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc,
3572 /*Id=*/nullptr, C.IntTy);
3573 Args.push_back(&DstArg);
3574 Args.push_back(&SrcArg);
3575 Args.push_back(&LastprivArg);
3576 auto &TaskDupFnInfo =
3577 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
3578 auto *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
3579 auto *TaskDup =
3580 llvm::Function::Create(TaskDupTy, llvm::GlobalValue::InternalLinkage,
3581 ".omp_task_dup.", &CGM.getModule());
3582 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskDup, TaskDupFnInfo);
3583 CodeGenFunction CGF(CGM);
3584 CGF.disableDebugInfo();
3585 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args);
3586
3587 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3588 CGF.GetAddrOfLocalVar(&DstArg),
3589 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3590 // task_dst->liter = lastpriv;
3591 if (WithLastIter) {
3592 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3593 LValue Base = CGF.EmitLValueForField(
3594 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
3595 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
3596 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
3597 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
3598 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
3599 }
3600
3601 // Emit initial values for private copies (if any).
3602 assert(!Privates.empty());
3603 Address KmpTaskSharedsPtr = Address::invalid();
3604 if (!Data.FirstprivateVars.empty()) {
3605 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3606 CGF.GetAddrOfLocalVar(&SrcArg),
3607 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
3608 LValue Base = CGF.EmitLValueForField(
3609 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
3610 KmpTaskSharedsPtr = Address(
3611 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
3612 Base, *std::next(KmpTaskTQTyRD->field_begin(),
3613 KmpTaskTShareds)),
3614 Loc),
3615 CGF.getNaturalTypeAlignment(SharedsTy));
3616 }
Alexey Bataev8a831592016-05-10 10:36:51 +00003617 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3618 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003619 CGF.FinishFunction();
3620 return TaskDup;
3621}
3622
Alexey Bataev8a831592016-05-10 10:36:51 +00003623/// Checks if destructor function is required to be generated.
3624/// \return true if cleanups are required, false otherwise.
3625static bool
3626checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
3627 bool NeedsCleanup = false;
3628 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3629 auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
3630 for (auto *FD : PrivateRD->fields()) {
3631 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
3632 if (NeedsCleanup)
3633 break;
3634 }
3635 return NeedsCleanup;
3636}
3637
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003638CGOpenMPRuntime::TaskResultTy
3639CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
3640 const OMPExecutableDirective &D,
3641 llvm::Value *TaskFunction, QualType SharedsTy,
3642 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003643 auto &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00003644 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003645 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003646 auto I = Data.PrivateCopies.begin();
3647 for (auto *E : Data.PrivateVars) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003648 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3649 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003650 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003651 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3652 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003653 ++I;
3654 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003655 I = Data.FirstprivateCopies.begin();
3656 auto IElemInitRef = Data.FirstprivateInits.begin();
3657 for (auto *E : Data.FirstprivateVars) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003658 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3659 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003660 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003661 PrivateHelpersTy(
3662 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3663 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
Richard Trieucc3949d2016-02-18 22:34:54 +00003664 ++I;
3665 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00003666 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00003667 I = Data.LastprivateCopies.begin();
3668 for (auto *E : Data.LastprivateVars) {
3669 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3670 Privates.push_back(std::make_pair(
3671 C.getDeclAlign(VD),
3672 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3673 /*PrivateElemInit=*/nullptr)));
3674 ++I;
3675 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003676 llvm::array_pod_sort(Privates.begin(), Privates.end(),
3677 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003678 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
3679 // Build type kmp_routine_entry_t (if not built yet).
3680 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003681 // Build type kmp_task_t (if not built yet).
3682 if (KmpTaskTQTy.isNull()) {
Alexey Bataev7292c292016-04-25 12:22:29 +00003683 KmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
3684 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003685 }
3686 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003687 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003688 auto *KmpTaskTWithPrivatesQTyRD =
3689 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
3690 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
3691 QualType KmpTaskTWithPrivatesPtrQTy =
3692 C.getPointerType(KmpTaskTWithPrivatesQTy);
3693 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
3694 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003695 auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003696 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
3697
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003698 // Emit initial values for private copies (if any).
3699 llvm::Value *TaskPrivatesMap = nullptr;
3700 auto *TaskPrivatesMapTy =
3701 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
3702 3)
3703 ->getType();
3704 if (!Privates.empty()) {
3705 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00003706 TaskPrivatesMap = emitTaskPrivateMappingFunction(
3707 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
3708 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003709 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3710 TaskPrivatesMap, TaskPrivatesMapTy);
3711 } else {
3712 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3713 cast<llvm::PointerType>(TaskPrivatesMapTy));
3714 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003715 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
3716 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003717 auto *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00003718 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3719 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3720 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003721
3722 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
3723 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
3724 // kmp_routine_entry_t *task_entry);
3725 // Task flags. Format is taken from
3726 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
3727 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00003728 enum {
3729 TiedFlag = 0x1,
3730 FinalFlag = 0x2,
3731 DestructorsFlag = 0x8,
3732 PriorityFlag = 0x20
3733 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003734 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00003735 bool NeedsCleanup = false;
3736 if (!Privates.empty()) {
3737 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
3738 if (NeedsCleanup)
3739 Flags = Flags | DestructorsFlag;
3740 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00003741 if (Data.Priority.getInt())
3742 Flags = Flags | PriorityFlag;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003743 auto *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003744 Data.Final.getPointer()
3745 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00003746 CGF.Builder.getInt32(FinalFlag),
3747 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003748 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003749 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataev40e36f12015-11-24 13:01:44 +00003750 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003751 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
3752 getThreadID(CGF, Loc), TaskFlags,
3753 KmpTaskTWithPrivatesTySize, SharedsSize,
3754 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3755 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003756 auto *NewTask = CGF.EmitRuntimeCall(
3757 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003758 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3759 NewTask, KmpTaskTWithPrivatesPtrTy);
3760 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
3761 KmpTaskTWithPrivatesQTy);
3762 LValue TDBase =
3763 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003764 // Fill the data in the resulting kmp_task_t record.
3765 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00003766 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003767 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003768 KmpTaskSharedsPtr =
3769 Address(CGF.EmitLoadOfScalar(
3770 CGF.EmitLValueForField(
3771 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
3772 KmpTaskTShareds)),
3773 Loc),
3774 CGF.getNaturalTypeAlignment(SharedsTy));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003775 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003776 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003777 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00003778 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003779 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00003780 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
3781 SharedsTy, SharedsPtrTy, Data, Privates,
3782 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003783 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
3784 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
3785 Result.TaskDupFn = emitTaskDupFunction(
3786 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
3787 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
3788 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003789 }
3790 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003791 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003792 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003793 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
3794 KmpTaskTWithPrivatesPtrQTy,
3795 KmpTaskTWithPrivatesQTy)
3796 : llvm::ConstantPointerNull::get(
3797 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
3798 LValue Destructor = CGF.EmitLValueForField(
3799 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
3800 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3801 DestructorFn, KmpRoutineEntryPtrTy),
3802 Destructor);
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003803 Result.NewTask = NewTask;
3804 Result.TaskEntry = TaskEntry;
3805 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
3806 Result.TDBase = TDBase;
3807 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
3808 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00003809}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003810
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003811void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
3812 const OMPExecutableDirective &D,
3813 llvm::Value *TaskFunction,
3814 QualType SharedsTy, Address Shareds,
3815 const Expr *IfCond,
3816 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00003817 if (!CGF.HaveInsertPoint())
3818 return;
3819
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003820 TaskResultTy Result =
3821 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
3822 llvm::Value *NewTask = Result.NewTask;
3823 llvm::Value *TaskEntry = Result.TaskEntry;
3824 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
3825 LValue TDBase = Result.TDBase;
3826 RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
Alexey Bataev7292c292016-04-25 12:22:29 +00003827 auto &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003828 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00003829 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003830 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00003831 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003832 // Dependence kind for RTL.
Alexey Bataev92e82f92015-11-23 13:33:42 +00003833 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003834 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
3835 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003836 QualType FlagsTy =
3837 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003838 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
3839 if (KmpDependInfoTy.isNull()) {
3840 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
3841 KmpDependInfoRD->startDefinition();
3842 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
3843 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
3844 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
3845 KmpDependInfoRD->completeDefinition();
3846 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003847 } else
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003848 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003849 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003850 // Define type kmp_depend_info[<Dependences.size()>];
3851 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00003852 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003853 ArrayType::Normal, /*IndexTypeQuals=*/0);
3854 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00003855 DependenciesArray =
3856 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
John McCall7f416cc2015-09-08 08:05:57 +00003857 for (unsigned i = 0; i < NumDependencies; ++i) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003858 const Expr *E = Data.Dependences[i].second;
John McCall7f416cc2015-09-08 08:05:57 +00003859 auto Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003860 llvm::Value *Size;
3861 QualType Ty = E->getType();
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003862 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
3863 LValue UpAddrLVal =
3864 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
3865 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00003866 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003867 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00003868 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003869 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
3870 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003871 } else
Alexey Bataev1189bd02016-01-26 12:20:39 +00003872 Size = CGF.getTypeSize(Ty);
John McCall7f416cc2015-09-08 08:05:57 +00003873 auto Base = CGF.MakeAddrLValue(
3874 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003875 KmpDependInfoTy);
3876 // deps[i].base_addr = &<Dependences[i].second>;
3877 auto BaseAddrLVal = CGF.EmitLValueForField(
3878 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00003879 CGF.EmitStoreOfScalar(
3880 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
3881 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003882 // deps[i].len = sizeof(<Dependences[i].second>);
3883 auto LenLVal = CGF.EmitLValueForField(
3884 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
3885 CGF.EmitStoreOfScalar(Size, LenLVal);
3886 // deps[i].flags = <Dependences[i].first>;
3887 RTLDependenceKindTy DepKind;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003888 switch (Data.Dependences[i].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003889 case OMPC_DEPEND_in:
3890 DepKind = DepIn;
3891 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00003892 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003893 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003894 case OMPC_DEPEND_inout:
3895 DepKind = DepInOut;
3896 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00003897 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00003898 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003899 case OMPC_DEPEND_unknown:
3900 llvm_unreachable("Unknown task dependence type");
3901 }
3902 auto FlagsLVal = CGF.EmitLValueForField(
3903 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
3904 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
3905 FlagsLVal);
3906 }
John McCall7f416cc2015-09-08 08:05:57 +00003907 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3908 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003909 CGF.VoidPtrTy);
3910 }
3911
Alexey Bataev62b63b12015-03-10 07:28:44 +00003912 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
3913 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003914 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
3915 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
3916 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
3917 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00003918 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003919 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00003920 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
3921 llvm::Value *DepTaskArgs[7];
3922 if (NumDependencies) {
3923 DepTaskArgs[0] = UpLoc;
3924 DepTaskArgs[1] = ThreadID;
3925 DepTaskArgs[2] = NewTask;
3926 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
3927 DepTaskArgs[4] = DependenciesArray.getPointer();
3928 DepTaskArgs[5] = CGF.Builder.getInt32(0);
3929 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3930 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003931 auto &&ThenCodeGen = [this, Loc, &Data, TDBase, KmpTaskTQTyRD,
Alexey Bataev48591dd2016-04-20 04:01:36 +00003932 NumDependencies, &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003933 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003934 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003935 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3936 auto PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
3937 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
3938 }
John McCall7f416cc2015-09-08 08:05:57 +00003939 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003940 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00003941 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00003942 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003943 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00003944 TaskArgs);
3945 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00003946 // Check if parent region is untied and build return for untied task;
3947 if (auto *Region =
3948 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3949 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003950 };
John McCall7f416cc2015-09-08 08:05:57 +00003951
3952 llvm::Value *DepWaitTaskArgs[6];
3953 if (NumDependencies) {
3954 DepWaitTaskArgs[0] = UpLoc;
3955 DepWaitTaskArgs[1] = ThreadID;
3956 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
3957 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
3958 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
3959 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3960 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003961 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
3962 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF,
3963 PrePostActionTy &) {
3964 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003965 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
3966 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
3967 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
3968 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
3969 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00003970 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003971 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003972 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003973 // Call proxy_task_entry(gtid, new_task);
3974 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy](
3975 CodeGenFunction &CGF, PrePostActionTy &Action) {
3976 Action.Enter(CGF);
3977 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
3978 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
3979 };
3980
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003981 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
3982 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003983 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
3984 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003985 RegionCodeGenTy RCG(CodeGen);
3986 CommonActionTy Action(
3987 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
3988 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
3989 RCG.setAction(Action);
3990 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003991 };
John McCall7f416cc2015-09-08 08:05:57 +00003992
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003993 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00003994 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003995 else {
3996 RegionCodeGenTy ThenRCG(ThenCodeGen);
3997 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003998 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003999}
4000
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004001void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
4002 const OMPLoopDirective &D,
4003 llvm::Value *TaskFunction,
4004 QualType SharedsTy, Address Shareds,
4005 const Expr *IfCond,
4006 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00004007 if (!CGF.HaveInsertPoint())
4008 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004009 TaskResultTy Result =
4010 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexey Bataev7292c292016-04-25 12:22:29 +00004011 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
4012 // libcall.
4013 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
4014 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
4015 // sched, kmp_uint64 grainsize, void *task_dup);
4016 llvm::Value *ThreadID = getThreadID(CGF, Loc);
4017 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
4018 llvm::Value *IfVal;
4019 if (IfCond) {
4020 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
4021 /*isSigned=*/true);
4022 } else
4023 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
4024
4025 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004026 Result.TDBase,
4027 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataev7292c292016-04-25 12:22:29 +00004028 auto *LBVar =
4029 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
4030 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
4031 /*IsInitializer=*/true);
4032 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004033 Result.TDBase,
4034 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataev7292c292016-04-25 12:22:29 +00004035 auto *UBVar =
4036 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
4037 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
4038 /*IsInitializer=*/true);
4039 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004040 Result.TDBase,
4041 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataev7292c292016-04-25 12:22:29 +00004042 auto *StVar =
4043 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
4044 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
4045 /*IsInitializer=*/true);
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00004046 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00004047 llvm::Value *TaskArgs[] = {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004048 UpLoc, ThreadID, Result.NewTask, IfVal, LBLVal.getPointer(),
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00004049 UBLVal.getPointer(), CGF.EmitLoadOfScalar(StLVal, SourceLocation()),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004050 llvm::ConstantInt::getSigned(CGF.IntTy, Data.Nogroup ? 1 : 0),
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00004051 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004052 CGF.IntTy, Data.Schedule.getPointer()
4053 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00004054 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004055 Data.Schedule.getPointer()
4056 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00004057 /*isSigned=*/false)
4058 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataevf93095a2016-05-05 08:46:22 +00004059 Result.TaskDupFn
4060 ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Result.TaskDupFn,
4061 CGF.VoidPtrTy)
4062 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00004063 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
4064}
4065
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004066/// \brief Emit reduction operation for each element of array (required for
4067/// array sections) LHS op = RHS.
4068/// \param Type Type of array.
4069/// \param LHSVar Variable on the left side of the reduction operation
4070/// (references element of array in original variable).
4071/// \param RHSVar Variable on the right side of the reduction operation
4072/// (references element of array in original variable).
4073/// \param RedOpGen Generator of reduction operation with use of LHSVar and
4074/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00004075static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004076 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
4077 const VarDecl *RHSVar,
4078 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
4079 const Expr *, const Expr *)> &RedOpGen,
4080 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
4081 const Expr *UpExpr = nullptr) {
4082 // Perform element-by-element initialization.
4083 QualType ElementTy;
4084 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
4085 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
4086
4087 // Drill down to the base element type on both arrays.
4088 auto ArrayTy = Type->getAsArrayTypeUnsafe();
4089 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4090
4091 auto RHSBegin = RHSAddr.getPointer();
4092 auto LHSBegin = LHSAddr.getPointer();
4093 // Cast from pointer to array type to pointer to single element.
4094 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
4095 // The basic structure here is a while-do loop.
4096 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
4097 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
4098 auto IsEmpty =
4099 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
4100 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4101
4102 // Enter the loop body, making that address the current address.
4103 auto EntryBB = CGF.Builder.GetInsertBlock();
4104 CGF.EmitBlock(BodyBB);
4105
4106 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
4107
4108 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
4109 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
4110 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4111 Address RHSElementCurrent =
4112 Address(RHSElementPHI,
4113 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
4114
4115 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
4116 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
4117 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4118 Address LHSElementCurrent =
4119 Address(LHSElementPHI,
4120 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
4121
4122 // Emit copy.
4123 CodeGenFunction::OMPPrivateScope Scope(CGF);
4124 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
4125 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
4126 Scope.Privatize();
4127 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4128 Scope.ForceCleanup();
4129
4130 // Shift the address forward by one element.
4131 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
4132 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
4133 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
4134 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
4135 // Check whether we've reached the end.
4136 auto Done =
4137 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
4138 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
4139 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
4140 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
4141
4142 // Done.
4143 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
4144}
4145
Alexey Bataeva839ddd2016-03-17 10:19:46 +00004146/// Emit reduction combiner. If the combiner is a simple expression emit it as
4147/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
4148/// UDR combiner function.
4149static void emitReductionCombiner(CodeGenFunction &CGF,
4150 const Expr *ReductionOp) {
4151 if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
4152 if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4153 if (auto *DRE =
4154 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4155 if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4156 std::pair<llvm::Function *, llvm::Function *> Reduction =
4157 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
4158 RValue Func = RValue::get(Reduction.first);
4159 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
4160 CGF.EmitIgnoredExpr(ReductionOp);
4161 return;
4162 }
4163 CGF.EmitIgnoredExpr(ReductionOp);
4164}
4165
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004166static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
4167 llvm::Type *ArgsType,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004168 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004169 ArrayRef<const Expr *> LHSExprs,
4170 ArrayRef<const Expr *> RHSExprs,
4171 ArrayRef<const Expr *> ReductionOps) {
4172 auto &C = CGM.getContext();
4173
4174 // void reduction_func(void *LHSArg, void *RHSArg);
4175 FunctionArgList Args;
4176 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
4177 C.VoidPtrTy);
4178 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
4179 C.VoidPtrTy);
4180 Args.push_back(&LHSArg);
4181 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00004182 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004183 auto *Fn = llvm::Function::Create(
4184 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
4185 ".omp.reduction.reduction_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004186 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004187 CodeGenFunction CGF(CGM);
4188 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
4189
4190 // Dst = (void*[n])(LHSArg);
4191 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00004192 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4193 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
4194 ArgsType), CGF.getPointerAlign());
4195 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4196 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
4197 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004198
4199 // ...
4200 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
4201 // ...
4202 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004203 auto IPriv = Privates.begin();
4204 unsigned Idx = 0;
4205 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00004206 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
4207 Scope.addPrivate(RHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004208 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00004209 });
4210 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
4211 Scope.addPrivate(LHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004212 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00004213 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004214 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00004215 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004216 // Get array size and emit VLA type.
4217 ++Idx;
4218 Address Elem =
4219 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
4220 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00004221 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy);
4222 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004223 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00004224 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004225 CGF.EmitVariablyModifiedType(PrivTy);
4226 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004227 }
4228 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004229 IPriv = Privates.begin();
4230 auto ILHS = LHSExprs.begin();
4231 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004232 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004233 if ((*IPriv)->getType()->isArrayType()) {
4234 // Emit reduction for array section.
4235 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4236 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00004237 EmitOMPAggregateReduction(
4238 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4239 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
4240 emitReductionCombiner(CGF, E);
4241 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004242 } else
4243 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00004244 emitReductionCombiner(CGF, E);
Richard Trieucc3949d2016-02-18 22:34:54 +00004245 ++IPriv;
4246 ++ILHS;
4247 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004248 }
4249 Scope.ForceCleanup();
4250 CGF.FinishFunction();
4251 return Fn;
4252}
4253
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004254static void emitSingleReductionCombiner(CodeGenFunction &CGF,
4255 const Expr *ReductionOp,
4256 const Expr *PrivateRef,
4257 const DeclRefExpr *LHS,
4258 const DeclRefExpr *RHS) {
4259 if (PrivateRef->getType()->isArrayType()) {
4260 // Emit reduction for array section.
4261 auto *LHSVar = cast<VarDecl>(LHS->getDecl());
4262 auto *RHSVar = cast<VarDecl>(RHS->getDecl());
4263 EmitOMPAggregateReduction(
4264 CGF, PrivateRef->getType(), LHSVar, RHSVar,
4265 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
4266 emitReductionCombiner(CGF, ReductionOp);
4267 });
4268 } else
4269 // Emit reduction for array subscript or single variable.
4270 emitReductionCombiner(CGF, ReductionOp);
4271}
4272
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004273void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004274 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004275 ArrayRef<const Expr *> LHSExprs,
4276 ArrayRef<const Expr *> RHSExprs,
4277 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00004278 bool WithNowait, bool SimpleReduction) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004279 if (!CGF.HaveInsertPoint())
4280 return;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004281 // Next code should be emitted for reduction:
4282 //
4283 // static kmp_critical_name lock = { 0 };
4284 //
4285 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
4286 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
4287 // ...
4288 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
4289 // *(Type<n>-1*)rhs[<n>-1]);
4290 // }
4291 //
4292 // ...
4293 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
4294 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
4295 // RedList, reduce_func, &<lock>)) {
4296 // case 1:
4297 // ...
4298 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
4299 // ...
4300 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
4301 // break;
4302 // case 2:
4303 // ...
4304 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
4305 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00004306 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004307 // break;
4308 // default:;
4309 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00004310 //
4311 // if SimpleReduction is true, only the next code is generated:
4312 // ...
4313 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
4314 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004315
4316 auto &C = CGM.getContext();
4317
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00004318 if (SimpleReduction) {
4319 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004320 auto IPriv = Privates.begin();
4321 auto ILHS = LHSExprs.begin();
4322 auto IRHS = RHSExprs.begin();
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00004323 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004324 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
4325 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00004326 ++IPriv;
4327 ++ILHS;
4328 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00004329 }
4330 return;
4331 }
4332
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004333 // 1. Build a list of reduction variables.
4334 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004335 auto Size = RHSExprs.size();
4336 for (auto *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00004337 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004338 // Reserve place for array size.
4339 ++Size;
4340 }
4341 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004342 QualType ReductionArrayTy =
4343 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
4344 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00004345 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004346 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004347 auto IPriv = Privates.begin();
4348 unsigned Idx = 0;
4349 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00004350 Address Elem =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004351 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00004352 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004353 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00004354 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
4355 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00004356 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004357 // Store array size.
4358 ++Idx;
4359 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
4360 CGF.getPointerSize());
Alexey Bataev1189bd02016-01-26 12:20:39 +00004361 llvm::Value *Size = CGF.Builder.CreateIntCast(
4362 CGF.getVLASize(
4363 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
4364 .first,
4365 CGF.SizeTy, /*isSigned=*/false);
4366 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
4367 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004368 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004369 }
4370
4371 // 2. Emit reduce_func().
4372 auto *ReductionFn = emitReductionFunction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004373 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
4374 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004375
4376 // 3. Create static kmp_critical_name lock = { 0 };
4377 auto *Lock = getCriticalRegionLock(".reduction");
4378
4379 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
4380 // RedList, reduce_func, &<lock>);
Alexey Bataev50b3c952016-02-19 10:38:26 +00004381 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004382 auto *ThreadId = getThreadID(CGF, Loc);
Alexey Bataev1189bd02016-01-26 12:20:39 +00004383 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00004384 auto *RL =
4385 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
4386 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004387 llvm::Value *Args[] = {
4388 IdentTLoc, // ident_t *<loc>
4389 ThreadId, // i32 <gtid>
4390 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
4391 ReductionArrayTySize, // size_type sizeof(RedList)
4392 RL, // void *RedList
4393 ReductionFn, // void (*) (void *, void *) <reduce_func>
4394 Lock // kmp_critical_name *&<lock>
4395 };
4396 auto Res = CGF.EmitRuntimeCall(
4397 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
4398 : OMPRTL__kmpc_reduce),
4399 Args);
4400
4401 // 5. Build switch(res)
4402 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
4403 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
4404
4405 // 6. Build case 1:
4406 // ...
4407 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
4408 // ...
4409 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
4410 // break;
4411 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
4412 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
4413 CGF.EmitBlock(Case1BB);
4414
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004415 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
4416 llvm::Value *EndArgs[] = {
4417 IdentTLoc, // ident_t *<loc>
4418 ThreadId, // i32 <gtid>
4419 Lock // kmp_critical_name *&<lock>
4420 };
4421 auto &&CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps](
4422 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004423 auto IPriv = Privates.begin();
4424 auto ILHS = LHSExprs.begin();
4425 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004426 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004427 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
4428 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00004429 ++IPriv;
4430 ++ILHS;
4431 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004432 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004433 };
4434 RegionCodeGenTy RCG(CodeGen);
4435 CommonActionTy Action(
4436 nullptr, llvm::None,
4437 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
4438 : OMPRTL__kmpc_end_reduce),
4439 EndArgs);
4440 RCG.setAction(Action);
4441 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004442
4443 CGF.EmitBranch(DefaultBB);
4444
4445 // 7. Build case 2:
4446 // ...
4447 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
4448 // ...
4449 // break;
4450 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
4451 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
4452 CGF.EmitBlock(Case2BB);
4453
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004454 auto &&AtomicCodeGen = [Loc, &Privates, &LHSExprs, &RHSExprs, &ReductionOps](
4455 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004456 auto ILHS = LHSExprs.begin();
4457 auto IRHS = RHSExprs.begin();
4458 auto IPriv = Privates.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004459 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004460 const Expr *XExpr = nullptr;
4461 const Expr *EExpr = nullptr;
4462 const Expr *UpExpr = nullptr;
4463 BinaryOperatorKind BO = BO_Comma;
4464 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
4465 if (BO->getOpcode() == BO_Assign) {
4466 XExpr = BO->getLHS();
4467 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004468 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004469 }
4470 // Try to emit update expression as a simple atomic.
4471 auto *RHSExpr = UpExpr;
4472 if (RHSExpr) {
4473 // Analyze RHS part of the whole expression.
4474 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
4475 RHSExpr->IgnoreParenImpCasts())) {
4476 // If this is a conditional operator, analyze its condition for
4477 // min/max reduction operator.
4478 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00004479 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004480 if (auto *BORHS =
4481 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
4482 EExpr = BORHS->getRHS();
4483 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004484 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004485 }
4486 if (XExpr) {
4487 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4488 auto &&AtomicRedGen = [BO, VD, IPriv,
4489 Loc](CodeGenFunction &CGF, const Expr *XExpr,
4490 const Expr *EExpr, const Expr *UpExpr) {
4491 LValue X = CGF.EmitLValue(XExpr);
4492 RValue E;
4493 if (EExpr)
4494 E = CGF.EmitAnyExpr(EExpr);
4495 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00004496 X, E, BO, /*IsXLHSInRHSPart=*/true,
4497 llvm::AtomicOrdering::Monotonic, Loc,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004498 [&CGF, UpExpr, VD, IPriv, Loc](RValue XRValue) {
4499 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4500 PrivateScope.addPrivate(
4501 VD, [&CGF, VD, XRValue, Loc]() -> Address {
4502 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
4503 CGF.emitOMPSimpleStore(
4504 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
4505 VD->getType().getNonReferenceType(), Loc);
4506 return LHSTemp;
4507 });
4508 (void)PrivateScope.Privatize();
4509 return CGF.EmitAnyExpr(UpExpr);
4510 });
4511 };
4512 if ((*IPriv)->getType()->isArrayType()) {
4513 // Emit atomic reduction for array section.
4514 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4515 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
4516 AtomicRedGen, XExpr, EExpr, UpExpr);
4517 } else
4518 // Emit atomic reduction for array subscript or single variable.
4519 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
4520 } else {
4521 // Emit as a critical region.
4522 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
4523 const Expr *, const Expr *) {
4524 auto &RT = CGF.CGM.getOpenMPRuntime();
4525 RT.emitCriticalRegion(
4526 CGF, ".atomic_reduction",
4527 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
4528 Action.Enter(CGF);
4529 emitReductionCombiner(CGF, E);
4530 },
4531 Loc);
4532 };
4533 if ((*IPriv)->getType()->isArrayType()) {
4534 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4535 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4536 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4537 CritRedGen);
4538 } else
4539 CritRedGen(CGF, nullptr, nullptr, nullptr);
4540 }
Richard Trieucc3949d2016-02-18 22:34:54 +00004541 ++ILHS;
4542 ++IRHS;
4543 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004544 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004545 };
4546 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
4547 if (!WithNowait) {
4548 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
4549 llvm::Value *EndArgs[] = {
4550 IdentTLoc, // ident_t *<loc>
4551 ThreadId, // i32 <gtid>
4552 Lock // kmp_critical_name *&<lock>
4553 };
4554 CommonActionTy Action(nullptr, llvm::None,
4555 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
4556 EndArgs);
4557 AtomicRCG.setAction(Action);
4558 AtomicRCG(CGF);
4559 } else
4560 AtomicRCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004561
4562 CGF.EmitBranch(DefaultBB);
4563 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
4564}
4565
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004566void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
4567 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004568 if (!CGF.HaveInsertPoint())
4569 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004570 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
4571 // global_tid);
4572 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
4573 // Ignore return result until untied tasks are supported.
4574 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00004575 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
4576 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004577}
4578
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004579void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004580 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00004581 const RegionCodeGenTy &CodeGen,
4582 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004583 if (!CGF.HaveInsertPoint())
4584 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004585 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004586 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00004587}
4588
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004589namespace {
4590enum RTCancelKind {
4591 CancelNoreq = 0,
4592 CancelParallel = 1,
4593 CancelLoop = 2,
4594 CancelSections = 3,
4595 CancelTaskgroup = 4
4596};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004597} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004598
4599static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
4600 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00004601 if (CancelRegion == OMPD_parallel)
4602 CancelKind = CancelParallel;
4603 else if (CancelRegion == OMPD_for)
4604 CancelKind = CancelLoop;
4605 else if (CancelRegion == OMPD_sections)
4606 CancelKind = CancelSections;
4607 else {
4608 assert(CancelRegion == OMPD_taskgroup);
4609 CancelKind = CancelTaskgroup;
4610 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004611 return CancelKind;
4612}
4613
4614void CGOpenMPRuntime::emitCancellationPointCall(
4615 CodeGenFunction &CGF, SourceLocation Loc,
4616 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004617 if (!CGF.HaveInsertPoint())
4618 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004619 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
4620 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004621 if (auto *OMPRegionInfo =
4622 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00004623 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004624 llvm::Value *Args[] = {
4625 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
4626 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004627 // Ignore return result until untied tasks are supported.
4628 auto *Result = CGF.EmitRuntimeCall(
4629 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
4630 // if (__kmpc_cancellationpoint()) {
4631 // __kmpc_cancel_barrier();
4632 // exit from construct;
4633 // }
4634 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4635 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4636 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4637 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4638 CGF.EmitBlock(ExitBB);
4639 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00004640 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004641 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004642 auto CancelDest =
4643 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004644 CGF.EmitBranchThroughCleanup(CancelDest);
4645 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4646 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004647 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004648}
4649
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004650void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00004651 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004652 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004653 if (!CGF.HaveInsertPoint())
4654 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004655 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
4656 // kmp_int32 cncl_kind);
4657 if (auto *OMPRegionInfo =
4658 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004659 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
4660 PrePostActionTy &) {
4661 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00004662 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004663 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00004664 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
4665 // Ignore return result until untied tasks are supported.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004666 auto *Result = CGF.EmitRuntimeCall(
4667 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00004668 // if (__kmpc_cancel()) {
4669 // __kmpc_cancel_barrier();
4670 // exit from construct;
4671 // }
4672 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4673 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4674 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4675 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4676 CGF.EmitBlock(ExitBB);
4677 // __kmpc_cancel_barrier();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004678 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev87933c72015-09-18 08:07:34 +00004679 // exit from construct;
4680 auto CancelDest =
4681 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
4682 CGF.EmitBranchThroughCleanup(CancelDest);
4683 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4684 };
4685 if (IfCond)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004686 emitOMPIfClause(CGF, IfCond, ThenGen,
4687 [](CodeGenFunction &, PrePostActionTy &) {});
4688 else {
4689 RegionCodeGenTy ThenRCG(ThenGen);
4690 ThenRCG(CGF);
4691 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004692 }
4693}
Samuel Antaobed3c462015-10-02 16:14:20 +00004694
Samuel Antaoee8fb302016-01-06 13:42:12 +00004695/// \brief Obtain information that uniquely identifies a target entry. This
Samuel Antao2de62b02016-02-13 23:35:10 +00004696/// consists of the file and device IDs as well as line number associated with
4697/// the relevant entry source location.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004698static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
4699 unsigned &DeviceID, unsigned &FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004700 unsigned &LineNum) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004701
4702 auto &SM = C.getSourceManager();
4703
4704 // The loc should be always valid and have a file ID (the user cannot use
4705 // #pragma directives in macros)
4706
4707 assert(Loc.isValid() && "Source location is expected to be always valid.");
4708 assert(Loc.isFileID() && "Source location is expected to refer to a file.");
4709
4710 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
4711 assert(PLoc.isValid() && "Source location is expected to be always valid.");
4712
4713 llvm::sys::fs::UniqueID ID;
4714 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
4715 llvm_unreachable("Source file with target region no longer exists!");
4716
4717 DeviceID = ID.getDevice();
4718 FileID = ID.getFile();
4719 LineNum = PLoc.getLine();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004720}
4721
4722void CGOpenMPRuntime::emitTargetOutlinedFunction(
4723 const OMPExecutableDirective &D, StringRef ParentName,
4724 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004725 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004726 assert(!ParentName.empty() && "Invalid target region parent name!");
4727
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004728 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
4729 IsOffloadEntry, CodeGen);
4730}
4731
4732void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
4733 const OMPExecutableDirective &D, StringRef ParentName,
4734 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
4735 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004736 // Create a unique name for the entry function using the source location
4737 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004738 //
Samuel Antao2de62b02016-02-13 23:35:10 +00004739 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00004740 //
4741 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00004742 // mangled name of the function that encloses the target region and BB is the
4743 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004744
4745 unsigned DeviceID;
4746 unsigned FileID;
4747 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004748 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004749 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004750 SmallString<64> EntryFnName;
4751 {
4752 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00004753 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
4754 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004755 }
4756
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004757 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4758
Samuel Antaobed3c462015-10-02 16:14:20 +00004759 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004760 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00004761 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004762
Alexey Bataev7ace49d2016-05-17 08:55:33 +00004763 OutlinedFn =
4764 CGF.GenerateOpenMPCapturedStmtFunction(CS, /*CastValToPtr=*/true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004765
4766 // If this target outline function is not an offload entry, we don't need to
4767 // register it.
4768 if (!IsOffloadEntry)
4769 return;
4770
4771 // The target region ID is used by the runtime library to identify the current
4772 // target region, so it only has to be unique and not necessarily point to
4773 // anything. It could be the pointer to the outlined function that implements
4774 // the target region, but we aren't using that so that the compiler doesn't
4775 // need to keep that, and could therefore inline the host function if proven
4776 // worthwhile during optimization. In the other hand, if emitting code for the
4777 // device, the ID has to be the function address so that it can retrieved from
4778 // the offloading entry and launched by the runtime library. We also mark the
4779 // outlined function to have external linkage in case we are emitting code for
4780 // the device, because these functions will be entry points to the device.
4781
4782 if (CGM.getLangOpts().OpenMPIsDevice) {
4783 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
4784 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage);
4785 } else
4786 OutlinedFnID = new llvm::GlobalVariable(
4787 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
4788 llvm::GlobalValue::PrivateLinkage,
4789 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id");
4790
4791 // Register the information for the entry associated with this target region.
4792 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00004793 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID);
Samuel Antaobed3c462015-10-02 16:14:20 +00004794}
4795
Carlo Bertolli6eee9062016-04-29 01:37:30 +00004796/// discard all CompoundStmts intervening between two constructs
4797static const Stmt *ignoreCompoundStmts(const Stmt *Body) {
4798 while (auto *CS = dyn_cast_or_null<CompoundStmt>(Body))
4799 Body = CS->body_front();
4800
4801 return Body;
4802}
4803
Samuel Antaob68e2db2016-03-03 16:20:23 +00004804/// \brief Emit the num_teams clause of an enclosed teams directive at the
4805/// target region scope. If there is no teams directive associated with the
4806/// target directive, or if there is no num_teams clause associated with the
4807/// enclosed teams directive, return nullptr.
4808static llvm::Value *
4809emitNumTeamsClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4810 CodeGenFunction &CGF,
4811 const OMPExecutableDirective &D) {
4812
4813 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4814 "teams directive expected to be "
4815 "emitted only for the host!");
4816
4817 // FIXME: For the moment we do not support combined directives with target and
4818 // teams, so we do not expect to get any num_teams clause in the provided
4819 // directive. Once we support that, this assertion can be replaced by the
4820 // actual emission of the clause expression.
4821 assert(D.getSingleClause<OMPNumTeamsClause>() == nullptr &&
4822 "Not expecting clause in directive.");
4823
4824 // If the current target region has a teams region enclosed, we need to get
4825 // the number of teams to pass to the runtime function call. This is done
4826 // by generating the expression in a inlined region. This is required because
4827 // the expression is captured in the enclosing target environment when the
4828 // teams directive is not combined with target.
4829
4830 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4831
4832 // FIXME: Accommodate other combined directives with teams when they become
4833 // available.
Carlo Bertolli6eee9062016-04-29 01:37:30 +00004834 if (auto *TeamsDir = dyn_cast_or_null<OMPTeamsDirective>(
4835 ignoreCompoundStmts(CS.getCapturedStmt()))) {
Samuel Antaob68e2db2016-03-03 16:20:23 +00004836 if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) {
4837 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4838 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4839 llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams());
4840 return CGF.Builder.CreateIntCast(NumTeams, CGF.Int32Ty,
4841 /*IsSigned=*/true);
4842 }
4843
4844 // If we have an enclosed teams directive but no num_teams clause we use
4845 // the default value 0.
4846 return CGF.Builder.getInt32(0);
4847 }
4848
4849 // No teams associated with the directive.
4850 return nullptr;
4851}
4852
4853/// \brief Emit the thread_limit clause of an enclosed teams directive at the
4854/// target region scope. If there is no teams directive associated with the
4855/// target directive, or if there is no thread_limit clause associated with the
4856/// enclosed teams directive, return nullptr.
4857static llvm::Value *
4858emitThreadLimitClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4859 CodeGenFunction &CGF,
4860 const OMPExecutableDirective &D) {
4861
4862 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4863 "teams directive expected to be "
4864 "emitted only for the host!");
4865
4866 // FIXME: For the moment we do not support combined directives with target and
4867 // teams, so we do not expect to get any thread_limit clause in the provided
4868 // directive. Once we support that, this assertion can be replaced by the
4869 // actual emission of the clause expression.
4870 assert(D.getSingleClause<OMPThreadLimitClause>() == nullptr &&
4871 "Not expecting clause in directive.");
4872
4873 // If the current target region has a teams region enclosed, we need to get
4874 // the thread limit to pass to the runtime function call. This is done
4875 // by generating the expression in a inlined region. This is required because
4876 // the expression is captured in the enclosing target environment when the
4877 // teams directive is not combined with target.
4878
4879 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4880
4881 // FIXME: Accommodate other combined directives with teams when they become
4882 // available.
Carlo Bertolli6eee9062016-04-29 01:37:30 +00004883 if (auto *TeamsDir = dyn_cast_or_null<OMPTeamsDirective>(
4884 ignoreCompoundStmts(CS.getCapturedStmt()))) {
Samuel Antaob68e2db2016-03-03 16:20:23 +00004885 if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) {
4886 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4887 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4888 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit());
4889 return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty,
4890 /*IsSigned=*/true);
4891 }
4892
4893 // If we have an enclosed teams directive but no thread_limit clause we use
4894 // the default value 0.
4895 return CGF.Builder.getInt32(0);
4896 }
4897
4898 // No teams associated with the directive.
4899 return nullptr;
4900}
4901
Samuel Antao86ace552016-04-27 22:40:57 +00004902namespace {
4903// \brief Utility to handle information from clauses associated with a given
4904// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
4905// It provides a convenient interface to obtain the information and generate
4906// code for that information.
4907class MappableExprsHandler {
4908public:
4909 /// \brief Values for bit flags used to specify the mapping type for
4910 /// offloading.
4911 enum OpenMPOffloadMappingFlags {
Samuel Antao86ace552016-04-27 22:40:57 +00004912 /// \brief Allocate memory on the device and move data from host to device.
4913 OMP_MAP_TO = 0x01,
4914 /// \brief Allocate memory on the device and move data from device to host.
4915 OMP_MAP_FROM = 0x02,
4916 /// \brief Always perform the requested mapping action on the element, even
4917 /// if it was already mapped before.
4918 OMP_MAP_ALWAYS = 0x04,
Samuel Antao86ace552016-04-27 22:40:57 +00004919 /// \brief Delete the element from the device environment, ignoring the
4920 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00004921 OMP_MAP_DELETE = 0x08,
4922 /// \brief The element being mapped is a pointer, therefore the pointee
4923 /// should be mapped as well.
4924 OMP_MAP_IS_PTR = 0x10,
4925 /// \brief This flags signals that an argument is the first one relating to
4926 /// a map/private clause expression. For some cases a single
4927 /// map/privatization results in multiple arguments passed to the runtime
4928 /// library.
4929 OMP_MAP_FIRST_REF = 0x20,
Samuel Antaod486f842016-05-26 16:53:38 +00004930 /// \brief This flag signals that the reference being passed is a pointer to
4931 /// private data.
4932 OMP_MAP_PRIVATE_PTR = 0x80,
Samuel Antao86ace552016-04-27 22:40:57 +00004933 /// \brief Pass the element to the device by value.
Samuel Antao6782e942016-05-26 16:48:10 +00004934 OMP_MAP_PRIVATE_VAL = 0x100,
Samuel Antao86ace552016-04-27 22:40:57 +00004935 };
4936
4937 typedef SmallVector<llvm::Value *, 16> MapValuesArrayTy;
4938 typedef SmallVector<unsigned, 16> MapFlagsArrayTy;
4939
4940private:
4941 /// \brief Directive from where the map clauses were extracted.
4942 const OMPExecutableDirective &Directive;
4943
4944 /// \brief Function the directive is being generated for.
4945 CodeGenFunction &CGF;
4946
Samuel Antaod486f842016-05-26 16:53:38 +00004947 /// \brief Set of all first private variables in the current directive.
4948 llvm::SmallPtrSet<const VarDecl *, 8> FirstPrivateDecls;
4949
Samuel Antao86ace552016-04-27 22:40:57 +00004950 llvm::Value *getExprTypeSize(const Expr *E) const {
4951 auto ExprTy = E->getType().getCanonicalType();
4952
4953 // Reference types are ignored for mapping purposes.
4954 if (auto *RefTy = ExprTy->getAs<ReferenceType>())
4955 ExprTy = RefTy->getPointeeType().getCanonicalType();
4956
4957 // Given that an array section is considered a built-in type, we need to
4958 // do the calculation based on the length of the section instead of relying
4959 // on CGF.getTypeSize(E->getType()).
4960 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
4961 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
4962 OAE->getBase()->IgnoreParenImpCasts())
4963 .getCanonicalType();
4964
4965 // If there is no length associated with the expression, that means we
4966 // are using the whole length of the base.
4967 if (!OAE->getLength() && OAE->getColonLoc().isValid())
4968 return CGF.getTypeSize(BaseTy);
4969
4970 llvm::Value *ElemSize;
4971 if (auto *PTy = BaseTy->getAs<PointerType>())
4972 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
4973 else {
4974 auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
4975 assert(ATy && "Expecting array type if not a pointer type.");
4976 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
4977 }
4978
4979 // If we don't have a length at this point, that is because we have an
4980 // array section with a single element.
4981 if (!OAE->getLength())
4982 return ElemSize;
4983
4984 auto *LengthVal = CGF.EmitScalarExpr(OAE->getLength());
4985 LengthVal =
4986 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false);
4987 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
4988 }
4989 return CGF.getTypeSize(ExprTy);
4990 }
4991
4992 /// \brief Return the corresponding bits for a given map clause modifier. Add
4993 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00004994 /// map as the first one of a series of maps that relate to the same map
4995 /// expression.
Samuel Antao86ace552016-04-27 22:40:57 +00004996 unsigned getMapTypeBits(OpenMPMapClauseKind MapType,
4997 OpenMPMapClauseKind MapTypeModifier, bool AddPtrFlag,
Samuel Antao6782e942016-05-26 16:48:10 +00004998 bool AddIsFirstFlag) const {
Samuel Antao86ace552016-04-27 22:40:57 +00004999 unsigned Bits = 0u;
5000 switch (MapType) {
5001 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00005002 case OMPC_MAP_release:
5003 // alloc and release is the default behavior in the runtime library, i.e.
5004 // if we don't pass any bits alloc/release that is what the runtime is
5005 // going to do. Therefore, we don't need to signal anything for these two
5006 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00005007 break;
5008 case OMPC_MAP_to:
5009 Bits = OMP_MAP_TO;
5010 break;
5011 case OMPC_MAP_from:
5012 Bits = OMP_MAP_FROM;
5013 break;
5014 case OMPC_MAP_tofrom:
5015 Bits = OMP_MAP_TO | OMP_MAP_FROM;
5016 break;
5017 case OMPC_MAP_delete:
5018 Bits = OMP_MAP_DELETE;
5019 break;
Samuel Antao86ace552016-04-27 22:40:57 +00005020 default:
5021 llvm_unreachable("Unexpected map type!");
5022 break;
5023 }
5024 if (AddPtrFlag)
Samuel Antao6782e942016-05-26 16:48:10 +00005025 Bits |= OMP_MAP_IS_PTR;
5026 if (AddIsFirstFlag)
5027 Bits |= OMP_MAP_FIRST_REF;
Samuel Antao86ace552016-04-27 22:40:57 +00005028 if (MapTypeModifier == OMPC_MAP_always)
5029 Bits |= OMP_MAP_ALWAYS;
5030 return Bits;
5031 }
5032
5033 /// \brief Return true if the provided expression is a final array section. A
5034 /// final array section, is one whose length can't be proved to be one.
5035 bool isFinalArraySectionExpression(const Expr *E) const {
5036 auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
5037
5038 // It is not an array section and therefore not a unity-size one.
5039 if (!OASE)
5040 return false;
5041
5042 // An array section with no colon always refer to a single element.
5043 if (OASE->getColonLoc().isInvalid())
5044 return false;
5045
5046 auto *Length = OASE->getLength();
5047
5048 // If we don't have a length we have to check if the array has size 1
5049 // for this dimension. Also, we should always expect a length if the
5050 // base type is pointer.
5051 if (!Length) {
5052 auto BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
5053 OASE->getBase()->IgnoreParenImpCasts())
5054 .getCanonicalType();
5055 if (auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
5056 return ATy->getSize().getSExtValue() != 1;
5057 // If we don't have a constant dimension length, we have to consider
5058 // the current section as having any size, so it is not necessarily
5059 // unitary. If it happen to be unity size, that's user fault.
5060 return true;
5061 }
5062
5063 // Check if the length evaluates to 1.
5064 llvm::APSInt ConstLength;
5065 if (!Length->EvaluateAsInt(ConstLength, CGF.getContext()))
5066 return true; // Can have more that size 1.
5067
5068 return ConstLength.getSExtValue() != 1;
5069 }
5070
5071 /// \brief Generate the base pointers, section pointers, sizes and map type
5072 /// bits for the provided map type, map modifier, and expression components.
5073 /// \a IsFirstComponent should be set to true if the provided set of
5074 /// components is the first associated with a capture.
5075 void generateInfoForComponentList(
5076 OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier,
5077 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
5078 MapValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
5079 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
5080 bool IsFirstComponentList) const {
5081
5082 // The following summarizes what has to be generated for each map and the
5083 // types bellow. The generated information is expressed in this order:
5084 // base pointer, section pointer, size, flags
5085 // (to add to the ones that come from the map type and modifier).
5086 //
5087 // double d;
5088 // int i[100];
5089 // float *p;
5090 //
5091 // struct S1 {
5092 // int i;
5093 // float f[50];
5094 // }
5095 // struct S2 {
5096 // int i;
5097 // float f[50];
5098 // S1 s;
5099 // double *p;
5100 // struct S2 *ps;
5101 // }
5102 // S2 s;
5103 // S2 *ps;
5104 //
5105 // map(d)
5106 // &d, &d, sizeof(double), noflags
5107 //
5108 // map(i)
5109 // &i, &i, 100*sizeof(int), noflags
5110 //
5111 // map(i[1:23])
5112 // &i(=&i[0]), &i[1], 23*sizeof(int), noflags
5113 //
5114 // map(p)
5115 // &p, &p, sizeof(float*), noflags
5116 //
5117 // map(p[1:24])
5118 // p, &p[1], 24*sizeof(float), noflags
5119 //
5120 // map(s)
5121 // &s, &s, sizeof(S2), noflags
5122 //
5123 // map(s.i)
5124 // &s, &(s.i), sizeof(int), noflags
5125 //
5126 // map(s.s.f)
5127 // &s, &(s.i.f), 50*sizeof(int), noflags
5128 //
5129 // map(s.p)
5130 // &s, &(s.p), sizeof(double*), noflags
5131 //
5132 // map(s.p[:22], s.a s.b)
5133 // &s, &(s.p), sizeof(double*), noflags
5134 // &(s.p), &(s.p[0]), 22*sizeof(double), ptr_flag + extra_flag
5135 //
5136 // map(s.ps)
5137 // &s, &(s.ps), sizeof(S2*), noflags
5138 //
5139 // map(s.ps->s.i)
5140 // &s, &(s.ps), sizeof(S2*), noflags
5141 // &(s.ps), &(s.ps->s.i), sizeof(int), ptr_flag + extra_flag
5142 //
5143 // map(s.ps->ps)
5144 // &s, &(s.ps), sizeof(S2*), noflags
5145 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag
5146 //
5147 // map(s.ps->ps->ps)
5148 // &s, &(s.ps), sizeof(S2*), noflags
5149 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag
5150 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
5151 //
5152 // map(s.ps->ps->s.f[:22])
5153 // &s, &(s.ps), sizeof(S2*), noflags
5154 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag
5155 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), ptr_flag + extra_flag
5156 //
5157 // map(ps)
5158 // &ps, &ps, sizeof(S2*), noflags
5159 //
5160 // map(ps->i)
5161 // ps, &(ps->i), sizeof(int), noflags
5162 //
5163 // map(ps->s.f)
5164 // ps, &(ps->s.f[0]), 50*sizeof(float), noflags
5165 //
5166 // map(ps->p)
5167 // ps, &(ps->p), sizeof(double*), noflags
5168 //
5169 // map(ps->p[:22])
5170 // ps, &(ps->p), sizeof(double*), noflags
5171 // &(ps->p), &(ps->p[0]), 22*sizeof(double), ptr_flag + extra_flag
5172 //
5173 // map(ps->ps)
5174 // ps, &(ps->ps), sizeof(S2*), noflags
5175 //
5176 // map(ps->ps->s.i)
5177 // ps, &(ps->ps), sizeof(S2*), noflags
5178 // &(ps->ps), &(ps->ps->s.i), sizeof(int), ptr_flag + extra_flag
5179 //
5180 // map(ps->ps->ps)
5181 // ps, &(ps->ps), sizeof(S2*), noflags
5182 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
5183 //
5184 // map(ps->ps->ps->ps)
5185 // ps, &(ps->ps), sizeof(S2*), noflags
5186 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
5187 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
5188 //
5189 // map(ps->ps->ps->s.f[:22])
5190 // ps, &(ps->ps), sizeof(S2*), noflags
5191 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
5192 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), ptr_flag +
5193 // extra_flag
5194
5195 // Track if the map information being generated is the first for a capture.
5196 bool IsCaptureFirstInfo = IsFirstComponentList;
5197
5198 // Scan the components from the base to the complete expression.
5199 auto CI = Components.rbegin();
5200 auto CE = Components.rend();
5201 auto I = CI;
5202
5203 // Track if the map information being generated is the first for a list of
5204 // components.
5205 bool IsExpressionFirstInfo = true;
5206 llvm::Value *BP = nullptr;
5207
5208 if (auto *ME = dyn_cast<MemberExpr>(I->getAssociatedExpression())) {
5209 // The base is the 'this' pointer. The content of the pointer is going
5210 // to be the base of the field being mapped.
5211 BP = CGF.EmitScalarExpr(ME->getBase());
5212 } else {
5213 // The base is the reference to the variable.
5214 // BP = &Var.
5215 BP = CGF.EmitLValue(cast<DeclRefExpr>(I->getAssociatedExpression()))
5216 .getPointer();
5217
5218 // If the variable is a pointer and is being dereferenced (i.e. is not
5219 // the last component), the base has to be the pointer itself, not his
5220 // reference.
5221 if (I->getAssociatedDeclaration()->getType()->isAnyPointerType() &&
5222 std::next(I) != CE) {
5223 auto PtrAddr = CGF.MakeNaturalAlignAddrLValue(
5224 BP, I->getAssociatedDeclaration()->getType());
5225 BP = CGF.EmitLoadOfPointerLValue(PtrAddr.getAddress(),
5226 I->getAssociatedDeclaration()
5227 ->getType()
5228 ->getAs<PointerType>())
5229 .getPointer();
5230
5231 // We do not need to generate individual map information for the
5232 // pointer, it can be associated with the combined storage.
5233 ++I;
5234 }
5235 }
5236
5237 for (; I != CE; ++I) {
5238 auto Next = std::next(I);
5239
5240 // We need to generate the addresses and sizes if this is the last
5241 // component, if the component is a pointer or if it is an array section
5242 // whose length can't be proved to be one. If this is a pointer, it
5243 // becomes the base address for the following components.
5244
5245 // A final array section, is one whose length can't be proved to be one.
5246 bool IsFinalArraySection =
5247 isFinalArraySectionExpression(I->getAssociatedExpression());
5248
5249 // Get information on whether the element is a pointer. Have to do a
5250 // special treatment for array sections given that they are built-in
5251 // types.
5252 const auto *OASE =
5253 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
5254 bool IsPointer =
5255 (OASE &&
5256 OMPArraySectionExpr::getBaseOriginalType(OASE)
5257 .getCanonicalType()
5258 ->isAnyPointerType()) ||
5259 I->getAssociatedExpression()->getType()->isAnyPointerType();
5260
5261 if (Next == CE || IsPointer || IsFinalArraySection) {
5262
5263 // If this is not the last component, we expect the pointer to be
5264 // associated with an array expression or member expression.
5265 assert((Next == CE ||
5266 isa<MemberExpr>(Next->getAssociatedExpression()) ||
5267 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
5268 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
5269 "Unexpected expression");
5270
5271 // Save the base we are currently using.
5272 BasePointers.push_back(BP);
5273
5274 auto *LB = CGF.EmitLValue(I->getAssociatedExpression()).getPointer();
5275 auto *Size = getExprTypeSize(I->getAssociatedExpression());
5276
5277 Pointers.push_back(LB);
5278 Sizes.push_back(Size);
Samuel Antao6782e942016-05-26 16:48:10 +00005279 // We need to add a pointer flag for each map that comes from the
5280 // same expression except for the first one. We also need to signal
5281 // this map is the first one that relates with the current capture
5282 // (there is a set of entries for each capture).
Samuel Antao86ace552016-04-27 22:40:57 +00005283 Types.push_back(getMapTypeBits(MapType, MapTypeModifier,
5284 !IsExpressionFirstInfo,
Samuel Antao6782e942016-05-26 16:48:10 +00005285 IsCaptureFirstInfo));
Samuel Antao86ace552016-04-27 22:40:57 +00005286
5287 // If we have a final array section, we are done with this expression.
5288 if (IsFinalArraySection)
5289 break;
5290
5291 // The pointer becomes the base for the next element.
5292 if (Next != CE)
5293 BP = LB;
5294
5295 IsExpressionFirstInfo = false;
5296 IsCaptureFirstInfo = false;
5297 continue;
5298 }
5299 }
5300 }
5301
Samuel Antaod486f842016-05-26 16:53:38 +00005302 /// \brief Return the adjusted map modifiers if the declaration a capture
5303 /// refers to appears in a first-private clause. This is expected to be used
5304 /// only with directives that start with 'target'.
5305 unsigned adjustMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap,
5306 unsigned CurrentModifiers) {
5307 assert(Cap.capturesVariable() && "Expected capture by reference only!");
5308
5309 // A first private variable captured by reference will use only the
5310 // 'private ptr' and 'map to' flag. Return the right flags if the captured
5311 // declaration is known as first-private in this handler.
5312 if (FirstPrivateDecls.count(Cap.getCapturedVar()))
5313 return MappableExprsHandler::OMP_MAP_PRIVATE_PTR |
5314 MappableExprsHandler::OMP_MAP_TO;
5315
5316 // We didn't modify anything.
5317 return CurrentModifiers;
5318 }
5319
Samuel Antao86ace552016-04-27 22:40:57 +00005320public:
5321 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Samuel Antaod486f842016-05-26 16:53:38 +00005322 : Directive(Dir), CGF(CGF) {
5323 // Extract firstprivate clause information.
5324 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
5325 for (const auto *D : C->varlists())
5326 FirstPrivateDecls.insert(
5327 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
5328 }
Samuel Antao86ace552016-04-27 22:40:57 +00005329
5330 /// \brief Generate all the base pointers, section pointers, sizes and map
5331 /// types for the extracted mappable expressions.
5332 void generateAllInfo(MapValuesArrayTy &BasePointers,
5333 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
5334 MapFlagsArrayTy &Types) const {
5335 BasePointers.clear();
5336 Pointers.clear();
5337 Sizes.clear();
5338 Types.clear();
5339
5340 struct MapInfo {
5341 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
5342 OpenMPMapClauseKind MapType;
5343 OpenMPMapClauseKind MapTypeModifier;
5344 };
5345
5346 // We have to process the component lists that relate with the same
5347 // declaration in a single chunk so that we can generate the map flags
5348 // correctly. Therefore, we organize all lists in a map.
5349 llvm::DenseMap<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
5350 for (auto *C : Directive.getClausesOfKind<OMPMapClause>())
5351 for (auto L : C->component_lists()) {
5352 const ValueDecl *VD =
5353 L.first ? cast<ValueDecl>(L.first->getCanonicalDecl()) : nullptr;
5354 Info[VD].push_back(
5355 {L.second, C->getMapType(), C->getMapTypeModifier()});
5356 }
5357
5358 for (auto &M : Info) {
5359 // We need to know when we generate information for the first component
5360 // associated with a capture, because the mapping flags depend on it.
5361 bool IsFirstComponentList = true;
5362 for (MapInfo &L : M.second) {
5363 assert(!L.Components.empty() &&
5364 "Not expecting declaration with no component lists.");
5365 generateInfoForComponentList(L.MapType, L.MapTypeModifier, L.Components,
5366 BasePointers, Pointers, Sizes, Types,
5367 IsFirstComponentList);
5368 IsFirstComponentList = false;
5369 }
5370 }
5371 }
5372
5373 /// \brief Generate the base pointers, section pointers, sizes and map types
5374 /// associated to a given capture.
5375 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
5376 MapValuesArrayTy &BasePointers,
5377 MapValuesArrayTy &Pointers,
5378 MapValuesArrayTy &Sizes,
5379 MapFlagsArrayTy &Types) const {
5380 assert(!Cap->capturesVariableArrayType() &&
5381 "Not expecting to generate map info for a variable array type!");
5382
5383 BasePointers.clear();
5384 Pointers.clear();
5385 Sizes.clear();
5386 Types.clear();
5387
5388 const ValueDecl *VD =
5389 Cap->capturesThis()
5390 ? nullptr
5391 : cast<ValueDecl>(Cap->getCapturedVar()->getCanonicalDecl());
5392
5393 // We need to know when we generating information for the first component
5394 // associated with a capture, because the mapping flags depend on it.
5395 bool IsFirstComponentList = true;
5396 for (auto *C : Directive.getClausesOfKind<OMPMapClause>())
5397 for (auto L : C->decl_component_lists(VD)) {
5398 assert(L.first == VD &&
5399 "We got information for the wrong declaration??");
5400 assert(!L.second.empty() &&
5401 "Not expecting declaration with no component lists.");
5402 generateInfoForComponentList(C->getMapType(), C->getMapTypeModifier(),
5403 L.second, BasePointers, Pointers, Sizes,
5404 Types, IsFirstComponentList);
5405 IsFirstComponentList = false;
5406 }
5407
5408 return;
5409 }
Samuel Antaod486f842016-05-26 16:53:38 +00005410
5411 /// \brief Generate the default map information for a given capture \a CI,
5412 /// record field declaration \a RI and captured value \a CV.
5413 void generateDefaultMapInfo(
5414 const CapturedStmt::Capture &CI, const FieldDecl &RI, llvm::Value *CV,
5415 MappableExprsHandler::MapValuesArrayTy &CurBasePointers,
5416 MappableExprsHandler::MapValuesArrayTy &CurPointers,
5417 MappableExprsHandler::MapValuesArrayTy &CurSizes,
5418 MappableExprsHandler::MapFlagsArrayTy &CurMapTypes) {
5419 auto &Ctx = CGF.getContext();
5420
5421 // Do the default mapping.
5422 if (CI.capturesThis()) {
5423 CurBasePointers.push_back(CV);
5424 CurPointers.push_back(CV);
5425 const PointerType *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
5426 CurSizes.push_back(CGF.getTypeSize(PtrTy->getPointeeType()));
5427 // Default map type.
5428 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_TO |
5429 MappableExprsHandler::OMP_MAP_FROM);
5430 } else if (CI.capturesVariableByCopy()) {
5431 if (!RI.getType()->isAnyPointerType()) {
5432 // If the field is not a pointer, we need to save the actual value
5433 // and load it as a void pointer.
5434 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_PRIVATE_VAL);
5435 auto DstAddr = CGF.CreateMemTemp(Ctx.getUIntPtrType(),
5436 Twine(CI.getCapturedVar()->getName()) +
5437 ".casted");
5438 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
5439
5440 auto *SrcAddrVal = CGF.EmitScalarConversion(
5441 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
5442 Ctx.getPointerType(RI.getType()), SourceLocation());
5443 LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI.getType());
5444
5445 // Store the value using the source type pointer.
5446 CGF.EmitStoreThroughLValue(RValue::get(CV), SrcLV);
5447
5448 // Load the value using the destination type pointer.
5449 CurBasePointers.push_back(
5450 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal());
5451 CurPointers.push_back(CurBasePointers.back());
5452
5453 // Get the size of the type to be used in the map.
5454 CurSizes.push_back(CGF.getTypeSize(RI.getType()));
5455 } else {
5456 // Pointers are implicitly mapped with a zero size and no flags
5457 // (other than first map that is added for all implicit maps).
5458 CurMapTypes.push_back(0u);
5459 CurBasePointers.push_back(CV);
5460 CurPointers.push_back(CV);
5461 CurSizes.push_back(llvm::Constant::getNullValue(CGF.SizeTy));
5462 }
5463 } else {
5464 assert(CI.capturesVariable() && "Expected captured reference.");
5465 CurBasePointers.push_back(CV);
5466 CurPointers.push_back(CV);
5467
5468 const ReferenceType *PtrTy =
5469 cast<ReferenceType>(RI.getType().getTypePtr());
5470 QualType ElementType = PtrTy->getPointeeType();
5471 CurSizes.push_back(CGF.getTypeSize(ElementType));
5472 // The default map type for a scalar/complex type is 'to' because by
5473 // default the value doesn't have to be retrieved. For an aggregate
5474 // type, the default is 'tofrom'.
5475 CurMapTypes.push_back(ElementType->isAggregateType()
5476 ? (MappableExprsHandler::OMP_MAP_TO |
5477 MappableExprsHandler::OMP_MAP_FROM)
5478 : MappableExprsHandler::OMP_MAP_TO);
5479
5480 // If we have a capture by reference we may need to add the private
5481 // pointer flag if the base declaration shows in some first-private
5482 // clause.
5483 CurMapTypes.back() =
5484 adjustMapModifiersForPrivateClauses(CI, CurMapTypes.back());
5485 }
5486 // Every default map produces a single argument, so, it is always the
5487 // first one.
5488 CurMapTypes.back() |= MappableExprsHandler::OMP_MAP_FIRST_REF;
5489 }
Samuel Antao86ace552016-04-27 22:40:57 +00005490};
Samuel Antaodf158d52016-04-27 22:58:19 +00005491
5492enum OpenMPOffloadingReservedDeviceIDs {
5493 /// \brief Device ID if the device was not defined, runtime should get it
5494 /// from environment variables in the spec.
5495 OMP_DEVICEID_UNDEF = -1,
5496};
5497} // anonymous namespace
5498
5499/// \brief Emit the arrays used to pass the captures and map information to the
5500/// offloading runtime library. If there is no map or capture information,
5501/// return nullptr by reference.
5502static void
5503emitOffloadingArrays(CodeGenFunction &CGF, llvm::Value *&BasePointersArray,
5504 llvm::Value *&PointersArray, llvm::Value *&SizesArray,
5505 llvm::Value *&MapTypesArray,
5506 MappableExprsHandler::MapValuesArrayTy &BasePointers,
5507 MappableExprsHandler::MapValuesArrayTy &Pointers,
5508 MappableExprsHandler::MapValuesArrayTy &Sizes,
5509 MappableExprsHandler::MapFlagsArrayTy &MapTypes) {
5510 auto &CGM = CGF.CGM;
5511 auto &Ctx = CGF.getContext();
5512
5513 BasePointersArray = PointersArray = SizesArray = MapTypesArray = nullptr;
5514
5515 if (unsigned PointerNumVal = BasePointers.size()) {
5516 // Detect if we have any capture size requiring runtime evaluation of the
5517 // size so that a constant array could be eventually used.
5518 bool hasRuntimeEvaluationCaptureSize = false;
5519 for (auto *S : Sizes)
5520 if (!isa<llvm::Constant>(S)) {
5521 hasRuntimeEvaluationCaptureSize = true;
5522 break;
5523 }
5524
5525 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
5526 QualType PointerArrayType =
5527 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
5528 /*IndexTypeQuals=*/0);
5529
5530 BasePointersArray =
5531 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
5532 PointersArray =
5533 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
5534
5535 // If we don't have any VLA types or other types that require runtime
5536 // evaluation, we can use a constant array for the map sizes, otherwise we
5537 // need to fill up the arrays as we do for the pointers.
5538 if (hasRuntimeEvaluationCaptureSize) {
5539 QualType SizeArrayType = Ctx.getConstantArrayType(
5540 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
5541 /*IndexTypeQuals=*/0);
5542 SizesArray =
5543 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
5544 } else {
5545 // We expect all the sizes to be constant, so we collect them to create
5546 // a constant array.
5547 SmallVector<llvm::Constant *, 16> ConstSizes;
5548 for (auto S : Sizes)
5549 ConstSizes.push_back(cast<llvm::Constant>(S));
5550
5551 auto *SizesArrayInit = llvm::ConstantArray::get(
5552 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
5553 auto *SizesArrayGbl = new llvm::GlobalVariable(
5554 CGM.getModule(), SizesArrayInit->getType(),
5555 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
5556 SizesArrayInit, ".offload_sizes");
5557 SizesArrayGbl->setUnnamedAddr(true);
5558 SizesArray = SizesArrayGbl;
5559 }
5560
5561 // The map types are always constant so we don't need to generate code to
5562 // fill arrays. Instead, we create an array constant.
5563 llvm::Constant *MapTypesArrayInit =
5564 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
5565 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
5566 CGM.getModule(), MapTypesArrayInit->getType(),
5567 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
5568 MapTypesArrayInit, ".offload_maptypes");
5569 MapTypesArrayGbl->setUnnamedAddr(true);
5570 MapTypesArray = MapTypesArrayGbl;
5571
5572 for (unsigned i = 0; i < PointerNumVal; ++i) {
5573 llvm::Value *BPVal = BasePointers[i];
5574 if (BPVal->getType()->isPointerTy())
5575 BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy);
5576 else {
5577 assert(BPVal->getType()->isIntegerTy() &&
5578 "If not a pointer, the value type must be an integer.");
5579 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy);
5580 }
5581 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
5582 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), BasePointersArray,
5583 0, i);
5584 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
5585 CGF.Builder.CreateStore(BPVal, BPAddr);
5586
5587 llvm::Value *PVal = Pointers[i];
5588 if (PVal->getType()->isPointerTy())
5589 PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy);
5590 else {
5591 assert(PVal->getType()->isIntegerTy() &&
5592 "If not a pointer, the value type must be an integer.");
5593 PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy);
5594 }
5595 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
5596 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray, 0,
5597 i);
5598 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
5599 CGF.Builder.CreateStore(PVal, PAddr);
5600
5601 if (hasRuntimeEvaluationCaptureSize) {
5602 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
5603 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
5604 /*Idx0=*/0,
5605 /*Idx1=*/i);
5606 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
5607 CGF.Builder.CreateStore(
5608 CGF.Builder.CreateIntCast(Sizes[i], CGM.SizeTy, /*isSigned=*/true),
5609 SAddr);
5610 }
5611 }
5612 }
5613}
5614/// \brief Emit the arguments to be passed to the runtime library based on the
5615/// arrays of pointers, sizes and map types.
5616static void emitOffloadingArraysArgument(
5617 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
5618 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
5619 llvm::Value *&MapTypesArrayArg, llvm::Value *BasePointersArray,
5620 llvm::Value *PointersArray, llvm::Value *SizesArray,
5621 llvm::Value *MapTypesArray, unsigned NumElems) {
5622 auto &CGM = CGF.CGM;
5623 if (NumElems) {
5624 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
5625 llvm::ArrayType::get(CGM.VoidPtrTy, NumElems), BasePointersArray,
5626 /*Idx0=*/0, /*Idx1=*/0);
5627 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
5628 llvm::ArrayType::get(CGM.VoidPtrTy, NumElems), PointersArray,
5629 /*Idx0=*/0,
5630 /*Idx1=*/0);
5631 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
5632 llvm::ArrayType::get(CGM.SizeTy, NumElems), SizesArray,
5633 /*Idx0=*/0, /*Idx1=*/0);
5634 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
5635 llvm::ArrayType::get(CGM.Int32Ty, NumElems), MapTypesArray,
5636 /*Idx0=*/0,
5637 /*Idx1=*/0);
5638 } else {
5639 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
5640 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
5641 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
5642 MapTypesArrayArg =
5643 llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo());
5644 }
Samuel Antao86ace552016-04-27 22:40:57 +00005645}
5646
Samuel Antaobed3c462015-10-02 16:14:20 +00005647void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
5648 const OMPExecutableDirective &D,
5649 llvm::Value *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00005650 llvm::Value *OutlinedFnID,
Samuel Antaobed3c462015-10-02 16:14:20 +00005651 const Expr *IfCond, const Expr *Device,
5652 ArrayRef<llvm::Value *> CapturedVars) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005653 if (!CGF.HaveInsertPoint())
5654 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00005655
Samuel Antaoee8fb302016-01-06 13:42:12 +00005656 assert(OutlinedFn && "Invalid outlined function!");
5657
Samuel Antao4af1b7b2015-12-02 17:44:43 +00005658 auto &Ctx = CGF.getContext();
5659
Samuel Antao86ace552016-04-27 22:40:57 +00005660 // Fill up the arrays with all the captured variables.
5661 MappableExprsHandler::MapValuesArrayTy KernelArgs;
5662 MappableExprsHandler::MapValuesArrayTy BasePointers;
5663 MappableExprsHandler::MapValuesArrayTy Pointers;
5664 MappableExprsHandler::MapValuesArrayTy Sizes;
5665 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobed3c462015-10-02 16:14:20 +00005666
Samuel Antao86ace552016-04-27 22:40:57 +00005667 MappableExprsHandler::MapValuesArrayTy CurBasePointers;
5668 MappableExprsHandler::MapValuesArrayTy CurPointers;
5669 MappableExprsHandler::MapValuesArrayTy CurSizes;
5670 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
5671
Samuel Antaod486f842016-05-26 16:53:38 +00005672 // Get mappable expression information.
5673 MappableExprsHandler MEHandler(D, CGF);
Samuel Antaobed3c462015-10-02 16:14:20 +00005674
5675 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
5676 auto RI = CS.getCapturedRecordDecl()->field_begin();
Samuel Antaobed3c462015-10-02 16:14:20 +00005677 auto CV = CapturedVars.begin();
5678 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
5679 CE = CS.capture_end();
5680 CI != CE; ++CI, ++RI, ++CV) {
5681 StringRef Name;
5682 QualType Ty;
Samuel Antaobed3c462015-10-02 16:14:20 +00005683
Samuel Antao86ace552016-04-27 22:40:57 +00005684 CurBasePointers.clear();
5685 CurPointers.clear();
5686 CurSizes.clear();
5687 CurMapTypes.clear();
5688
5689 // VLA sizes are passed to the outlined region by copy and do not have map
5690 // information associated.
Samuel Antaobed3c462015-10-02 16:14:20 +00005691 if (CI->capturesVariableArrayType()) {
Samuel Antao86ace552016-04-27 22:40:57 +00005692 CurBasePointers.push_back(*CV);
5693 CurPointers.push_back(*CV);
5694 CurSizes.push_back(CGF.getTypeSize(RI->getType()));
Samuel Antao4af1b7b2015-12-02 17:44:43 +00005695 // Copy to the device as an argument. No need to retrieve it.
Samuel Antao6782e942016-05-26 16:48:10 +00005696 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_PRIVATE_VAL |
5697 MappableExprsHandler::OMP_MAP_FIRST_REF);
Samuel Antaobed3c462015-10-02 16:14:20 +00005698 } else {
Samuel Antao86ace552016-04-27 22:40:57 +00005699 // If we have any information in the map clause, we use it, otherwise we
5700 // just do a default mapping.
Samuel Antaod486f842016-05-26 16:53:38 +00005701 MEHandler.generateInfoForCapture(CI, CurBasePointers, CurPointers,
Samuel Antao86ace552016-04-27 22:40:57 +00005702 CurSizes, CurMapTypes);
Samuel Antaod486f842016-05-26 16:53:38 +00005703 if (CurBasePointers.empty())
5704 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
5705 CurPointers, CurSizes, CurMapTypes);
Samuel Antaobed3c462015-10-02 16:14:20 +00005706 }
Samuel Antao86ace552016-04-27 22:40:57 +00005707 // We expect to have at least an element of information for this capture.
5708 assert(!CurBasePointers.empty() && "Non-existing map pointer for capture!");
5709 assert(CurBasePointers.size() == CurPointers.size() &&
5710 CurBasePointers.size() == CurSizes.size() &&
5711 CurBasePointers.size() == CurMapTypes.size() &&
5712 "Inconsistent map information sizes!");
Samuel Antaobed3c462015-10-02 16:14:20 +00005713
Samuel Antao86ace552016-04-27 22:40:57 +00005714 // The kernel args are always the first elements of the base pointers
5715 // associated with a capture.
5716 KernelArgs.push_back(CurBasePointers.front());
5717 // We need to append the results of this capture to what we already have.
5718 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
5719 Pointers.append(CurPointers.begin(), CurPointers.end());
5720 Sizes.append(CurSizes.begin(), CurSizes.end());
5721 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
Samuel Antaobed3c462015-10-02 16:14:20 +00005722 }
5723
5724 // Keep track on whether the host function has to be executed.
5725 auto OffloadErrorQType =
Samuel Antao4af1b7b2015-12-02 17:44:43 +00005726 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00005727 auto OffloadError = CGF.MakeAddrLValue(
5728 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
5729 OffloadErrorQType);
5730 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
5731 OffloadError);
5732
5733 // Fill up the pointer arrays and transfer execution to the device.
Samuel Antaodf158d52016-04-27 22:58:19 +00005734 auto &&ThenGen = [&Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes, Device,
5735 OutlinedFnID, OffloadError, OffloadErrorQType,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005736 &D](CodeGenFunction &CGF, PrePostActionTy &) {
5737 auto &RT = CGF.CGM.getOpenMPRuntime();
Samuel Antaodf158d52016-04-27 22:58:19 +00005738 // Emit the offloading arrays.
Samuel Antaobed3c462015-10-02 16:14:20 +00005739 llvm::Value *BasePointersArray;
5740 llvm::Value *PointersArray;
5741 llvm::Value *SizesArray;
5742 llvm::Value *MapTypesArray;
Samuel Antaodf158d52016-04-27 22:58:19 +00005743 emitOffloadingArrays(CGF, BasePointersArray, PointersArray, SizesArray,
5744 MapTypesArray, BasePointers, Pointers, Sizes,
5745 MapTypes);
5746 emitOffloadingArraysArgument(CGF, BasePointersArray, PointersArray,
5747 SizesArray, MapTypesArray, BasePointersArray,
5748 PointersArray, SizesArray, MapTypesArray,
5749 BasePointers.size());
Samuel Antaobed3c462015-10-02 16:14:20 +00005750
5751 // On top of the arrays that were filled up, the target offloading call
5752 // takes as arguments the device id as well as the host pointer. The host
5753 // pointer is used by the runtime library to identify the current target
5754 // region, so it only has to be unique and not necessarily point to
5755 // anything. It could be the pointer to the outlined function that
5756 // implements the target region, but we aren't using that so that the
5757 // compiler doesn't need to keep that, and could therefore inline the host
5758 // function if proven worthwhile during optimization.
5759
Samuel Antaoee8fb302016-01-06 13:42:12 +00005760 // From this point on, we need to have an ID of the target region defined.
5761 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00005762
5763 // Emit device ID if any.
5764 llvm::Value *DeviceID;
5765 if (Device)
5766 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005767 CGF.Int32Ty, /*isSigned=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00005768 else
5769 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
5770
Samuel Antaodf158d52016-04-27 22:58:19 +00005771 // Emit the number of elements in the offloading arrays.
5772 llvm::Value *PointerNum = CGF.Builder.getInt32(BasePointers.size());
5773
Samuel Antaob68e2db2016-03-03 16:20:23 +00005774 // Return value of the runtime offloading call.
5775 llvm::Value *Return;
5776
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005777 auto *NumTeams = emitNumTeamsClauseForTargetDirective(RT, CGF, D);
5778 auto *ThreadLimit = emitThreadLimitClauseForTargetDirective(RT, CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00005779
5780 // If we have NumTeams defined this means that we have an enclosed teams
5781 // region. Therefore we also expect to have ThreadLimit defined. These two
5782 // values should be defined in the presence of a teams directive, regardless
5783 // of having any clauses associated. If the user is using teams but no
5784 // clauses, these two values will be the default that should be passed to
5785 // the runtime library - a 32-bit integer with the value zero.
5786 if (NumTeams) {
5787 assert(ThreadLimit && "Thread limit expression should be available along "
5788 "with number of teams.");
5789 llvm::Value *OffloadingArgs[] = {
5790 DeviceID, OutlinedFnID, PointerNum,
5791 BasePointersArray, PointersArray, SizesArray,
5792 MapTypesArray, NumTeams, ThreadLimit};
5793 Return = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005794 RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00005795 } else {
5796 llvm::Value *OffloadingArgs[] = {
5797 DeviceID, OutlinedFnID, PointerNum, BasePointersArray,
5798 PointersArray, SizesArray, MapTypesArray};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005799 Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target),
Samuel Antaob68e2db2016-03-03 16:20:23 +00005800 OffloadingArgs);
5801 }
Samuel Antaobed3c462015-10-02 16:14:20 +00005802
5803 CGF.EmitStoreOfScalar(Return, OffloadError);
5804 };
5805
Samuel Antaoee8fb302016-01-06 13:42:12 +00005806 // Notify that the host version must be executed.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005807 auto &&ElseGen = [OffloadError](CodeGenFunction &CGF, PrePostActionTy &) {
5808 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/-1u),
Samuel Antaoee8fb302016-01-06 13:42:12 +00005809 OffloadError);
5810 };
5811
5812 // If we have a target function ID it means that we need to support
5813 // offloading, otherwise, just execute on the host. We need to execute on host
5814 // regardless of the conditional in the if clause if, e.g., the user do not
5815 // specify target triples.
5816 if (OutlinedFnID) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005817 if (IfCond)
Samuel Antaoee8fb302016-01-06 13:42:12 +00005818 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005819 else {
5820 RegionCodeGenTy ThenRCG(ThenGen);
5821 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005822 }
5823 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005824 RegionCodeGenTy ElseRCG(ElseGen);
5825 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005826 }
Samuel Antaobed3c462015-10-02 16:14:20 +00005827
5828 // Check the error code and execute the host version if required.
5829 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
5830 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
5831 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
5832 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
5833 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
5834
5835 CGF.EmitBlock(OffloadFailedBlock);
Samuel Antao86ace552016-04-27 22:40:57 +00005836 CGF.Builder.CreateCall(OutlinedFn, KernelArgs);
Samuel Antaobed3c462015-10-02 16:14:20 +00005837 CGF.EmitBranch(OffloadContBlock);
5838
5839 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00005840}
Samuel Antaoee8fb302016-01-06 13:42:12 +00005841
5842void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
5843 StringRef ParentName) {
5844 if (!S)
5845 return;
5846
5847 // If we find a OMP target directive, codegen the outline function and
5848 // register the result.
5849 // FIXME: Add other directives with target when they become supported.
5850 bool isTargetDirective = isa<OMPTargetDirective>(S);
5851
5852 if (isTargetDirective) {
5853 auto *E = cast<OMPExecutableDirective>(S);
5854 unsigned DeviceID;
5855 unsigned FileID;
5856 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00005857 getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00005858 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00005859
5860 // Is this a target region that should not be emitted as an entry point? If
5861 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00005862 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
5863 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00005864 return;
5865
5866 llvm::Function *Fn;
5867 llvm::Constant *Addr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005868 std::tie(Fn, Addr) =
5869 CodeGenFunction::EmitOMPTargetDirectiveOutlinedFunction(
5870 CGM, cast<OMPTargetDirective>(*E), ParentName,
5871 /*isOffloadEntry=*/true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00005872 assert(Fn && Addr && "Target region emission failed.");
5873 return;
5874 }
5875
5876 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) {
Samuel Antaoe49645c2016-05-08 06:43:56 +00005877 if (!E->hasAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00005878 return;
5879
5880 scanForTargetRegionsFunctions(
5881 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(),
5882 ParentName);
5883 return;
5884 }
5885
5886 // If this is a lambda function, look into its body.
5887 if (auto *L = dyn_cast<LambdaExpr>(S))
5888 S = L->getBody();
5889
5890 // Keep looking for target regions recursively.
5891 for (auto *II : S->children())
5892 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00005893}
5894
5895bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
5896 auto &FD = *cast<FunctionDecl>(GD.getDecl());
5897
5898 // If emitting code for the host, we do not process FD here. Instead we do
5899 // the normal code generation.
5900 if (!CGM.getLangOpts().OpenMPIsDevice)
5901 return false;
5902
5903 // Try to detect target regions in the function.
5904 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
5905
5906 // We should not emit any function othen that the ones created during the
5907 // scanning. Therefore, we signal that this function is completely dealt
5908 // with.
5909 return true;
5910}
5911
5912bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
5913 if (!CGM.getLangOpts().OpenMPIsDevice)
5914 return false;
5915
5916 // Check if there are Ctors/Dtors in this declaration and look for target
5917 // regions in it. We use the complete variant to produce the kernel name
5918 // mangling.
5919 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
5920 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
5921 for (auto *Ctor : RD->ctors()) {
5922 StringRef ParentName =
5923 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
5924 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
5925 }
5926 auto *Dtor = RD->getDestructor();
5927 if (Dtor) {
5928 StringRef ParentName =
5929 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
5930 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
5931 }
5932 }
5933
5934 // If we are in target mode we do not emit any global (declare target is not
5935 // implemented yet). Therefore we signal that GD was processed in this case.
5936 return true;
5937}
5938
5939bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
5940 auto *VD = GD.getDecl();
5941 if (isa<FunctionDecl>(VD))
5942 return emitTargetFunctions(GD);
5943
5944 return emitTargetGlobalVariable(GD);
5945}
5946
5947llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
5948 // If we have offloading in the current module, we need to emit the entries
5949 // now and register the offloading descriptor.
5950 createOffloadEntriesAndInfoMetadata();
5951
5952 // Create and register the offloading binary descriptors. This is the main
5953 // entity that captures all the information about offloading in the current
5954 // compilation unit.
5955 return createOffloadingBinaryDescriptorRegistration();
5956}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00005957
5958void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
5959 const OMPExecutableDirective &D,
5960 SourceLocation Loc,
5961 llvm::Value *OutlinedFn,
5962 ArrayRef<llvm::Value *> CapturedVars) {
5963 if (!CGF.HaveInsertPoint())
5964 return;
5965
5966 auto *RTLoc = emitUpdateLocation(CGF, Loc);
5967 CodeGenFunction::RunCleanupsScope Scope(CGF);
5968
5969 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
5970 llvm::Value *Args[] = {
5971 RTLoc,
5972 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
5973 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
5974 llvm::SmallVector<llvm::Value *, 16> RealArgs;
5975 RealArgs.append(std::begin(Args), std::end(Args));
5976 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
5977
5978 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
5979 CGF.EmitRuntimeCall(RTLFn, RealArgs);
5980}
5981
5982void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00005983 const Expr *NumTeams,
5984 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00005985 SourceLocation Loc) {
5986 if (!CGF.HaveInsertPoint())
5987 return;
5988
5989 auto *RTLoc = emitUpdateLocation(CGF, Loc);
5990
Carlo Bertollic6872252016-04-04 15:55:02 +00005991 llvm::Value *NumTeamsVal =
5992 (NumTeams)
5993 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
5994 CGF.CGM.Int32Ty, /* isSigned = */ true)
5995 : CGF.Builder.getInt32(0);
5996
5997 llvm::Value *ThreadLimitVal =
5998 (ThreadLimit)
5999 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
6000 CGF.CGM.Int32Ty, /* isSigned = */ true)
6001 : CGF.Builder.getInt32(0);
6002
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00006003 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00006004 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
6005 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00006006 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
6007 PushNumTeamsArgs);
6008}
Samuel Antaodf158d52016-04-27 22:58:19 +00006009
6010void CGOpenMPRuntime::emitTargetDataCalls(CodeGenFunction &CGF,
6011 const OMPExecutableDirective &D,
6012 const Expr *IfCond,
6013 const Expr *Device,
6014 const RegionCodeGenTy &CodeGen) {
6015
6016 if (!CGF.HaveInsertPoint())
6017 return;
6018
6019 llvm::Value *BasePointersArray = nullptr;
6020 llvm::Value *PointersArray = nullptr;
6021 llvm::Value *SizesArray = nullptr;
6022 llvm::Value *MapTypesArray = nullptr;
6023 unsigned NumOfPtrs = 0;
6024
6025 // Generate the code for the opening of the data environment. Capture all the
6026 // arguments of the runtime call by reference because they are used in the
6027 // closing of the region.
6028 auto &&BeginThenGen = [&D, &CGF, &BasePointersArray, &PointersArray,
6029 &SizesArray, &MapTypesArray, Device,
6030 &NumOfPtrs](CodeGenFunction &CGF, PrePostActionTy &) {
6031 // Fill up the arrays with all the mapped variables.
6032 MappableExprsHandler::MapValuesArrayTy BasePointers;
6033 MappableExprsHandler::MapValuesArrayTy Pointers;
6034 MappableExprsHandler::MapValuesArrayTy Sizes;
6035 MappableExprsHandler::MapFlagsArrayTy MapTypes;
6036
6037 // Get map clause information.
6038 MappableExprsHandler MCHandler(D, CGF);
6039 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
6040 NumOfPtrs = BasePointers.size();
6041
6042 // Fill up the arrays and create the arguments.
6043 emitOffloadingArrays(CGF, BasePointersArray, PointersArray, SizesArray,
6044 MapTypesArray, BasePointers, Pointers, Sizes,
6045 MapTypes);
6046
6047 llvm::Value *BasePointersArrayArg = nullptr;
6048 llvm::Value *PointersArrayArg = nullptr;
6049 llvm::Value *SizesArrayArg = nullptr;
6050 llvm::Value *MapTypesArrayArg = nullptr;
6051 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
6052 SizesArrayArg, MapTypesArrayArg,
6053 BasePointersArray, PointersArray, SizesArray,
6054 MapTypesArray, NumOfPtrs);
6055
6056 // Emit device ID if any.
6057 llvm::Value *DeviceID = nullptr;
6058 if (Device)
6059 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
6060 CGF.Int32Ty, /*isSigned=*/true);
6061 else
6062 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
6063
6064 // Emit the number of elements in the offloading arrays.
6065 auto *PointerNum = CGF.Builder.getInt32(NumOfPtrs);
6066
6067 llvm::Value *OffloadingArgs[] = {
6068 DeviceID, PointerNum, BasePointersArrayArg,
6069 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
6070 auto &RT = CGF.CGM.getOpenMPRuntime();
6071 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target_data_begin),
6072 OffloadingArgs);
6073 };
6074
6075 // Generate code for the closing of the data region.
6076 auto &&EndThenGen = [&CGF, &BasePointersArray, &PointersArray, &SizesArray,
6077 &MapTypesArray, Device,
6078 &NumOfPtrs](CodeGenFunction &CGF, PrePostActionTy &) {
6079 assert(BasePointersArray && PointersArray && SizesArray && MapTypesArray &&
6080 NumOfPtrs && "Invalid data environment closing arguments.");
6081
6082 llvm::Value *BasePointersArrayArg = nullptr;
6083 llvm::Value *PointersArrayArg = nullptr;
6084 llvm::Value *SizesArrayArg = nullptr;
6085 llvm::Value *MapTypesArrayArg = nullptr;
6086 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
6087 SizesArrayArg, MapTypesArrayArg,
6088 BasePointersArray, PointersArray, SizesArray,
6089 MapTypesArray, NumOfPtrs);
6090
6091 // Emit device ID if any.
6092 llvm::Value *DeviceID = nullptr;
6093 if (Device)
6094 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
6095 CGF.Int32Ty, /*isSigned=*/true);
6096 else
6097 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
6098
6099 // Emit the number of elements in the offloading arrays.
6100 auto *PointerNum = CGF.Builder.getInt32(NumOfPtrs);
6101
6102 llvm::Value *OffloadingArgs[] = {
6103 DeviceID, PointerNum, BasePointersArrayArg,
6104 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
6105 auto &RT = CGF.CGM.getOpenMPRuntime();
6106 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target_data_end),
6107 OffloadingArgs);
6108 };
6109
6110 // In the event we get an if clause, we don't have to take any action on the
6111 // else side.
6112 auto &&ElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
6113
6114 if (IfCond) {
6115 emitOMPIfClause(CGF, IfCond, BeginThenGen, ElseGen);
6116 } else {
6117 RegionCodeGenTy BeginThenRCG(BeginThenGen);
6118 BeginThenRCG(CGF);
6119 }
6120
6121 CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data, CodeGen);
6122
6123 if (IfCond) {
6124 emitOMPIfClause(CGF, IfCond, EndThenGen, ElseGen);
6125 } else {
6126 RegionCodeGenTy EndThenRCG(EndThenGen);
6127 EndThenRCG(CGF);
6128 }
6129}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00006130
Samuel Antao8dd66282016-04-27 23:14:30 +00006131void CGOpenMPRuntime::emitTargetEnterOrExitDataCall(
6132 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
6133 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00006134 if (!CGF.HaveInsertPoint())
6135 return;
6136
Samuel Antao8dd66282016-04-27 23:14:30 +00006137 assert((isa<OMPTargetEnterDataDirective>(D) ||
6138 isa<OMPTargetExitDataDirective>(D)) &&
6139 "Expecting either target enter or exit data directives.");
6140
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00006141 // Generate the code for the opening of the data environment.
6142 auto &&ThenGen = [&D, &CGF, Device](CodeGenFunction &CGF, PrePostActionTy &) {
6143 // Fill up the arrays with all the mapped variables.
6144 MappableExprsHandler::MapValuesArrayTy BasePointers;
6145 MappableExprsHandler::MapValuesArrayTy Pointers;
6146 MappableExprsHandler::MapValuesArrayTy Sizes;
6147 MappableExprsHandler::MapFlagsArrayTy MapTypes;
6148
6149 // Get map clause information.
6150 MappableExprsHandler MCHandler(D, CGF);
6151 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
6152
6153 llvm::Value *BasePointersArrayArg = nullptr;
6154 llvm::Value *PointersArrayArg = nullptr;
6155 llvm::Value *SizesArrayArg = nullptr;
6156 llvm::Value *MapTypesArrayArg = nullptr;
6157
6158 // Fill up the arrays and create the arguments.
6159 emitOffloadingArrays(CGF, BasePointersArrayArg, PointersArrayArg,
6160 SizesArrayArg, MapTypesArrayArg, BasePointers,
6161 Pointers, Sizes, MapTypes);
6162 emitOffloadingArraysArgument(
6163 CGF, BasePointersArrayArg, PointersArrayArg, SizesArrayArg,
6164 MapTypesArrayArg, BasePointersArrayArg, PointersArrayArg, SizesArrayArg,
6165 MapTypesArrayArg, BasePointers.size());
6166
6167 // Emit device ID if any.
6168 llvm::Value *DeviceID = nullptr;
6169 if (Device)
6170 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
6171 CGF.Int32Ty, /*isSigned=*/true);
6172 else
6173 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
6174
6175 // Emit the number of elements in the offloading arrays.
6176 auto *PointerNum = CGF.Builder.getInt32(BasePointers.size());
6177
6178 llvm::Value *OffloadingArgs[] = {
6179 DeviceID, PointerNum, BasePointersArrayArg,
6180 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
6181 auto &RT = CGF.CGM.getOpenMPRuntime();
Samuel Antao8dd66282016-04-27 23:14:30 +00006182 CGF.EmitRuntimeCall(
6183 RT.createRuntimeFunction(isa<OMPTargetEnterDataDirective>(D)
6184 ? OMPRTL__tgt_target_data_begin
6185 : OMPRTL__tgt_target_data_end),
6186 OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00006187 };
6188
6189 // In the event we get an if clause, we don't have to take any action on the
6190 // else side.
6191 auto &&ElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
6192
6193 if (IfCond) {
6194 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
6195 } else {
6196 RegionCodeGenTy ThenGenRCG(ThenGen);
6197 ThenGenRCG(CGF);
6198 }
6199}
Alexey Bataevc7a82b42016-05-06 09:40:08 +00006200
6201namespace {
6202 /// Kind of parameter in a function with 'declare simd' directive.
6203 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
6204 /// Attribute set of the parameter.
6205 struct ParamAttrTy {
6206 ParamKindTy Kind = Vector;
6207 llvm::APSInt StrideOrArg;
6208 llvm::APSInt Alignment;
6209 };
6210} // namespace
6211
6212static unsigned evaluateCDTSize(const FunctionDecl *FD,
6213 ArrayRef<ParamAttrTy> ParamAttrs) {
6214 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
6215 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
6216 // of that clause. The VLEN value must be power of 2.
6217 // In other case the notion of the function`s "characteristic data type" (CDT)
6218 // is used to compute the vector length.
6219 // CDT is defined in the following order:
6220 // a) For non-void function, the CDT is the return type.
6221 // b) If the function has any non-uniform, non-linear parameters, then the
6222 // CDT is the type of the first such parameter.
6223 // c) If the CDT determined by a) or b) above is struct, union, or class
6224 // type which is pass-by-value (except for the type that maps to the
6225 // built-in complex data type), the characteristic data type is int.
6226 // d) If none of the above three cases is applicable, the CDT is int.
6227 // The VLEN is then determined based on the CDT and the size of vector
6228 // register of that ISA for which current vector version is generated. The
6229 // VLEN is computed using the formula below:
6230 // VLEN = sizeof(vector_register) / sizeof(CDT),
6231 // where vector register size specified in section 3.2.1 Registers and the
6232 // Stack Frame of original AMD64 ABI document.
6233 QualType RetType = FD->getReturnType();
6234 if (RetType.isNull())
6235 return 0;
6236 ASTContext &C = FD->getASTContext();
6237 QualType CDT;
6238 if (!RetType.isNull() && !RetType->isVoidType())
6239 CDT = RetType;
6240 else {
6241 unsigned Offset = 0;
6242 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
6243 if (ParamAttrs[Offset].Kind == Vector)
6244 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
6245 ++Offset;
6246 }
6247 if (CDT.isNull()) {
6248 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
6249 if (ParamAttrs[I + Offset].Kind == Vector) {
6250 CDT = FD->getParamDecl(I)->getType();
6251 break;
6252 }
6253 }
6254 }
6255 }
6256 if (CDT.isNull())
6257 CDT = C.IntTy;
6258 CDT = CDT->getCanonicalTypeUnqualified();
6259 if (CDT->isRecordType() || CDT->isUnionType())
6260 CDT = C.IntTy;
6261 return C.getTypeSize(CDT);
6262}
6263
6264static void
6265emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
6266 llvm::APSInt VLENVal,
6267 ArrayRef<ParamAttrTy> ParamAttrs,
6268 OMPDeclareSimdDeclAttr::BranchStateTy State) {
6269 struct ISADataTy {
6270 char ISA;
6271 unsigned VecRegSize;
6272 };
6273 ISADataTy ISAData[] = {
6274 {
6275 'b', 128
6276 }, // SSE
6277 {
6278 'c', 256
6279 }, // AVX
6280 {
6281 'd', 256
6282 }, // AVX2
6283 {
6284 'e', 512
6285 }, // AVX512
6286 };
6287 llvm::SmallVector<char, 2> Masked;
6288 switch (State) {
6289 case OMPDeclareSimdDeclAttr::BS_Undefined:
6290 Masked.push_back('N');
6291 Masked.push_back('M');
6292 break;
6293 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
6294 Masked.push_back('N');
6295 break;
6296 case OMPDeclareSimdDeclAttr::BS_Inbranch:
6297 Masked.push_back('M');
6298 break;
6299 }
6300 for (auto Mask : Masked) {
6301 for (auto &Data : ISAData) {
6302 SmallString<256> Buffer;
6303 llvm::raw_svector_ostream Out(Buffer);
6304 Out << "_ZGV" << Data.ISA << Mask;
6305 if (!VLENVal) {
6306 Out << llvm::APSInt::getUnsigned(Data.VecRegSize /
6307 evaluateCDTSize(FD, ParamAttrs));
6308 } else
6309 Out << VLENVal;
6310 for (auto &ParamAttr : ParamAttrs) {
6311 switch (ParamAttr.Kind){
6312 case LinearWithVarStride:
6313 Out << 's' << ParamAttr.StrideOrArg;
6314 break;
6315 case Linear:
6316 Out << 'l';
6317 if (!!ParamAttr.StrideOrArg)
6318 Out << ParamAttr.StrideOrArg;
6319 break;
6320 case Uniform:
6321 Out << 'u';
6322 break;
6323 case Vector:
6324 Out << 'v';
6325 break;
6326 }
6327 if (!!ParamAttr.Alignment)
6328 Out << 'a' << ParamAttr.Alignment;
6329 }
6330 Out << '_' << Fn->getName();
6331 Fn->addFnAttr(Out.str());
6332 }
6333 }
6334}
6335
6336void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
6337 llvm::Function *Fn) {
6338 ASTContext &C = CGM.getContext();
6339 FD = FD->getCanonicalDecl();
6340 // Map params to their positions in function decl.
6341 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
6342 if (isa<CXXMethodDecl>(FD))
6343 ParamPositions.insert({FD, 0});
6344 unsigned ParamPos = ParamPositions.size();
6345 for (auto *P : FD->params()) {
6346 ParamPositions.insert({P->getCanonicalDecl(), ParamPos});
6347 ++ParamPos;
6348 }
6349 for (auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
6350 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
6351 // Mark uniform parameters.
6352 for (auto *E : Attr->uniforms()) {
6353 E = E->IgnoreParenImpCasts();
6354 unsigned Pos;
6355 if (isa<CXXThisExpr>(E))
6356 Pos = ParamPositions[FD];
6357 else {
6358 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
6359 ->getCanonicalDecl();
6360 Pos = ParamPositions[PVD];
6361 }
6362 ParamAttrs[Pos].Kind = Uniform;
6363 }
6364 // Get alignment info.
6365 auto NI = Attr->alignments_begin();
6366 for (auto *E : Attr->aligneds()) {
6367 E = E->IgnoreParenImpCasts();
6368 unsigned Pos;
6369 QualType ParmTy;
6370 if (isa<CXXThisExpr>(E)) {
6371 Pos = ParamPositions[FD];
6372 ParmTy = E->getType();
6373 } else {
6374 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
6375 ->getCanonicalDecl();
6376 Pos = ParamPositions[PVD];
6377 ParmTy = PVD->getType();
6378 }
6379 ParamAttrs[Pos].Alignment =
6380 (*NI) ? (*NI)->EvaluateKnownConstInt(C)
6381 : llvm::APSInt::getUnsigned(
6382 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
6383 .getQuantity());
6384 ++NI;
6385 }
6386 // Mark linear parameters.
6387 auto SI = Attr->steps_begin();
6388 auto MI = Attr->modifiers_begin();
6389 for (auto *E : Attr->linears()) {
6390 E = E->IgnoreParenImpCasts();
6391 unsigned Pos;
6392 if (isa<CXXThisExpr>(E))
6393 Pos = ParamPositions[FD];
6394 else {
6395 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
6396 ->getCanonicalDecl();
6397 Pos = ParamPositions[PVD];
6398 }
6399 auto &ParamAttr = ParamAttrs[Pos];
6400 ParamAttr.Kind = Linear;
6401 if (*SI) {
6402 if (!(*SI)->EvaluateAsInt(ParamAttr.StrideOrArg, C,
6403 Expr::SE_AllowSideEffects)) {
6404 if (auto *DRE = cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
6405 if (auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
6406 ParamAttr.Kind = LinearWithVarStride;
6407 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
6408 ParamPositions[StridePVD->getCanonicalDecl()]);
6409 }
6410 }
6411 }
6412 }
6413 ++SI;
6414 ++MI;
6415 }
6416 llvm::APSInt VLENVal;
6417 if (const Expr *VLEN = Attr->getSimdlen())
6418 VLENVal = VLEN->EvaluateKnownConstInt(C);
6419 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
6420 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
6421 CGM.getTriple().getArch() == llvm::Triple::x86_64)
6422 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
6423 }
6424}
Alexey Bataev8b427062016-05-25 12:36:08 +00006425
6426namespace {
6427/// Cleanup action for doacross support.
6428class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
6429public:
6430 static const int DoacrossFinArgs = 2;
6431
6432private:
6433 llvm::Value *RTLFn;
6434 llvm::Value *Args[DoacrossFinArgs];
6435
6436public:
6437 DoacrossCleanupTy(llvm::Value *RTLFn, ArrayRef<llvm::Value *> CallArgs)
6438 : RTLFn(RTLFn) {
6439 assert(CallArgs.size() == DoacrossFinArgs);
6440 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
6441 }
6442 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
6443 if (!CGF.HaveInsertPoint())
6444 return;
6445 CGF.EmitRuntimeCall(RTLFn, Args);
6446 }
6447};
6448} // namespace
6449
6450void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
6451 const OMPLoopDirective &D) {
6452 if (!CGF.HaveInsertPoint())
6453 return;
6454
6455 ASTContext &C = CGM.getContext();
6456 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
6457 RecordDecl *RD;
6458 if (KmpDimTy.isNull()) {
6459 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
6460 // kmp_int64 lo; // lower
6461 // kmp_int64 up; // upper
6462 // kmp_int64 st; // stride
6463 // };
6464 RD = C.buildImplicitRecord("kmp_dim");
6465 RD->startDefinition();
6466 addFieldToRecordDecl(C, RD, Int64Ty);
6467 addFieldToRecordDecl(C, RD, Int64Ty);
6468 addFieldToRecordDecl(C, RD, Int64Ty);
6469 RD->completeDefinition();
6470 KmpDimTy = C.getRecordType(RD);
6471 } else
6472 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
6473
6474 Address DimsAddr = CGF.CreateMemTemp(KmpDimTy, "dims");
6475 CGF.EmitNullInitialization(DimsAddr, KmpDimTy);
6476 enum { LowerFD = 0, UpperFD, StrideFD };
6477 // Fill dims with data.
6478 LValue DimsLVal = CGF.MakeAddrLValue(DimsAddr, KmpDimTy);
6479 // dims.upper = num_iterations;
6480 LValue UpperLVal =
6481 CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), UpperFD));
6482 llvm::Value *NumIterVal = CGF.EmitScalarConversion(
6483 CGF.EmitScalarExpr(D.getNumIterations()), D.getNumIterations()->getType(),
6484 Int64Ty, D.getNumIterations()->getExprLoc());
6485 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
6486 // dims.stride = 1;
6487 LValue StrideLVal =
6488 CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), StrideFD));
6489 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
6490 StrideLVal);
6491
6492 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
6493 // kmp_int32 num_dims, struct kmp_dim * dims);
6494 llvm::Value *Args[] = {emitUpdateLocation(CGF, D.getLocStart()),
6495 getThreadID(CGF, D.getLocStart()),
6496 llvm::ConstantInt::getSigned(CGM.Int32Ty, 1),
6497 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6498 DimsAddr.getPointer(), CGM.VoidPtrTy)};
6499
6500 llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_init);
6501 CGF.EmitRuntimeCall(RTLFn, Args);
6502 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
6503 emitUpdateLocation(CGF, D.getLocEnd()), getThreadID(CGF, D.getLocEnd())};
6504 llvm::Value *FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
6505 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
6506 llvm::makeArrayRef(FiniArgs));
6507}
6508
6509void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
6510 const OMPDependClause *C) {
6511 QualType Int64Ty =
6512 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
6513 const Expr *CounterVal = C->getCounterValue();
6514 assert(CounterVal);
6515 llvm::Value *CntVal = CGF.EmitScalarConversion(CGF.EmitScalarExpr(CounterVal),
6516 CounterVal->getType(), Int64Ty,
6517 CounterVal->getExprLoc());
6518 Address CntAddr = CGF.CreateMemTemp(Int64Ty, ".cnt.addr");
6519 CGF.EmitStoreOfScalar(CntVal, CntAddr, /*Volatile=*/false, Int64Ty);
6520 llvm::Value *Args[] = {emitUpdateLocation(CGF, C->getLocStart()),
6521 getThreadID(CGF, C->getLocStart()),
6522 CntAddr.getPointer()};
6523 llvm::Value *RTLFn;
6524 if (C->getDependencyKind() == OMPC_DEPEND_source)
6525 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
6526 else {
6527 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
6528 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
6529 }
6530 CGF.EmitRuntimeCall(RTLFn, Args);
6531}
6532