blob: 3ac572e8bed0bb823e9d0b98bd8b828e10c01352 [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 Antao86ace552016-04-27 22:40:57 +00004930 /// \brief Pass the element to the device by value.
Samuel Antao6782e942016-05-26 16:48:10 +00004931 OMP_MAP_PRIVATE_VAL = 0x100,
Samuel Antao86ace552016-04-27 22:40:57 +00004932 };
4933
4934 typedef SmallVector<llvm::Value *, 16> MapValuesArrayTy;
4935 typedef SmallVector<unsigned, 16> MapFlagsArrayTy;
4936
4937private:
4938 /// \brief Directive from where the map clauses were extracted.
4939 const OMPExecutableDirective &Directive;
4940
4941 /// \brief Function the directive is being generated for.
4942 CodeGenFunction &CGF;
4943
4944 llvm::Value *getExprTypeSize(const Expr *E) const {
4945 auto ExprTy = E->getType().getCanonicalType();
4946
4947 // Reference types are ignored for mapping purposes.
4948 if (auto *RefTy = ExprTy->getAs<ReferenceType>())
4949 ExprTy = RefTy->getPointeeType().getCanonicalType();
4950
4951 // Given that an array section is considered a built-in type, we need to
4952 // do the calculation based on the length of the section instead of relying
4953 // on CGF.getTypeSize(E->getType()).
4954 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
4955 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
4956 OAE->getBase()->IgnoreParenImpCasts())
4957 .getCanonicalType();
4958
4959 // If there is no length associated with the expression, that means we
4960 // are using the whole length of the base.
4961 if (!OAE->getLength() && OAE->getColonLoc().isValid())
4962 return CGF.getTypeSize(BaseTy);
4963
4964 llvm::Value *ElemSize;
4965 if (auto *PTy = BaseTy->getAs<PointerType>())
4966 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
4967 else {
4968 auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
4969 assert(ATy && "Expecting array type if not a pointer type.");
4970 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
4971 }
4972
4973 // If we don't have a length at this point, that is because we have an
4974 // array section with a single element.
4975 if (!OAE->getLength())
4976 return ElemSize;
4977
4978 auto *LengthVal = CGF.EmitScalarExpr(OAE->getLength());
4979 LengthVal =
4980 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false);
4981 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
4982 }
4983 return CGF.getTypeSize(ExprTy);
4984 }
4985
4986 /// \brief Return the corresponding bits for a given map clause modifier. Add
4987 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00004988 /// map as the first one of a series of maps that relate to the same map
4989 /// expression.
Samuel Antao86ace552016-04-27 22:40:57 +00004990 unsigned getMapTypeBits(OpenMPMapClauseKind MapType,
4991 OpenMPMapClauseKind MapTypeModifier, bool AddPtrFlag,
Samuel Antao6782e942016-05-26 16:48:10 +00004992 bool AddIsFirstFlag) const {
Samuel Antao86ace552016-04-27 22:40:57 +00004993 unsigned Bits = 0u;
4994 switch (MapType) {
4995 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00004996 case OMPC_MAP_release:
4997 // alloc and release is the default behavior in the runtime library, i.e.
4998 // if we don't pass any bits alloc/release that is what the runtime is
4999 // going to do. Therefore, we don't need to signal anything for these two
5000 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00005001 break;
5002 case OMPC_MAP_to:
5003 Bits = OMP_MAP_TO;
5004 break;
5005 case OMPC_MAP_from:
5006 Bits = OMP_MAP_FROM;
5007 break;
5008 case OMPC_MAP_tofrom:
5009 Bits = OMP_MAP_TO | OMP_MAP_FROM;
5010 break;
5011 case OMPC_MAP_delete:
5012 Bits = OMP_MAP_DELETE;
5013 break;
Samuel Antao86ace552016-04-27 22:40:57 +00005014 default:
5015 llvm_unreachable("Unexpected map type!");
5016 break;
5017 }
5018 if (AddPtrFlag)
Samuel Antao6782e942016-05-26 16:48:10 +00005019 Bits |= OMP_MAP_IS_PTR;
5020 if (AddIsFirstFlag)
5021 Bits |= OMP_MAP_FIRST_REF;
Samuel Antao86ace552016-04-27 22:40:57 +00005022 if (MapTypeModifier == OMPC_MAP_always)
5023 Bits |= OMP_MAP_ALWAYS;
5024 return Bits;
5025 }
5026
5027 /// \brief Return true if the provided expression is a final array section. A
5028 /// final array section, is one whose length can't be proved to be one.
5029 bool isFinalArraySectionExpression(const Expr *E) const {
5030 auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
5031
5032 // It is not an array section and therefore not a unity-size one.
5033 if (!OASE)
5034 return false;
5035
5036 // An array section with no colon always refer to a single element.
5037 if (OASE->getColonLoc().isInvalid())
5038 return false;
5039
5040 auto *Length = OASE->getLength();
5041
5042 // If we don't have a length we have to check if the array has size 1
5043 // for this dimension. Also, we should always expect a length if the
5044 // base type is pointer.
5045 if (!Length) {
5046 auto BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
5047 OASE->getBase()->IgnoreParenImpCasts())
5048 .getCanonicalType();
5049 if (auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
5050 return ATy->getSize().getSExtValue() != 1;
5051 // If we don't have a constant dimension length, we have to consider
5052 // the current section as having any size, so it is not necessarily
5053 // unitary. If it happen to be unity size, that's user fault.
5054 return true;
5055 }
5056
5057 // Check if the length evaluates to 1.
5058 llvm::APSInt ConstLength;
5059 if (!Length->EvaluateAsInt(ConstLength, CGF.getContext()))
5060 return true; // Can have more that size 1.
5061
5062 return ConstLength.getSExtValue() != 1;
5063 }
5064
5065 /// \brief Generate the base pointers, section pointers, sizes and map type
5066 /// bits for the provided map type, map modifier, and expression components.
5067 /// \a IsFirstComponent should be set to true if the provided set of
5068 /// components is the first associated with a capture.
5069 void generateInfoForComponentList(
5070 OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier,
5071 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
5072 MapValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
5073 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
5074 bool IsFirstComponentList) const {
5075
5076 // The following summarizes what has to be generated for each map and the
5077 // types bellow. The generated information is expressed in this order:
5078 // base pointer, section pointer, size, flags
5079 // (to add to the ones that come from the map type and modifier).
5080 //
5081 // double d;
5082 // int i[100];
5083 // float *p;
5084 //
5085 // struct S1 {
5086 // int i;
5087 // float f[50];
5088 // }
5089 // struct S2 {
5090 // int i;
5091 // float f[50];
5092 // S1 s;
5093 // double *p;
5094 // struct S2 *ps;
5095 // }
5096 // S2 s;
5097 // S2 *ps;
5098 //
5099 // map(d)
5100 // &d, &d, sizeof(double), noflags
5101 //
5102 // map(i)
5103 // &i, &i, 100*sizeof(int), noflags
5104 //
5105 // map(i[1:23])
5106 // &i(=&i[0]), &i[1], 23*sizeof(int), noflags
5107 //
5108 // map(p)
5109 // &p, &p, sizeof(float*), noflags
5110 //
5111 // map(p[1:24])
5112 // p, &p[1], 24*sizeof(float), noflags
5113 //
5114 // map(s)
5115 // &s, &s, sizeof(S2), noflags
5116 //
5117 // map(s.i)
5118 // &s, &(s.i), sizeof(int), noflags
5119 //
5120 // map(s.s.f)
5121 // &s, &(s.i.f), 50*sizeof(int), noflags
5122 //
5123 // map(s.p)
5124 // &s, &(s.p), sizeof(double*), noflags
5125 //
5126 // map(s.p[:22], s.a s.b)
5127 // &s, &(s.p), sizeof(double*), noflags
5128 // &(s.p), &(s.p[0]), 22*sizeof(double), ptr_flag + extra_flag
5129 //
5130 // map(s.ps)
5131 // &s, &(s.ps), sizeof(S2*), noflags
5132 //
5133 // map(s.ps->s.i)
5134 // &s, &(s.ps), sizeof(S2*), noflags
5135 // &(s.ps), &(s.ps->s.i), sizeof(int), ptr_flag + extra_flag
5136 //
5137 // map(s.ps->ps)
5138 // &s, &(s.ps), sizeof(S2*), noflags
5139 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag
5140 //
5141 // map(s.ps->ps->ps)
5142 // &s, &(s.ps), sizeof(S2*), noflags
5143 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag
5144 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
5145 //
5146 // map(s.ps->ps->s.f[:22])
5147 // &s, &(s.ps), sizeof(S2*), noflags
5148 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag
5149 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), ptr_flag + extra_flag
5150 //
5151 // map(ps)
5152 // &ps, &ps, sizeof(S2*), noflags
5153 //
5154 // map(ps->i)
5155 // ps, &(ps->i), sizeof(int), noflags
5156 //
5157 // map(ps->s.f)
5158 // ps, &(ps->s.f[0]), 50*sizeof(float), noflags
5159 //
5160 // map(ps->p)
5161 // ps, &(ps->p), sizeof(double*), noflags
5162 //
5163 // map(ps->p[:22])
5164 // ps, &(ps->p), sizeof(double*), noflags
5165 // &(ps->p), &(ps->p[0]), 22*sizeof(double), ptr_flag + extra_flag
5166 //
5167 // map(ps->ps)
5168 // ps, &(ps->ps), sizeof(S2*), noflags
5169 //
5170 // map(ps->ps->s.i)
5171 // ps, &(ps->ps), sizeof(S2*), noflags
5172 // &(ps->ps), &(ps->ps->s.i), sizeof(int), ptr_flag + extra_flag
5173 //
5174 // map(ps->ps->ps)
5175 // ps, &(ps->ps), sizeof(S2*), noflags
5176 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
5177 //
5178 // map(ps->ps->ps->ps)
5179 // ps, &(ps->ps), sizeof(S2*), noflags
5180 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
5181 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
5182 //
5183 // map(ps->ps->ps->s.f[:22])
5184 // ps, &(ps->ps), sizeof(S2*), noflags
5185 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag
5186 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), ptr_flag +
5187 // extra_flag
5188
5189 // Track if the map information being generated is the first for a capture.
5190 bool IsCaptureFirstInfo = IsFirstComponentList;
5191
5192 // Scan the components from the base to the complete expression.
5193 auto CI = Components.rbegin();
5194 auto CE = Components.rend();
5195 auto I = CI;
5196
5197 // Track if the map information being generated is the first for a list of
5198 // components.
5199 bool IsExpressionFirstInfo = true;
5200 llvm::Value *BP = nullptr;
5201
5202 if (auto *ME = dyn_cast<MemberExpr>(I->getAssociatedExpression())) {
5203 // The base is the 'this' pointer. The content of the pointer is going
5204 // to be the base of the field being mapped.
5205 BP = CGF.EmitScalarExpr(ME->getBase());
5206 } else {
5207 // The base is the reference to the variable.
5208 // BP = &Var.
5209 BP = CGF.EmitLValue(cast<DeclRefExpr>(I->getAssociatedExpression()))
5210 .getPointer();
5211
5212 // If the variable is a pointer and is being dereferenced (i.e. is not
5213 // the last component), the base has to be the pointer itself, not his
5214 // reference.
5215 if (I->getAssociatedDeclaration()->getType()->isAnyPointerType() &&
5216 std::next(I) != CE) {
5217 auto PtrAddr = CGF.MakeNaturalAlignAddrLValue(
5218 BP, I->getAssociatedDeclaration()->getType());
5219 BP = CGF.EmitLoadOfPointerLValue(PtrAddr.getAddress(),
5220 I->getAssociatedDeclaration()
5221 ->getType()
5222 ->getAs<PointerType>())
5223 .getPointer();
5224
5225 // We do not need to generate individual map information for the
5226 // pointer, it can be associated with the combined storage.
5227 ++I;
5228 }
5229 }
5230
5231 for (; I != CE; ++I) {
5232 auto Next = std::next(I);
5233
5234 // We need to generate the addresses and sizes if this is the last
5235 // component, if the component is a pointer or if it is an array section
5236 // whose length can't be proved to be one. If this is a pointer, it
5237 // becomes the base address for the following components.
5238
5239 // A final array section, is one whose length can't be proved to be one.
5240 bool IsFinalArraySection =
5241 isFinalArraySectionExpression(I->getAssociatedExpression());
5242
5243 // Get information on whether the element is a pointer. Have to do a
5244 // special treatment for array sections given that they are built-in
5245 // types.
5246 const auto *OASE =
5247 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
5248 bool IsPointer =
5249 (OASE &&
5250 OMPArraySectionExpr::getBaseOriginalType(OASE)
5251 .getCanonicalType()
5252 ->isAnyPointerType()) ||
5253 I->getAssociatedExpression()->getType()->isAnyPointerType();
5254
5255 if (Next == CE || IsPointer || IsFinalArraySection) {
5256
5257 // If this is not the last component, we expect the pointer to be
5258 // associated with an array expression or member expression.
5259 assert((Next == CE ||
5260 isa<MemberExpr>(Next->getAssociatedExpression()) ||
5261 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
5262 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
5263 "Unexpected expression");
5264
5265 // Save the base we are currently using.
5266 BasePointers.push_back(BP);
5267
5268 auto *LB = CGF.EmitLValue(I->getAssociatedExpression()).getPointer();
5269 auto *Size = getExprTypeSize(I->getAssociatedExpression());
5270
5271 Pointers.push_back(LB);
5272 Sizes.push_back(Size);
Samuel Antao6782e942016-05-26 16:48:10 +00005273 // We need to add a pointer flag for each map that comes from the
5274 // same expression except for the first one. We also need to signal
5275 // this map is the first one that relates with the current capture
5276 // (there is a set of entries for each capture).
Samuel Antao86ace552016-04-27 22:40:57 +00005277 Types.push_back(getMapTypeBits(MapType, MapTypeModifier,
5278 !IsExpressionFirstInfo,
Samuel Antao6782e942016-05-26 16:48:10 +00005279 IsCaptureFirstInfo));
Samuel Antao86ace552016-04-27 22:40:57 +00005280
5281 // If we have a final array section, we are done with this expression.
5282 if (IsFinalArraySection)
5283 break;
5284
5285 // The pointer becomes the base for the next element.
5286 if (Next != CE)
5287 BP = LB;
5288
5289 IsExpressionFirstInfo = false;
5290 IsCaptureFirstInfo = false;
5291 continue;
5292 }
5293 }
5294 }
5295
5296public:
5297 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
5298 : Directive(Dir), CGF(CGF) {}
5299
5300 /// \brief Generate all the base pointers, section pointers, sizes and map
5301 /// types for the extracted mappable expressions.
5302 void generateAllInfo(MapValuesArrayTy &BasePointers,
5303 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
5304 MapFlagsArrayTy &Types) const {
5305 BasePointers.clear();
5306 Pointers.clear();
5307 Sizes.clear();
5308 Types.clear();
5309
5310 struct MapInfo {
5311 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
5312 OpenMPMapClauseKind MapType;
5313 OpenMPMapClauseKind MapTypeModifier;
5314 };
5315
5316 // We have to process the component lists that relate with the same
5317 // declaration in a single chunk so that we can generate the map flags
5318 // correctly. Therefore, we organize all lists in a map.
5319 llvm::DenseMap<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
5320 for (auto *C : Directive.getClausesOfKind<OMPMapClause>())
5321 for (auto L : C->component_lists()) {
5322 const ValueDecl *VD =
5323 L.first ? cast<ValueDecl>(L.first->getCanonicalDecl()) : nullptr;
5324 Info[VD].push_back(
5325 {L.second, C->getMapType(), C->getMapTypeModifier()});
5326 }
5327
5328 for (auto &M : Info) {
5329 // We need to know when we generate information for the first component
5330 // associated with a capture, because the mapping flags depend on it.
5331 bool IsFirstComponentList = true;
5332 for (MapInfo &L : M.second) {
5333 assert(!L.Components.empty() &&
5334 "Not expecting declaration with no component lists.");
5335 generateInfoForComponentList(L.MapType, L.MapTypeModifier, L.Components,
5336 BasePointers, Pointers, Sizes, Types,
5337 IsFirstComponentList);
5338 IsFirstComponentList = false;
5339 }
5340 }
5341 }
5342
5343 /// \brief Generate the base pointers, section pointers, sizes and map types
5344 /// associated to a given capture.
5345 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
5346 MapValuesArrayTy &BasePointers,
5347 MapValuesArrayTy &Pointers,
5348 MapValuesArrayTy &Sizes,
5349 MapFlagsArrayTy &Types) const {
5350 assert(!Cap->capturesVariableArrayType() &&
5351 "Not expecting to generate map info for a variable array type!");
5352
5353 BasePointers.clear();
5354 Pointers.clear();
5355 Sizes.clear();
5356 Types.clear();
5357
5358 const ValueDecl *VD =
5359 Cap->capturesThis()
5360 ? nullptr
5361 : cast<ValueDecl>(Cap->getCapturedVar()->getCanonicalDecl());
5362
5363 // We need to know when we generating information for the first component
5364 // associated with a capture, because the mapping flags depend on it.
5365 bool IsFirstComponentList = true;
5366 for (auto *C : Directive.getClausesOfKind<OMPMapClause>())
5367 for (auto L : C->decl_component_lists(VD)) {
5368 assert(L.first == VD &&
5369 "We got information for the wrong declaration??");
5370 assert(!L.second.empty() &&
5371 "Not expecting declaration with no component lists.");
5372 generateInfoForComponentList(C->getMapType(), C->getMapTypeModifier(),
5373 L.second, BasePointers, Pointers, Sizes,
5374 Types, IsFirstComponentList);
5375 IsFirstComponentList = false;
5376 }
5377
5378 return;
5379 }
5380};
Samuel Antaodf158d52016-04-27 22:58:19 +00005381
5382enum OpenMPOffloadingReservedDeviceIDs {
5383 /// \brief Device ID if the device was not defined, runtime should get it
5384 /// from environment variables in the spec.
5385 OMP_DEVICEID_UNDEF = -1,
5386};
5387} // anonymous namespace
5388
5389/// \brief Emit the arrays used to pass the captures and map information to the
5390/// offloading runtime library. If there is no map or capture information,
5391/// return nullptr by reference.
5392static void
5393emitOffloadingArrays(CodeGenFunction &CGF, llvm::Value *&BasePointersArray,
5394 llvm::Value *&PointersArray, llvm::Value *&SizesArray,
5395 llvm::Value *&MapTypesArray,
5396 MappableExprsHandler::MapValuesArrayTy &BasePointers,
5397 MappableExprsHandler::MapValuesArrayTy &Pointers,
5398 MappableExprsHandler::MapValuesArrayTy &Sizes,
5399 MappableExprsHandler::MapFlagsArrayTy &MapTypes) {
5400 auto &CGM = CGF.CGM;
5401 auto &Ctx = CGF.getContext();
5402
5403 BasePointersArray = PointersArray = SizesArray = MapTypesArray = nullptr;
5404
5405 if (unsigned PointerNumVal = BasePointers.size()) {
5406 // Detect if we have any capture size requiring runtime evaluation of the
5407 // size so that a constant array could be eventually used.
5408 bool hasRuntimeEvaluationCaptureSize = false;
5409 for (auto *S : Sizes)
5410 if (!isa<llvm::Constant>(S)) {
5411 hasRuntimeEvaluationCaptureSize = true;
5412 break;
5413 }
5414
5415 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
5416 QualType PointerArrayType =
5417 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
5418 /*IndexTypeQuals=*/0);
5419
5420 BasePointersArray =
5421 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
5422 PointersArray =
5423 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
5424
5425 // If we don't have any VLA types or other types that require runtime
5426 // evaluation, we can use a constant array for the map sizes, otherwise we
5427 // need to fill up the arrays as we do for the pointers.
5428 if (hasRuntimeEvaluationCaptureSize) {
5429 QualType SizeArrayType = Ctx.getConstantArrayType(
5430 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
5431 /*IndexTypeQuals=*/0);
5432 SizesArray =
5433 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
5434 } else {
5435 // We expect all the sizes to be constant, so we collect them to create
5436 // a constant array.
5437 SmallVector<llvm::Constant *, 16> ConstSizes;
5438 for (auto S : Sizes)
5439 ConstSizes.push_back(cast<llvm::Constant>(S));
5440
5441 auto *SizesArrayInit = llvm::ConstantArray::get(
5442 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
5443 auto *SizesArrayGbl = new llvm::GlobalVariable(
5444 CGM.getModule(), SizesArrayInit->getType(),
5445 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
5446 SizesArrayInit, ".offload_sizes");
5447 SizesArrayGbl->setUnnamedAddr(true);
5448 SizesArray = SizesArrayGbl;
5449 }
5450
5451 // The map types are always constant so we don't need to generate code to
5452 // fill arrays. Instead, we create an array constant.
5453 llvm::Constant *MapTypesArrayInit =
5454 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
5455 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
5456 CGM.getModule(), MapTypesArrayInit->getType(),
5457 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
5458 MapTypesArrayInit, ".offload_maptypes");
5459 MapTypesArrayGbl->setUnnamedAddr(true);
5460 MapTypesArray = MapTypesArrayGbl;
5461
5462 for (unsigned i = 0; i < PointerNumVal; ++i) {
5463 llvm::Value *BPVal = BasePointers[i];
5464 if (BPVal->getType()->isPointerTy())
5465 BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy);
5466 else {
5467 assert(BPVal->getType()->isIntegerTy() &&
5468 "If not a pointer, the value type must be an integer.");
5469 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy);
5470 }
5471 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
5472 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), BasePointersArray,
5473 0, i);
5474 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
5475 CGF.Builder.CreateStore(BPVal, BPAddr);
5476
5477 llvm::Value *PVal = Pointers[i];
5478 if (PVal->getType()->isPointerTy())
5479 PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy);
5480 else {
5481 assert(PVal->getType()->isIntegerTy() &&
5482 "If not a pointer, the value type must be an integer.");
5483 PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy);
5484 }
5485 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
5486 llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray, 0,
5487 i);
5488 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
5489 CGF.Builder.CreateStore(PVal, PAddr);
5490
5491 if (hasRuntimeEvaluationCaptureSize) {
5492 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
5493 llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
5494 /*Idx0=*/0,
5495 /*Idx1=*/i);
5496 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
5497 CGF.Builder.CreateStore(
5498 CGF.Builder.CreateIntCast(Sizes[i], CGM.SizeTy, /*isSigned=*/true),
5499 SAddr);
5500 }
5501 }
5502 }
5503}
5504/// \brief Emit the arguments to be passed to the runtime library based on the
5505/// arrays of pointers, sizes and map types.
5506static void emitOffloadingArraysArgument(
5507 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
5508 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
5509 llvm::Value *&MapTypesArrayArg, llvm::Value *BasePointersArray,
5510 llvm::Value *PointersArray, llvm::Value *SizesArray,
5511 llvm::Value *MapTypesArray, unsigned NumElems) {
5512 auto &CGM = CGF.CGM;
5513 if (NumElems) {
5514 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
5515 llvm::ArrayType::get(CGM.VoidPtrTy, NumElems), BasePointersArray,
5516 /*Idx0=*/0, /*Idx1=*/0);
5517 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
5518 llvm::ArrayType::get(CGM.VoidPtrTy, NumElems), PointersArray,
5519 /*Idx0=*/0,
5520 /*Idx1=*/0);
5521 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
5522 llvm::ArrayType::get(CGM.SizeTy, NumElems), SizesArray,
5523 /*Idx0=*/0, /*Idx1=*/0);
5524 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
5525 llvm::ArrayType::get(CGM.Int32Ty, NumElems), MapTypesArray,
5526 /*Idx0=*/0,
5527 /*Idx1=*/0);
5528 } else {
5529 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
5530 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
5531 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
5532 MapTypesArrayArg =
5533 llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo());
5534 }
Samuel Antao86ace552016-04-27 22:40:57 +00005535}
5536
Samuel Antaobed3c462015-10-02 16:14:20 +00005537void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
5538 const OMPExecutableDirective &D,
5539 llvm::Value *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00005540 llvm::Value *OutlinedFnID,
Samuel Antaobed3c462015-10-02 16:14:20 +00005541 const Expr *IfCond, const Expr *Device,
5542 ArrayRef<llvm::Value *> CapturedVars) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005543 if (!CGF.HaveInsertPoint())
5544 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00005545
Samuel Antaoee8fb302016-01-06 13:42:12 +00005546 assert(OutlinedFn && "Invalid outlined function!");
5547
Samuel Antao4af1b7b2015-12-02 17:44:43 +00005548 auto &Ctx = CGF.getContext();
5549
Samuel Antao86ace552016-04-27 22:40:57 +00005550 // Fill up the arrays with all the captured variables.
5551 MappableExprsHandler::MapValuesArrayTy KernelArgs;
5552 MappableExprsHandler::MapValuesArrayTy BasePointers;
5553 MappableExprsHandler::MapValuesArrayTy Pointers;
5554 MappableExprsHandler::MapValuesArrayTy Sizes;
5555 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobed3c462015-10-02 16:14:20 +00005556
Samuel Antao86ace552016-04-27 22:40:57 +00005557 MappableExprsHandler::MapValuesArrayTy CurBasePointers;
5558 MappableExprsHandler::MapValuesArrayTy CurPointers;
5559 MappableExprsHandler::MapValuesArrayTy CurSizes;
5560 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
5561
5562 // Get map clause information.
5563 MappableExprsHandler MCHandler(D, CGF);
Samuel Antaobed3c462015-10-02 16:14:20 +00005564
5565 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
5566 auto RI = CS.getCapturedRecordDecl()->field_begin();
Samuel Antaobed3c462015-10-02 16:14:20 +00005567 auto CV = CapturedVars.begin();
5568 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
5569 CE = CS.capture_end();
5570 CI != CE; ++CI, ++RI, ++CV) {
5571 StringRef Name;
5572 QualType Ty;
Samuel Antaobed3c462015-10-02 16:14:20 +00005573
Samuel Antao86ace552016-04-27 22:40:57 +00005574 CurBasePointers.clear();
5575 CurPointers.clear();
5576 CurSizes.clear();
5577 CurMapTypes.clear();
5578
5579 // VLA sizes are passed to the outlined region by copy and do not have map
5580 // information associated.
Samuel Antaobed3c462015-10-02 16:14:20 +00005581 if (CI->capturesVariableArrayType()) {
Samuel Antao86ace552016-04-27 22:40:57 +00005582 CurBasePointers.push_back(*CV);
5583 CurPointers.push_back(*CV);
5584 CurSizes.push_back(CGF.getTypeSize(RI->getType()));
Samuel Antao4af1b7b2015-12-02 17:44:43 +00005585 // Copy to the device as an argument. No need to retrieve it.
Samuel Antao6782e942016-05-26 16:48:10 +00005586 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_PRIVATE_VAL |
5587 MappableExprsHandler::OMP_MAP_FIRST_REF);
Samuel Antaobed3c462015-10-02 16:14:20 +00005588 } else {
Samuel Antao86ace552016-04-27 22:40:57 +00005589 // If we have any information in the map clause, we use it, otherwise we
5590 // just do a default mapping.
5591 MCHandler.generateInfoForCapture(CI, CurBasePointers, CurPointers,
5592 CurSizes, CurMapTypes);
Samuel Antaobed3c462015-10-02 16:14:20 +00005593
Samuel Antao86ace552016-04-27 22:40:57 +00005594 if (CurBasePointers.empty()) {
5595 // Do the default mapping.
5596 if (CI->capturesThis()) {
5597 CurBasePointers.push_back(*CV);
5598 CurPointers.push_back(*CV);
5599 const PointerType *PtrTy =
5600 cast<PointerType>(RI->getType().getTypePtr());
5601 CurSizes.push_back(CGF.getTypeSize(PtrTy->getPointeeType()));
5602 // Default map type.
5603 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_TO |
5604 MappableExprsHandler::OMP_MAP_FROM);
5605 } else if (CI->capturesVariableByCopy()) {
Samuel Antao86ace552016-04-27 22:40:57 +00005606 if (!RI->getType()->isAnyPointerType()) {
5607 // If the field is not a pointer, we need to save the actual value
Alexey Bataev7ace49d2016-05-17 08:55:33 +00005608 // and load it as a void pointer.
Samuel Antao6782e942016-05-26 16:48:10 +00005609 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_PRIVATE_VAL);
Samuel Antao86ace552016-04-27 22:40:57 +00005610 auto DstAddr = CGF.CreateMemTemp(
5611 Ctx.getUIntPtrType(),
5612 Twine(CI->getCapturedVar()->getName()) + ".casted");
5613 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
5614
5615 auto *SrcAddrVal = CGF.EmitScalarConversion(
5616 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
5617 Ctx.getPointerType(RI->getType()), SourceLocation());
5618 LValue SrcLV =
5619 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType());
5620
5621 // Store the value using the source type pointer.
5622 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV);
5623
5624 // Load the value using the destination type pointer.
5625 CurBasePointers.push_back(
5626 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal());
5627 CurPointers.push_back(CurBasePointers.back());
Samuel Antao6782e942016-05-26 16:48:10 +00005628
5629 // Get the size of the type to be used in the map.
5630 CurSizes.push_back(CGF.getTypeSize(RI->getType()));
Samuel Antao86ace552016-04-27 22:40:57 +00005631 } else {
Samuel Antao6782e942016-05-26 16:48:10 +00005632 // Pointers are implicitly mapped with a zero size and no flags
5633 // (other than first map that is added for all implicit maps).
5634 CurMapTypes.push_back(0u);
Samuel Antao86ace552016-04-27 22:40:57 +00005635 CurBasePointers.push_back(*CV);
5636 CurPointers.push_back(*CV);
Samuel Antao6782e942016-05-26 16:48:10 +00005637 CurSizes.push_back(llvm::Constant::getNullValue(CGM.SizeTy));
Samuel Antao86ace552016-04-27 22:40:57 +00005638 }
Samuel Antao86ace552016-04-27 22:40:57 +00005639 } else {
5640 assert(CI->capturesVariable() && "Expected captured reference.");
5641 CurBasePointers.push_back(*CV);
5642 CurPointers.push_back(*CV);
5643
5644 const ReferenceType *PtrTy =
5645 cast<ReferenceType>(RI->getType().getTypePtr());
5646 QualType ElementType = PtrTy->getPointeeType();
5647 CurSizes.push_back(CGF.getTypeSize(ElementType));
5648 // The default map type for a scalar/complex type is 'to' because by
5649 // default the value doesn't have to be retrieved. For an aggregate
Samuel Antao6782e942016-05-26 16:48:10 +00005650 // type, the default is 'tofrom'.
Samuel Antao86ace552016-04-27 22:40:57 +00005651 CurMapTypes.push_back(ElementType->isAggregateType()
5652 ? (MappableExprsHandler::OMP_MAP_TO |
5653 MappableExprsHandler::OMP_MAP_FROM)
5654 : MappableExprsHandler::OMP_MAP_TO);
5655 }
Samuel Antao6782e942016-05-26 16:48:10 +00005656 // Every default map produces a single argument, so, it is always the
5657 // first one.
5658 CurMapTypes.back() |= MappableExprsHandler::OMP_MAP_FIRST_REF;
Samuel Antao86ace552016-04-27 22:40:57 +00005659 }
Samuel Antaobed3c462015-10-02 16:14:20 +00005660 }
Samuel Antao86ace552016-04-27 22:40:57 +00005661 // We expect to have at least an element of information for this capture.
5662 assert(!CurBasePointers.empty() && "Non-existing map pointer for capture!");
5663 assert(CurBasePointers.size() == CurPointers.size() &&
5664 CurBasePointers.size() == CurSizes.size() &&
5665 CurBasePointers.size() == CurMapTypes.size() &&
5666 "Inconsistent map information sizes!");
Samuel Antaobed3c462015-10-02 16:14:20 +00005667
Samuel Antao86ace552016-04-27 22:40:57 +00005668 // The kernel args are always the first elements of the base pointers
5669 // associated with a capture.
5670 KernelArgs.push_back(CurBasePointers.front());
5671 // We need to append the results of this capture to what we already have.
5672 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
5673 Pointers.append(CurPointers.begin(), CurPointers.end());
5674 Sizes.append(CurSizes.begin(), CurSizes.end());
5675 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
Samuel Antaobed3c462015-10-02 16:14:20 +00005676 }
5677
5678 // Keep track on whether the host function has to be executed.
5679 auto OffloadErrorQType =
Samuel Antao4af1b7b2015-12-02 17:44:43 +00005680 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00005681 auto OffloadError = CGF.MakeAddrLValue(
5682 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
5683 OffloadErrorQType);
5684 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
5685 OffloadError);
5686
5687 // Fill up the pointer arrays and transfer execution to the device.
Samuel Antaodf158d52016-04-27 22:58:19 +00005688 auto &&ThenGen = [&Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes, Device,
5689 OutlinedFnID, OffloadError, OffloadErrorQType,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005690 &D](CodeGenFunction &CGF, PrePostActionTy &) {
5691 auto &RT = CGF.CGM.getOpenMPRuntime();
Samuel Antaodf158d52016-04-27 22:58:19 +00005692 // Emit the offloading arrays.
Samuel Antaobed3c462015-10-02 16:14:20 +00005693 llvm::Value *BasePointersArray;
5694 llvm::Value *PointersArray;
5695 llvm::Value *SizesArray;
5696 llvm::Value *MapTypesArray;
Samuel Antaodf158d52016-04-27 22:58:19 +00005697 emitOffloadingArrays(CGF, BasePointersArray, PointersArray, SizesArray,
5698 MapTypesArray, BasePointers, Pointers, Sizes,
5699 MapTypes);
5700 emitOffloadingArraysArgument(CGF, BasePointersArray, PointersArray,
5701 SizesArray, MapTypesArray, BasePointersArray,
5702 PointersArray, SizesArray, MapTypesArray,
5703 BasePointers.size());
Samuel Antaobed3c462015-10-02 16:14:20 +00005704
5705 // On top of the arrays that were filled up, the target offloading call
5706 // takes as arguments the device id as well as the host pointer. The host
5707 // pointer is used by the runtime library to identify the current target
5708 // region, so it only has to be unique and not necessarily point to
5709 // anything. It could be the pointer to the outlined function that
5710 // implements the target region, but we aren't using that so that the
5711 // compiler doesn't need to keep that, and could therefore inline the host
5712 // function if proven worthwhile during optimization.
5713
Samuel Antaoee8fb302016-01-06 13:42:12 +00005714 // From this point on, we need to have an ID of the target region defined.
5715 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00005716
5717 // Emit device ID if any.
5718 llvm::Value *DeviceID;
5719 if (Device)
5720 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005721 CGF.Int32Ty, /*isSigned=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00005722 else
5723 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
5724
Samuel Antaodf158d52016-04-27 22:58:19 +00005725 // Emit the number of elements in the offloading arrays.
5726 llvm::Value *PointerNum = CGF.Builder.getInt32(BasePointers.size());
5727
Samuel Antaob68e2db2016-03-03 16:20:23 +00005728 // Return value of the runtime offloading call.
5729 llvm::Value *Return;
5730
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005731 auto *NumTeams = emitNumTeamsClauseForTargetDirective(RT, CGF, D);
5732 auto *ThreadLimit = emitThreadLimitClauseForTargetDirective(RT, CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00005733
5734 // If we have NumTeams defined this means that we have an enclosed teams
5735 // region. Therefore we also expect to have ThreadLimit defined. These two
5736 // values should be defined in the presence of a teams directive, regardless
5737 // of having any clauses associated. If the user is using teams but no
5738 // clauses, these two values will be the default that should be passed to
5739 // the runtime library - a 32-bit integer with the value zero.
5740 if (NumTeams) {
5741 assert(ThreadLimit && "Thread limit expression should be available along "
5742 "with number of teams.");
5743 llvm::Value *OffloadingArgs[] = {
5744 DeviceID, OutlinedFnID, PointerNum,
5745 BasePointersArray, PointersArray, SizesArray,
5746 MapTypesArray, NumTeams, ThreadLimit};
5747 Return = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005748 RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00005749 } else {
5750 llvm::Value *OffloadingArgs[] = {
5751 DeviceID, OutlinedFnID, PointerNum, BasePointersArray,
5752 PointersArray, SizesArray, MapTypesArray};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005753 Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target),
Samuel Antaob68e2db2016-03-03 16:20:23 +00005754 OffloadingArgs);
5755 }
Samuel Antaobed3c462015-10-02 16:14:20 +00005756
5757 CGF.EmitStoreOfScalar(Return, OffloadError);
5758 };
5759
Samuel Antaoee8fb302016-01-06 13:42:12 +00005760 // Notify that the host version must be executed.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005761 auto &&ElseGen = [OffloadError](CodeGenFunction &CGF, PrePostActionTy &) {
5762 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/-1u),
Samuel Antaoee8fb302016-01-06 13:42:12 +00005763 OffloadError);
5764 };
5765
5766 // If we have a target function ID it means that we need to support
5767 // offloading, otherwise, just execute on the host. We need to execute on host
5768 // regardless of the conditional in the if clause if, e.g., the user do not
5769 // specify target triples.
5770 if (OutlinedFnID) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005771 if (IfCond)
Samuel Antaoee8fb302016-01-06 13:42:12 +00005772 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005773 else {
5774 RegionCodeGenTy ThenRCG(ThenGen);
5775 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005776 }
5777 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005778 RegionCodeGenTy ElseRCG(ElseGen);
5779 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005780 }
Samuel Antaobed3c462015-10-02 16:14:20 +00005781
5782 // Check the error code and execute the host version if required.
5783 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
5784 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
5785 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
5786 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
5787 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
5788
5789 CGF.EmitBlock(OffloadFailedBlock);
Samuel Antao86ace552016-04-27 22:40:57 +00005790 CGF.Builder.CreateCall(OutlinedFn, KernelArgs);
Samuel Antaobed3c462015-10-02 16:14:20 +00005791 CGF.EmitBranch(OffloadContBlock);
5792
5793 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00005794}
Samuel Antaoee8fb302016-01-06 13:42:12 +00005795
5796void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
5797 StringRef ParentName) {
5798 if (!S)
5799 return;
5800
5801 // If we find a OMP target directive, codegen the outline function and
5802 // register the result.
5803 // FIXME: Add other directives with target when they become supported.
5804 bool isTargetDirective = isa<OMPTargetDirective>(S);
5805
5806 if (isTargetDirective) {
5807 auto *E = cast<OMPExecutableDirective>(S);
5808 unsigned DeviceID;
5809 unsigned FileID;
5810 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00005811 getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00005812 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00005813
5814 // Is this a target region that should not be emitted as an entry point? If
5815 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00005816 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
5817 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00005818 return;
5819
5820 llvm::Function *Fn;
5821 llvm::Constant *Addr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005822 std::tie(Fn, Addr) =
5823 CodeGenFunction::EmitOMPTargetDirectiveOutlinedFunction(
5824 CGM, cast<OMPTargetDirective>(*E), ParentName,
5825 /*isOffloadEntry=*/true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00005826 assert(Fn && Addr && "Target region emission failed.");
5827 return;
5828 }
5829
5830 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) {
Samuel Antaoe49645c2016-05-08 06:43:56 +00005831 if (!E->hasAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00005832 return;
5833
5834 scanForTargetRegionsFunctions(
5835 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(),
5836 ParentName);
5837 return;
5838 }
5839
5840 // If this is a lambda function, look into its body.
5841 if (auto *L = dyn_cast<LambdaExpr>(S))
5842 S = L->getBody();
5843
5844 // Keep looking for target regions recursively.
5845 for (auto *II : S->children())
5846 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00005847}
5848
5849bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
5850 auto &FD = *cast<FunctionDecl>(GD.getDecl());
5851
5852 // If emitting code for the host, we do not process FD here. Instead we do
5853 // the normal code generation.
5854 if (!CGM.getLangOpts().OpenMPIsDevice)
5855 return false;
5856
5857 // Try to detect target regions in the function.
5858 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
5859
5860 // We should not emit any function othen that the ones created during the
5861 // scanning. Therefore, we signal that this function is completely dealt
5862 // with.
5863 return true;
5864}
5865
5866bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
5867 if (!CGM.getLangOpts().OpenMPIsDevice)
5868 return false;
5869
5870 // Check if there are Ctors/Dtors in this declaration and look for target
5871 // regions in it. We use the complete variant to produce the kernel name
5872 // mangling.
5873 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
5874 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
5875 for (auto *Ctor : RD->ctors()) {
5876 StringRef ParentName =
5877 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
5878 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
5879 }
5880 auto *Dtor = RD->getDestructor();
5881 if (Dtor) {
5882 StringRef ParentName =
5883 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
5884 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
5885 }
5886 }
5887
5888 // If we are in target mode we do not emit any global (declare target is not
5889 // implemented yet). Therefore we signal that GD was processed in this case.
5890 return true;
5891}
5892
5893bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
5894 auto *VD = GD.getDecl();
5895 if (isa<FunctionDecl>(VD))
5896 return emitTargetFunctions(GD);
5897
5898 return emitTargetGlobalVariable(GD);
5899}
5900
5901llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
5902 // If we have offloading in the current module, we need to emit the entries
5903 // now and register the offloading descriptor.
5904 createOffloadEntriesAndInfoMetadata();
5905
5906 // Create and register the offloading binary descriptors. This is the main
5907 // entity that captures all the information about offloading in the current
5908 // compilation unit.
5909 return createOffloadingBinaryDescriptorRegistration();
5910}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00005911
5912void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
5913 const OMPExecutableDirective &D,
5914 SourceLocation Loc,
5915 llvm::Value *OutlinedFn,
5916 ArrayRef<llvm::Value *> CapturedVars) {
5917 if (!CGF.HaveInsertPoint())
5918 return;
5919
5920 auto *RTLoc = emitUpdateLocation(CGF, Loc);
5921 CodeGenFunction::RunCleanupsScope Scope(CGF);
5922
5923 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
5924 llvm::Value *Args[] = {
5925 RTLoc,
5926 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
5927 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
5928 llvm::SmallVector<llvm::Value *, 16> RealArgs;
5929 RealArgs.append(std::begin(Args), std::end(Args));
5930 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
5931
5932 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
5933 CGF.EmitRuntimeCall(RTLFn, RealArgs);
5934}
5935
5936void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00005937 const Expr *NumTeams,
5938 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00005939 SourceLocation Loc) {
5940 if (!CGF.HaveInsertPoint())
5941 return;
5942
5943 auto *RTLoc = emitUpdateLocation(CGF, Loc);
5944
Carlo Bertollic6872252016-04-04 15:55:02 +00005945 llvm::Value *NumTeamsVal =
5946 (NumTeams)
5947 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
5948 CGF.CGM.Int32Ty, /* isSigned = */ true)
5949 : CGF.Builder.getInt32(0);
5950
5951 llvm::Value *ThreadLimitVal =
5952 (ThreadLimit)
5953 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
5954 CGF.CGM.Int32Ty, /* isSigned = */ true)
5955 : CGF.Builder.getInt32(0);
5956
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00005957 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00005958 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
5959 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00005960 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
5961 PushNumTeamsArgs);
5962}
Samuel Antaodf158d52016-04-27 22:58:19 +00005963
5964void CGOpenMPRuntime::emitTargetDataCalls(CodeGenFunction &CGF,
5965 const OMPExecutableDirective &D,
5966 const Expr *IfCond,
5967 const Expr *Device,
5968 const RegionCodeGenTy &CodeGen) {
5969
5970 if (!CGF.HaveInsertPoint())
5971 return;
5972
5973 llvm::Value *BasePointersArray = nullptr;
5974 llvm::Value *PointersArray = nullptr;
5975 llvm::Value *SizesArray = nullptr;
5976 llvm::Value *MapTypesArray = nullptr;
5977 unsigned NumOfPtrs = 0;
5978
5979 // Generate the code for the opening of the data environment. Capture all the
5980 // arguments of the runtime call by reference because they are used in the
5981 // closing of the region.
5982 auto &&BeginThenGen = [&D, &CGF, &BasePointersArray, &PointersArray,
5983 &SizesArray, &MapTypesArray, Device,
5984 &NumOfPtrs](CodeGenFunction &CGF, PrePostActionTy &) {
5985 // Fill up the arrays with all the mapped variables.
5986 MappableExprsHandler::MapValuesArrayTy BasePointers;
5987 MappableExprsHandler::MapValuesArrayTy Pointers;
5988 MappableExprsHandler::MapValuesArrayTy Sizes;
5989 MappableExprsHandler::MapFlagsArrayTy MapTypes;
5990
5991 // Get map clause information.
5992 MappableExprsHandler MCHandler(D, CGF);
5993 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
5994 NumOfPtrs = BasePointers.size();
5995
5996 // Fill up the arrays and create the arguments.
5997 emitOffloadingArrays(CGF, BasePointersArray, PointersArray, SizesArray,
5998 MapTypesArray, BasePointers, Pointers, Sizes,
5999 MapTypes);
6000
6001 llvm::Value *BasePointersArrayArg = nullptr;
6002 llvm::Value *PointersArrayArg = nullptr;
6003 llvm::Value *SizesArrayArg = nullptr;
6004 llvm::Value *MapTypesArrayArg = nullptr;
6005 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
6006 SizesArrayArg, MapTypesArrayArg,
6007 BasePointersArray, PointersArray, SizesArray,
6008 MapTypesArray, NumOfPtrs);
6009
6010 // Emit device ID if any.
6011 llvm::Value *DeviceID = nullptr;
6012 if (Device)
6013 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
6014 CGF.Int32Ty, /*isSigned=*/true);
6015 else
6016 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
6017
6018 // Emit the number of elements in the offloading arrays.
6019 auto *PointerNum = CGF.Builder.getInt32(NumOfPtrs);
6020
6021 llvm::Value *OffloadingArgs[] = {
6022 DeviceID, PointerNum, BasePointersArrayArg,
6023 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
6024 auto &RT = CGF.CGM.getOpenMPRuntime();
6025 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target_data_begin),
6026 OffloadingArgs);
6027 };
6028
6029 // Generate code for the closing of the data region.
6030 auto &&EndThenGen = [&CGF, &BasePointersArray, &PointersArray, &SizesArray,
6031 &MapTypesArray, Device,
6032 &NumOfPtrs](CodeGenFunction &CGF, PrePostActionTy &) {
6033 assert(BasePointersArray && PointersArray && SizesArray && MapTypesArray &&
6034 NumOfPtrs && "Invalid data environment closing arguments.");
6035
6036 llvm::Value *BasePointersArrayArg = nullptr;
6037 llvm::Value *PointersArrayArg = nullptr;
6038 llvm::Value *SizesArrayArg = nullptr;
6039 llvm::Value *MapTypesArrayArg = nullptr;
6040 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
6041 SizesArrayArg, MapTypesArrayArg,
6042 BasePointersArray, PointersArray, SizesArray,
6043 MapTypesArray, NumOfPtrs);
6044
6045 // Emit device ID if any.
6046 llvm::Value *DeviceID = nullptr;
6047 if (Device)
6048 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
6049 CGF.Int32Ty, /*isSigned=*/true);
6050 else
6051 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
6052
6053 // Emit the number of elements in the offloading arrays.
6054 auto *PointerNum = CGF.Builder.getInt32(NumOfPtrs);
6055
6056 llvm::Value *OffloadingArgs[] = {
6057 DeviceID, PointerNum, BasePointersArrayArg,
6058 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
6059 auto &RT = CGF.CGM.getOpenMPRuntime();
6060 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target_data_end),
6061 OffloadingArgs);
6062 };
6063
6064 // In the event we get an if clause, we don't have to take any action on the
6065 // else side.
6066 auto &&ElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
6067
6068 if (IfCond) {
6069 emitOMPIfClause(CGF, IfCond, BeginThenGen, ElseGen);
6070 } else {
6071 RegionCodeGenTy BeginThenRCG(BeginThenGen);
6072 BeginThenRCG(CGF);
6073 }
6074
6075 CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data, CodeGen);
6076
6077 if (IfCond) {
6078 emitOMPIfClause(CGF, IfCond, EndThenGen, ElseGen);
6079 } else {
6080 RegionCodeGenTy EndThenRCG(EndThenGen);
6081 EndThenRCG(CGF);
6082 }
6083}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00006084
Samuel Antao8dd66282016-04-27 23:14:30 +00006085void CGOpenMPRuntime::emitTargetEnterOrExitDataCall(
6086 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
6087 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00006088 if (!CGF.HaveInsertPoint())
6089 return;
6090
Samuel Antao8dd66282016-04-27 23:14:30 +00006091 assert((isa<OMPTargetEnterDataDirective>(D) ||
6092 isa<OMPTargetExitDataDirective>(D)) &&
6093 "Expecting either target enter or exit data directives.");
6094
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00006095 // Generate the code for the opening of the data environment.
6096 auto &&ThenGen = [&D, &CGF, Device](CodeGenFunction &CGF, PrePostActionTy &) {
6097 // Fill up the arrays with all the mapped variables.
6098 MappableExprsHandler::MapValuesArrayTy BasePointers;
6099 MappableExprsHandler::MapValuesArrayTy Pointers;
6100 MappableExprsHandler::MapValuesArrayTy Sizes;
6101 MappableExprsHandler::MapFlagsArrayTy MapTypes;
6102
6103 // Get map clause information.
6104 MappableExprsHandler MCHandler(D, CGF);
6105 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
6106
6107 llvm::Value *BasePointersArrayArg = nullptr;
6108 llvm::Value *PointersArrayArg = nullptr;
6109 llvm::Value *SizesArrayArg = nullptr;
6110 llvm::Value *MapTypesArrayArg = nullptr;
6111
6112 // Fill up the arrays and create the arguments.
6113 emitOffloadingArrays(CGF, BasePointersArrayArg, PointersArrayArg,
6114 SizesArrayArg, MapTypesArrayArg, BasePointers,
6115 Pointers, Sizes, MapTypes);
6116 emitOffloadingArraysArgument(
6117 CGF, BasePointersArrayArg, PointersArrayArg, SizesArrayArg,
6118 MapTypesArrayArg, BasePointersArrayArg, PointersArrayArg, SizesArrayArg,
6119 MapTypesArrayArg, BasePointers.size());
6120
6121 // Emit device ID if any.
6122 llvm::Value *DeviceID = nullptr;
6123 if (Device)
6124 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
6125 CGF.Int32Ty, /*isSigned=*/true);
6126 else
6127 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
6128
6129 // Emit the number of elements in the offloading arrays.
6130 auto *PointerNum = CGF.Builder.getInt32(BasePointers.size());
6131
6132 llvm::Value *OffloadingArgs[] = {
6133 DeviceID, PointerNum, BasePointersArrayArg,
6134 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
6135 auto &RT = CGF.CGM.getOpenMPRuntime();
Samuel Antao8dd66282016-04-27 23:14:30 +00006136 CGF.EmitRuntimeCall(
6137 RT.createRuntimeFunction(isa<OMPTargetEnterDataDirective>(D)
6138 ? OMPRTL__tgt_target_data_begin
6139 : OMPRTL__tgt_target_data_end),
6140 OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00006141 };
6142
6143 // In the event we get an if clause, we don't have to take any action on the
6144 // else side.
6145 auto &&ElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
6146
6147 if (IfCond) {
6148 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
6149 } else {
6150 RegionCodeGenTy ThenGenRCG(ThenGen);
6151 ThenGenRCG(CGF);
6152 }
6153}
Alexey Bataevc7a82b42016-05-06 09:40:08 +00006154
6155namespace {
6156 /// Kind of parameter in a function with 'declare simd' directive.
6157 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
6158 /// Attribute set of the parameter.
6159 struct ParamAttrTy {
6160 ParamKindTy Kind = Vector;
6161 llvm::APSInt StrideOrArg;
6162 llvm::APSInt Alignment;
6163 };
6164} // namespace
6165
6166static unsigned evaluateCDTSize(const FunctionDecl *FD,
6167 ArrayRef<ParamAttrTy> ParamAttrs) {
6168 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
6169 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
6170 // of that clause. The VLEN value must be power of 2.
6171 // In other case the notion of the function`s "characteristic data type" (CDT)
6172 // is used to compute the vector length.
6173 // CDT is defined in the following order:
6174 // a) For non-void function, the CDT is the return type.
6175 // b) If the function has any non-uniform, non-linear parameters, then the
6176 // CDT is the type of the first such parameter.
6177 // c) If the CDT determined by a) or b) above is struct, union, or class
6178 // type which is pass-by-value (except for the type that maps to the
6179 // built-in complex data type), the characteristic data type is int.
6180 // d) If none of the above three cases is applicable, the CDT is int.
6181 // The VLEN is then determined based on the CDT and the size of vector
6182 // register of that ISA for which current vector version is generated. The
6183 // VLEN is computed using the formula below:
6184 // VLEN = sizeof(vector_register) / sizeof(CDT),
6185 // where vector register size specified in section 3.2.1 Registers and the
6186 // Stack Frame of original AMD64 ABI document.
6187 QualType RetType = FD->getReturnType();
6188 if (RetType.isNull())
6189 return 0;
6190 ASTContext &C = FD->getASTContext();
6191 QualType CDT;
6192 if (!RetType.isNull() && !RetType->isVoidType())
6193 CDT = RetType;
6194 else {
6195 unsigned Offset = 0;
6196 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
6197 if (ParamAttrs[Offset].Kind == Vector)
6198 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
6199 ++Offset;
6200 }
6201 if (CDT.isNull()) {
6202 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
6203 if (ParamAttrs[I + Offset].Kind == Vector) {
6204 CDT = FD->getParamDecl(I)->getType();
6205 break;
6206 }
6207 }
6208 }
6209 }
6210 if (CDT.isNull())
6211 CDT = C.IntTy;
6212 CDT = CDT->getCanonicalTypeUnqualified();
6213 if (CDT->isRecordType() || CDT->isUnionType())
6214 CDT = C.IntTy;
6215 return C.getTypeSize(CDT);
6216}
6217
6218static void
6219emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
6220 llvm::APSInt VLENVal,
6221 ArrayRef<ParamAttrTy> ParamAttrs,
6222 OMPDeclareSimdDeclAttr::BranchStateTy State) {
6223 struct ISADataTy {
6224 char ISA;
6225 unsigned VecRegSize;
6226 };
6227 ISADataTy ISAData[] = {
6228 {
6229 'b', 128
6230 }, // SSE
6231 {
6232 'c', 256
6233 }, // AVX
6234 {
6235 'd', 256
6236 }, // AVX2
6237 {
6238 'e', 512
6239 }, // AVX512
6240 };
6241 llvm::SmallVector<char, 2> Masked;
6242 switch (State) {
6243 case OMPDeclareSimdDeclAttr::BS_Undefined:
6244 Masked.push_back('N');
6245 Masked.push_back('M');
6246 break;
6247 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
6248 Masked.push_back('N');
6249 break;
6250 case OMPDeclareSimdDeclAttr::BS_Inbranch:
6251 Masked.push_back('M');
6252 break;
6253 }
6254 for (auto Mask : Masked) {
6255 for (auto &Data : ISAData) {
6256 SmallString<256> Buffer;
6257 llvm::raw_svector_ostream Out(Buffer);
6258 Out << "_ZGV" << Data.ISA << Mask;
6259 if (!VLENVal) {
6260 Out << llvm::APSInt::getUnsigned(Data.VecRegSize /
6261 evaluateCDTSize(FD, ParamAttrs));
6262 } else
6263 Out << VLENVal;
6264 for (auto &ParamAttr : ParamAttrs) {
6265 switch (ParamAttr.Kind){
6266 case LinearWithVarStride:
6267 Out << 's' << ParamAttr.StrideOrArg;
6268 break;
6269 case Linear:
6270 Out << 'l';
6271 if (!!ParamAttr.StrideOrArg)
6272 Out << ParamAttr.StrideOrArg;
6273 break;
6274 case Uniform:
6275 Out << 'u';
6276 break;
6277 case Vector:
6278 Out << 'v';
6279 break;
6280 }
6281 if (!!ParamAttr.Alignment)
6282 Out << 'a' << ParamAttr.Alignment;
6283 }
6284 Out << '_' << Fn->getName();
6285 Fn->addFnAttr(Out.str());
6286 }
6287 }
6288}
6289
6290void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
6291 llvm::Function *Fn) {
6292 ASTContext &C = CGM.getContext();
6293 FD = FD->getCanonicalDecl();
6294 // Map params to their positions in function decl.
6295 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
6296 if (isa<CXXMethodDecl>(FD))
6297 ParamPositions.insert({FD, 0});
6298 unsigned ParamPos = ParamPositions.size();
6299 for (auto *P : FD->params()) {
6300 ParamPositions.insert({P->getCanonicalDecl(), ParamPos});
6301 ++ParamPos;
6302 }
6303 for (auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
6304 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
6305 // Mark uniform parameters.
6306 for (auto *E : Attr->uniforms()) {
6307 E = E->IgnoreParenImpCasts();
6308 unsigned Pos;
6309 if (isa<CXXThisExpr>(E))
6310 Pos = ParamPositions[FD];
6311 else {
6312 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
6313 ->getCanonicalDecl();
6314 Pos = ParamPositions[PVD];
6315 }
6316 ParamAttrs[Pos].Kind = Uniform;
6317 }
6318 // Get alignment info.
6319 auto NI = Attr->alignments_begin();
6320 for (auto *E : Attr->aligneds()) {
6321 E = E->IgnoreParenImpCasts();
6322 unsigned Pos;
6323 QualType ParmTy;
6324 if (isa<CXXThisExpr>(E)) {
6325 Pos = ParamPositions[FD];
6326 ParmTy = E->getType();
6327 } else {
6328 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
6329 ->getCanonicalDecl();
6330 Pos = ParamPositions[PVD];
6331 ParmTy = PVD->getType();
6332 }
6333 ParamAttrs[Pos].Alignment =
6334 (*NI) ? (*NI)->EvaluateKnownConstInt(C)
6335 : llvm::APSInt::getUnsigned(
6336 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
6337 .getQuantity());
6338 ++NI;
6339 }
6340 // Mark linear parameters.
6341 auto SI = Attr->steps_begin();
6342 auto MI = Attr->modifiers_begin();
6343 for (auto *E : Attr->linears()) {
6344 E = E->IgnoreParenImpCasts();
6345 unsigned Pos;
6346 if (isa<CXXThisExpr>(E))
6347 Pos = ParamPositions[FD];
6348 else {
6349 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
6350 ->getCanonicalDecl();
6351 Pos = ParamPositions[PVD];
6352 }
6353 auto &ParamAttr = ParamAttrs[Pos];
6354 ParamAttr.Kind = Linear;
6355 if (*SI) {
6356 if (!(*SI)->EvaluateAsInt(ParamAttr.StrideOrArg, C,
6357 Expr::SE_AllowSideEffects)) {
6358 if (auto *DRE = cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
6359 if (auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
6360 ParamAttr.Kind = LinearWithVarStride;
6361 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
6362 ParamPositions[StridePVD->getCanonicalDecl()]);
6363 }
6364 }
6365 }
6366 }
6367 ++SI;
6368 ++MI;
6369 }
6370 llvm::APSInt VLENVal;
6371 if (const Expr *VLEN = Attr->getSimdlen())
6372 VLENVal = VLEN->EvaluateKnownConstInt(C);
6373 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
6374 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
6375 CGM.getTriple().getArch() == llvm::Triple::x86_64)
6376 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
6377 }
6378}
Alexey Bataev8b427062016-05-25 12:36:08 +00006379
6380namespace {
6381/// Cleanup action for doacross support.
6382class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
6383public:
6384 static const int DoacrossFinArgs = 2;
6385
6386private:
6387 llvm::Value *RTLFn;
6388 llvm::Value *Args[DoacrossFinArgs];
6389
6390public:
6391 DoacrossCleanupTy(llvm::Value *RTLFn, ArrayRef<llvm::Value *> CallArgs)
6392 : RTLFn(RTLFn) {
6393 assert(CallArgs.size() == DoacrossFinArgs);
6394 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
6395 }
6396 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
6397 if (!CGF.HaveInsertPoint())
6398 return;
6399 CGF.EmitRuntimeCall(RTLFn, Args);
6400 }
6401};
6402} // namespace
6403
6404void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
6405 const OMPLoopDirective &D) {
6406 if (!CGF.HaveInsertPoint())
6407 return;
6408
6409 ASTContext &C = CGM.getContext();
6410 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
6411 RecordDecl *RD;
6412 if (KmpDimTy.isNull()) {
6413 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
6414 // kmp_int64 lo; // lower
6415 // kmp_int64 up; // upper
6416 // kmp_int64 st; // stride
6417 // };
6418 RD = C.buildImplicitRecord("kmp_dim");
6419 RD->startDefinition();
6420 addFieldToRecordDecl(C, RD, Int64Ty);
6421 addFieldToRecordDecl(C, RD, Int64Ty);
6422 addFieldToRecordDecl(C, RD, Int64Ty);
6423 RD->completeDefinition();
6424 KmpDimTy = C.getRecordType(RD);
6425 } else
6426 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
6427
6428 Address DimsAddr = CGF.CreateMemTemp(KmpDimTy, "dims");
6429 CGF.EmitNullInitialization(DimsAddr, KmpDimTy);
6430 enum { LowerFD = 0, UpperFD, StrideFD };
6431 // Fill dims with data.
6432 LValue DimsLVal = CGF.MakeAddrLValue(DimsAddr, KmpDimTy);
6433 // dims.upper = num_iterations;
6434 LValue UpperLVal =
6435 CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), UpperFD));
6436 llvm::Value *NumIterVal = CGF.EmitScalarConversion(
6437 CGF.EmitScalarExpr(D.getNumIterations()), D.getNumIterations()->getType(),
6438 Int64Ty, D.getNumIterations()->getExprLoc());
6439 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
6440 // dims.stride = 1;
6441 LValue StrideLVal =
6442 CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), StrideFD));
6443 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
6444 StrideLVal);
6445
6446 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
6447 // kmp_int32 num_dims, struct kmp_dim * dims);
6448 llvm::Value *Args[] = {emitUpdateLocation(CGF, D.getLocStart()),
6449 getThreadID(CGF, D.getLocStart()),
6450 llvm::ConstantInt::getSigned(CGM.Int32Ty, 1),
6451 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6452 DimsAddr.getPointer(), CGM.VoidPtrTy)};
6453
6454 llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_init);
6455 CGF.EmitRuntimeCall(RTLFn, Args);
6456 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
6457 emitUpdateLocation(CGF, D.getLocEnd()), getThreadID(CGF, D.getLocEnd())};
6458 llvm::Value *FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
6459 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
6460 llvm::makeArrayRef(FiniArgs));
6461}
6462
6463void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
6464 const OMPDependClause *C) {
6465 QualType Int64Ty =
6466 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
6467 const Expr *CounterVal = C->getCounterValue();
6468 assert(CounterVal);
6469 llvm::Value *CntVal = CGF.EmitScalarConversion(CGF.EmitScalarExpr(CounterVal),
6470 CounterVal->getType(), Int64Ty,
6471 CounterVal->getExprLoc());
6472 Address CntAddr = CGF.CreateMemTemp(Int64Ty, ".cnt.addr");
6473 CGF.EmitStoreOfScalar(CntVal, CntAddr, /*Volatile=*/false, Int64Ty);
6474 llvm::Value *Args[] = {emitUpdateLocation(CGF, C->getLocStart()),
6475 getThreadID(CGF, C->getLocStart()),
6476 CntAddr.getPointer()};
6477 llvm::Value *RTLFn;
6478 if (C->getDependencyKind() == OMPC_DEPEND_source)
6479 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
6480 else {
6481 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
6482 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
6483 }
6484 CGF.EmitRuntimeCall(RTLFn, Args);
6485}
6486