blob: f732131bf5b0b789077c1bd6f007d04182219a4c [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides a class for OpenMP runtime code generation.
11//
12//===----------------------------------------------------------------------===//
13
Samuel Antaoee8fb302016-01-06 13:42:12 +000014#include "CGCXXABI.h"
15#include "CGCleanup.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000016#include "CGOpenMPRuntime.h"
17#include "CodeGenFunction.h"
18#include "clang/AST/Decl.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000019#include "clang/AST/StmtOpenMP.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000020#include "llvm/ADT/ArrayRef.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000021#include "llvm/Bitcode/ReaderWriter.h"
Alexey Bataevd74d0602014-10-13 06:02:40 +000022#include "llvm/IR/CallSite.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000023#include "llvm/IR/DerivedTypes.h"
24#include "llvm/IR/GlobalValue.h"
25#include "llvm/IR/Value.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000026#include "llvm/Support/Format.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000027#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000028#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000029
30using namespace clang;
31using namespace CodeGen;
32
Benjamin Kramerc52193f2014-10-10 13:57:57 +000033namespace {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000034/// \brief Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000035class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
36public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000037 /// \brief Kinds of OpenMP regions used in codegen.
38 enum CGOpenMPRegionKind {
39 /// \brief Region with outlined function for standalone 'parallel'
40 /// directive.
41 ParallelOutlinedRegion,
42 /// \brief Region with outlined function for standalone 'task' directive.
43 TaskOutlinedRegion,
44 /// \brief Region for constructs that do not require function outlining,
45 /// like 'for', 'sections', 'atomic' etc. directives.
46 InlinedRegion,
Samuel Antaobed3c462015-10-02 16:14:20 +000047 /// \brief Region with outlined function for standalone 'target' directive.
48 TargetRegion,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000049 };
Alexey Bataev18095712014-10-10 12:19:54 +000050
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000051 CGOpenMPRegionInfo(const CapturedStmt &CS,
52 const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000053 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
54 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000055 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000056 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000057
58 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000059 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
60 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000061 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000062 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000063
64 /// \brief Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000065 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000066 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000067
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000068 /// \brief Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000069 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000070
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000071 /// \brief Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000072 /// \return LValue for thread id variable. This LValue always has type int32*.
73 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000074
Alexey Bataev48591dd2016-04-20 04:01:36 +000075 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
76
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000077 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000078
Alexey Bataev81c7ea02015-07-03 09:56:58 +000079 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
80
Alexey Bataev25e5b442015-09-15 12:52:43 +000081 bool hasCancel() const { return HasCancel; }
82
Alexey Bataev18095712014-10-10 12:19:54 +000083 static bool classof(const CGCapturedStmtInfo *Info) {
84 return Info->getKind() == CR_OpenMP;
85 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000086
Alexey Bataev48591dd2016-04-20 04:01:36 +000087 ~CGOpenMPRegionInfo() override = default;
88
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000089protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000090 CGOpenMPRegionKind RegionKind;
Hans Wennborg45c74392016-01-12 20:54:36 +000091 RegionCodeGenTy CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000092 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +000093 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000094};
Alexey Bataev18095712014-10-10 12:19:54 +000095
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000096/// \brief API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +000097class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000098public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000099 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000100 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000101 OpenMPDirectiveKind Kind, bool HasCancel)
102 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
103 HasCancel),
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000104 ThreadIDVar(ThreadIDVar) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000105 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
106 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000107
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000108 /// \brief Get a variable or parameter for storing global thread id
109 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000110 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000111
Alexey Bataev18095712014-10-10 12:19:54 +0000112 /// \brief Get the name of the capture helper.
Benjamin Kramerc52193f2014-10-10 13:57:57 +0000113 StringRef getHelperName() const override { return ".omp_outlined."; }
Alexey Bataev18095712014-10-10 12:19:54 +0000114
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000115 static bool classof(const CGCapturedStmtInfo *Info) {
116 return CGOpenMPRegionInfo::classof(Info) &&
117 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
118 ParallelOutlinedRegion;
119 }
120
Alexey Bataev18095712014-10-10 12:19:54 +0000121private:
122 /// \brief A variable or parameter storing global thread id for OpenMP
123 /// constructs.
124 const VarDecl *ThreadIDVar;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000125};
126
Alexey Bataev62b63b12015-03-10 07:28:44 +0000127/// \brief API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000128class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000129public:
Alexey Bataev48591dd2016-04-20 04:01:36 +0000130 class UntiedTaskActionTy final : public PrePostActionTy {
131 bool Untied;
132 const VarDecl *PartIDVar;
133 const RegionCodeGenTy UntiedCodeGen;
134 llvm::SwitchInst *UntiedSwitch = nullptr;
135
136 public:
137 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
138 const RegionCodeGenTy &UntiedCodeGen)
139 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
140 void Enter(CodeGenFunction &CGF) override {
141 if (Untied) {
142 // Emit task switching point.
143 auto PartIdLVal = CGF.EmitLoadOfPointerLValue(
144 CGF.GetAddrOfLocalVar(PartIDVar),
145 PartIDVar->getType()->castAs<PointerType>());
146 auto *Res = CGF.EmitLoadOfScalar(PartIdLVal, SourceLocation());
147 auto *DoneBB = CGF.createBasicBlock(".untied.done.");
148 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
149 CGF.EmitBlock(DoneBB);
150 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
151 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
152 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
153 CGF.Builder.GetInsertBlock());
154 emitUntiedSwitch(CGF);
155 }
156 }
157 void emitUntiedSwitch(CodeGenFunction &CGF) const {
158 if (Untied) {
159 auto PartIdLVal = CGF.EmitLoadOfPointerLValue(
160 CGF.GetAddrOfLocalVar(PartIDVar),
161 PartIDVar->getType()->castAs<PointerType>());
162 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
163 PartIdLVal);
164 UntiedCodeGen(CGF);
165 CodeGenFunction::JumpDest CurPoint =
166 CGF.getJumpDestInCurrentScope(".untied.next.");
167 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
168 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
169 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
170 CGF.Builder.GetInsertBlock());
171 CGF.EmitBranchThroughCleanup(CurPoint);
172 CGF.EmitBlock(CurPoint.getBlock());
173 }
174 }
175 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
176 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000177 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000178 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000179 const RegionCodeGenTy &CodeGen,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000180 OpenMPDirectiveKind Kind, bool HasCancel,
181 const UntiedTaskActionTy &Action)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000182 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev48591dd2016-04-20 04:01:36 +0000183 ThreadIDVar(ThreadIDVar), Action(Action) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000184 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
185 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000186
Alexey Bataev62b63b12015-03-10 07:28:44 +0000187 /// \brief Get a variable or parameter for storing global thread id
188 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000189 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000190
191 /// \brief Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000192 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000193
Alexey Bataev62b63b12015-03-10 07:28:44 +0000194 /// \brief Get the name of the capture helper.
195 StringRef getHelperName() const override { return ".omp_outlined."; }
196
Alexey Bataev48591dd2016-04-20 04:01:36 +0000197 void emitUntiedSwitch(CodeGenFunction &CGF) override {
198 Action.emitUntiedSwitch(CGF);
199 }
200
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000201 static bool classof(const CGCapturedStmtInfo *Info) {
202 return CGOpenMPRegionInfo::classof(Info) &&
203 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
204 TaskOutlinedRegion;
205 }
206
Alexey Bataev62b63b12015-03-10 07:28:44 +0000207private:
208 /// \brief A variable or parameter storing global thread id for OpenMP
209 /// constructs.
210 const VarDecl *ThreadIDVar;
Alexey Bataev48591dd2016-04-20 04:01:36 +0000211 /// Action for emitting code for untied tasks.
212 const UntiedTaskActionTy &Action;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000213};
214
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000215/// \brief API for inlined captured statement code generation in OpenMP
216/// constructs.
217class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
218public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000219 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000220 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000221 OpenMPDirectiveKind Kind, bool HasCancel)
222 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
223 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000224 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000225
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000226 // \brief Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000227 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000228 if (OuterRegionInfo)
229 return OuterRegionInfo->getContextValue();
230 llvm_unreachable("No context value for inlined OpenMP region");
231 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000232
Hans Wennborg7eb54642015-09-10 17:07:54 +0000233 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000234 if (OuterRegionInfo) {
235 OuterRegionInfo->setContextValue(V);
236 return;
237 }
238 llvm_unreachable("No context value for inlined OpenMP region");
239 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000240
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000241 /// \brief Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000242 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000243 if (OuterRegionInfo)
244 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000245 // If there is no outer outlined region,no need to lookup in a list of
246 // captured variables, we can use the original one.
247 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000248 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000249
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000250 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000251 if (OuterRegionInfo)
252 return OuterRegionInfo->getThisFieldDecl();
253 return nullptr;
254 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000255
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000256 /// \brief Get a variable or parameter for storing global thread id
257 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000258 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000259 if (OuterRegionInfo)
260 return OuterRegionInfo->getThreadIDVariable();
261 return nullptr;
262 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000263
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000264 /// \brief Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000265 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000266 if (auto *OuterRegionInfo = getOldCSI())
267 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000268 llvm_unreachable("No helper name for inlined OpenMP construct");
269 }
270
Alexey Bataev48591dd2016-04-20 04:01:36 +0000271 void emitUntiedSwitch(CodeGenFunction &CGF) override {
272 if (OuterRegionInfo)
273 OuterRegionInfo->emitUntiedSwitch(CGF);
274 }
275
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000276 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
277
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000278 static bool classof(const CGCapturedStmtInfo *Info) {
279 return CGOpenMPRegionInfo::classof(Info) &&
280 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
281 }
282
Alexey Bataev48591dd2016-04-20 04:01:36 +0000283 ~CGOpenMPInlinedRegionInfo() override = default;
284
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000285private:
286 /// \brief CodeGen info about outer OpenMP region.
287 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
288 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000289};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000290
Samuel Antaobed3c462015-10-02 16:14:20 +0000291/// \brief API for captured statement code generation in OpenMP target
292/// constructs. For this captures, implicit parameters are used instead of the
Samuel Antaoee8fb302016-01-06 13:42:12 +0000293/// captured fields. The name of the target region has to be unique in a given
294/// application so it is provided by the client, because only the client has
295/// the information to generate that.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000296class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
Samuel Antaobed3c462015-10-02 16:14:20 +0000297public:
298 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000299 const RegionCodeGenTy &CodeGen, StringRef HelperName)
Samuel Antaobed3c462015-10-02 16:14:20 +0000300 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000301 /*HasCancel=*/false),
302 HelperName(HelperName) {}
Samuel Antaobed3c462015-10-02 16:14:20 +0000303
304 /// \brief This is unused for target regions because each starts executing
305 /// with a single thread.
306 const VarDecl *getThreadIDVariable() const override { return nullptr; }
307
308 /// \brief Get the name of the capture helper.
Samuel Antaoee8fb302016-01-06 13:42:12 +0000309 StringRef getHelperName() const override { return HelperName; }
Samuel Antaobed3c462015-10-02 16:14:20 +0000310
311 static bool classof(const CGCapturedStmtInfo *Info) {
312 return CGOpenMPRegionInfo::classof(Info) &&
313 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
314 }
Samuel Antaoee8fb302016-01-06 13:42:12 +0000315
316private:
317 StringRef HelperName;
Samuel Antaobed3c462015-10-02 16:14:20 +0000318};
319
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000320static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000321 llvm_unreachable("No codegen for expressions");
322}
323/// \brief API for generation of expressions captured in a innermost OpenMP
324/// region.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000325class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000326public:
327 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
328 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
329 OMPD_unknown,
330 /*HasCancel=*/false),
331 PrivScope(CGF) {
332 // Make sure the globals captured in the provided statement are local by
333 // using the privatization logic. We assume the same variable is not
334 // captured more than once.
335 for (auto &C : CS.captures()) {
336 if (!C.capturesVariable() && !C.capturesVariableByCopy())
337 continue;
338
339 const VarDecl *VD = C.getCapturedVar();
340 if (VD->isLocalVarDeclOrParm())
341 continue;
342
343 DeclRefExpr DRE(const_cast<VarDecl *>(VD),
344 /*RefersToEnclosingVariableOrCapture=*/false,
345 VD->getType().getNonReferenceType(), VK_LValue,
346 SourceLocation());
347 PrivScope.addPrivate(VD, [&CGF, &DRE]() -> Address {
348 return CGF.EmitLValue(&DRE).getAddress();
349 });
350 }
351 (void)PrivScope.Privatize();
352 }
353
354 /// \brief Lookup the captured field decl for a variable.
355 const FieldDecl *lookup(const VarDecl *VD) const override {
356 if (auto *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
357 return FD;
358 return nullptr;
359 }
360
361 /// \brief Emit the captured statement body.
362 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
363 llvm_unreachable("No body for expressions");
364 }
365
366 /// \brief Get a variable or parameter for storing global thread id
367 /// inside OpenMP construct.
368 const VarDecl *getThreadIDVariable() const override {
369 llvm_unreachable("No thread id for expressions");
370 }
371
372 /// \brief Get the name of the capture helper.
373 StringRef getHelperName() const override {
374 llvm_unreachable("No helper name for expressions");
375 }
376
377 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
378
379private:
380 /// Private scope to capture global variables.
381 CodeGenFunction::OMPPrivateScope PrivScope;
382};
383
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000384/// \brief RAII for emitting code of OpenMP constructs.
385class InlinedOpenMPRegionRAII {
386 CodeGenFunction &CGF;
387
388public:
389 /// \brief Constructs region for combined constructs.
390 /// \param CodeGen Code generation sequence for combined directives. Includes
391 /// a list of functions used for code generation of implicitly inlined
392 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000393 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000394 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000395 : CGF(CGF) {
396 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000397 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
398 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000399 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000400
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000401 ~InlinedOpenMPRegionRAII() {
402 // Restore original CapturedStmtInfo only if we're done with code emission.
403 auto *OldCSI =
404 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
405 delete CGF.CapturedStmtInfo;
406 CGF.CapturedStmtInfo = OldCSI;
407 }
408};
409
Alexey Bataev50b3c952016-02-19 10:38:26 +0000410/// \brief Values for bit flags used in the ident_t to describe the fields.
411/// All enumeric elements are named and described in accordance with the code
412/// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
413enum OpenMPLocationFlags {
414 /// \brief Use trampoline for internal microtask.
415 OMP_IDENT_IMD = 0x01,
416 /// \brief Use c-style ident structure.
417 OMP_IDENT_KMPC = 0x02,
418 /// \brief Atomic reduction option for kmpc_reduce.
419 OMP_ATOMIC_REDUCE = 0x10,
420 /// \brief Explicit 'barrier' directive.
421 OMP_IDENT_BARRIER_EXPL = 0x20,
422 /// \brief Implicit barrier in code.
423 OMP_IDENT_BARRIER_IMPL = 0x40,
424 /// \brief Implicit barrier in 'for' directive.
425 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
426 /// \brief Implicit barrier in 'sections' directive.
427 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
428 /// \brief Implicit barrier in 'single' directive.
429 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140
430};
431
432/// \brief Describes ident structure that describes a source location.
433/// All descriptions are taken from
434/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
435/// Original structure:
436/// typedef struct ident {
437/// kmp_int32 reserved_1; /**< might be used in Fortran;
438/// see above */
439/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
440/// KMP_IDENT_KMPC identifies this union
441/// member */
442/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
443/// see above */
444///#if USE_ITT_BUILD
445/// /* but currently used for storing
446/// region-specific ITT */
447/// /* contextual information. */
448///#endif /* USE_ITT_BUILD */
449/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
450/// C++ */
451/// char const *psource; /**< String describing the source location.
452/// The string is composed of semi-colon separated
453// fields which describe the source file,
454/// the function and a pair of line numbers that
455/// delimit the construct.
456/// */
457/// } ident_t;
458enum IdentFieldIndex {
459 /// \brief might be used in Fortran
460 IdentField_Reserved_1,
461 /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
462 IdentField_Flags,
463 /// \brief Not really used in Fortran any more
464 IdentField_Reserved_2,
465 /// \brief Source[4] in Fortran, do not use for C++
466 IdentField_Reserved_3,
467 /// \brief String describing the source location. The string is composed of
468 /// semi-colon separated fields which describe the source file, the function
469 /// and a pair of line numbers that delimit the construct.
470 IdentField_PSource
471};
472
473/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
474/// the enum sched_type in kmp.h).
475enum OpenMPSchedType {
476 /// \brief Lower bound for default (unordered) versions.
477 OMP_sch_lower = 32,
478 OMP_sch_static_chunked = 33,
479 OMP_sch_static = 34,
480 OMP_sch_dynamic_chunked = 35,
481 OMP_sch_guided_chunked = 36,
482 OMP_sch_runtime = 37,
483 OMP_sch_auto = 38,
484 /// \brief Lower bound for 'ordered' versions.
485 OMP_ord_lower = 64,
486 OMP_ord_static_chunked = 65,
487 OMP_ord_static = 66,
488 OMP_ord_dynamic_chunked = 67,
489 OMP_ord_guided_chunked = 68,
490 OMP_ord_runtime = 69,
491 OMP_ord_auto = 70,
492 OMP_sch_default = OMP_sch_static,
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000493 /// \brief dist_schedule types
494 OMP_dist_sch_static_chunked = 91,
495 OMP_dist_sch_static = 92,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000496};
497
498enum OpenMPRTLFunction {
499 /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
500 /// kmpc_micro microtask, ...);
501 OMPRTL__kmpc_fork_call,
502 /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc,
503 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
504 OMPRTL__kmpc_threadprivate_cached,
505 /// \brief Call to void __kmpc_threadprivate_register( ident_t *,
506 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
507 OMPRTL__kmpc_threadprivate_register,
508 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
509 OMPRTL__kmpc_global_thread_num,
510 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
511 // kmp_critical_name *crit);
512 OMPRTL__kmpc_critical,
513 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
514 // global_tid, kmp_critical_name *crit, uintptr_t hint);
515 OMPRTL__kmpc_critical_with_hint,
516 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
517 // kmp_critical_name *crit);
518 OMPRTL__kmpc_end_critical,
519 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
520 // global_tid);
521 OMPRTL__kmpc_cancel_barrier,
522 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
523 OMPRTL__kmpc_barrier,
524 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
525 OMPRTL__kmpc_for_static_fini,
526 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
527 // global_tid);
528 OMPRTL__kmpc_serialized_parallel,
529 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
530 // global_tid);
531 OMPRTL__kmpc_end_serialized_parallel,
532 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
533 // kmp_int32 num_threads);
534 OMPRTL__kmpc_push_num_threads,
535 // Call to void __kmpc_flush(ident_t *loc);
536 OMPRTL__kmpc_flush,
537 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
538 OMPRTL__kmpc_master,
539 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
540 OMPRTL__kmpc_end_master,
541 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
542 // int end_part);
543 OMPRTL__kmpc_omp_taskyield,
544 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
545 OMPRTL__kmpc_single,
546 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
547 OMPRTL__kmpc_end_single,
548 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
549 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
550 // kmp_routine_entry_t *task_entry);
551 OMPRTL__kmpc_omp_task_alloc,
552 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
553 // new_task);
554 OMPRTL__kmpc_omp_task,
555 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
556 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
557 // kmp_int32 didit);
558 OMPRTL__kmpc_copyprivate,
559 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
560 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
561 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
562 OMPRTL__kmpc_reduce,
563 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
564 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
565 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
566 // *lck);
567 OMPRTL__kmpc_reduce_nowait,
568 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
569 // kmp_critical_name *lck);
570 OMPRTL__kmpc_end_reduce,
571 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
572 // kmp_critical_name *lck);
573 OMPRTL__kmpc_end_reduce_nowait,
574 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
575 // kmp_task_t * new_task);
576 OMPRTL__kmpc_omp_task_begin_if0,
577 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
578 // kmp_task_t * new_task);
579 OMPRTL__kmpc_omp_task_complete_if0,
580 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
581 OMPRTL__kmpc_ordered,
582 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
583 OMPRTL__kmpc_end_ordered,
584 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
585 // global_tid);
586 OMPRTL__kmpc_omp_taskwait,
587 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
588 OMPRTL__kmpc_taskgroup,
589 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
590 OMPRTL__kmpc_end_taskgroup,
591 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
592 // int proc_bind);
593 OMPRTL__kmpc_push_proc_bind,
594 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
595 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
596 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
597 OMPRTL__kmpc_omp_task_with_deps,
598 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
599 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
600 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
601 OMPRTL__kmpc_omp_wait_deps,
602 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
603 // global_tid, kmp_int32 cncl_kind);
604 OMPRTL__kmpc_cancellationpoint,
605 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
606 // kmp_int32 cncl_kind);
607 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000608 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
609 // kmp_int32 num_teams, kmp_int32 thread_limit);
610 OMPRTL__kmpc_push_num_teams,
611 /// \brief Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc,
612 /// kmpc_micro microtask, ...);
613 OMPRTL__kmpc_fork_teams,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000614
615 //
616 // Offloading related calls
617 //
618 // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
619 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
620 // *arg_types);
621 OMPRTL__tgt_target,
Samuel Antaob68e2db2016-03-03 16:20:23 +0000622 // Call to int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
623 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
624 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
625 OMPRTL__tgt_target_teams,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000626 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
627 OMPRTL__tgt_register_lib,
628 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
629 OMPRTL__tgt_unregister_lib,
630};
631
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000632/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
633/// region.
634class CleanupTy final : public EHScopeStack::Cleanup {
635 PrePostActionTy *Action;
636
637public:
638 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
639 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
640 if (!CGF.HaveInsertPoint())
641 return;
642 Action->Exit(CGF);
643 }
644};
645
Hans Wennborg7eb54642015-09-10 17:07:54 +0000646} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000647
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000648void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
649 CodeGenFunction::RunCleanupsScope Scope(CGF);
650 if (PrePostAction) {
651 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
652 Callback(CodeGen, CGF, *PrePostAction);
653 } else {
654 PrePostActionTy Action;
655 Callback(CodeGen, CGF, Action);
656 }
657}
658
Alexey Bataev18095712014-10-10 12:19:54 +0000659LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +0000660 return CGF.EmitLoadOfPointerLValue(
661 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
662 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +0000663}
664
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000665void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000666 if (!CGF.HaveInsertPoint())
667 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000668 // 1.2.2 OpenMP Language Terminology
669 // Structured block - An executable statement with a single entry at the
670 // top and a single exit at the bottom.
671 // The point of exit cannot be a branch out of the structured block.
672 // longjmp() and throw() must not violate the entry/exit criteria.
673 CGF.EHStack.pushTerminate();
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000674 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000675 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000676}
677
Alexey Bataev62b63b12015-03-10 07:28:44 +0000678LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
679 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000680 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
681 getThreadIDVariable()->getType(),
682 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000683}
684
Alexey Bataev9959db52014-05-06 10:08:46 +0000685CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000686 : CGM(CGM), OffloadEntriesInfoManager(CGM) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000687 IdentTy = llvm::StructType::create(
688 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
689 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000690 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000691 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +0000692
693 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +0000694}
695
Alexey Bataev91797552015-03-18 04:13:55 +0000696void CGOpenMPRuntime::clear() {
697 InternalVars.clear();
698}
699
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000700static llvm::Function *
701emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
702 const Expr *CombinerInitializer, const VarDecl *In,
703 const VarDecl *Out, bool IsCombiner) {
704 // void .omp_combiner.(Ty *in, Ty *out);
705 auto &C = CGM.getContext();
706 QualType PtrTy = C.getPointerType(Ty).withRestrict();
707 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000708 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
709 /*Id=*/nullptr, PtrTy);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000710 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
711 /*Id=*/nullptr, PtrTy);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000712 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000713 Args.push_back(&OmpInParm);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000714 auto &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +0000715 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000716 auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
717 auto *Fn = llvm::Function::Create(
718 FnTy, llvm::GlobalValue::InternalLinkage,
719 IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
720 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000721 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000722 CodeGenFunction CGF(CGM);
723 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
724 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
725 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args);
726 CodeGenFunction::OMPPrivateScope Scope(CGF);
727 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
728 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() -> Address {
729 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
730 .getAddress();
731 });
732 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
733 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() -> Address {
734 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
735 .getAddress();
736 });
737 (void)Scope.Privatize();
738 CGF.EmitIgnoredExpr(CombinerInitializer);
739 Scope.ForceCleanup();
740 CGF.FinishFunction();
741 return Fn;
742}
743
744void CGOpenMPRuntime::emitUserDefinedReduction(
745 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
746 if (UDRMap.count(D) > 0)
747 return;
748 auto &C = CGM.getContext();
749 if (!In || !Out) {
750 In = &C.Idents.get("omp_in");
751 Out = &C.Idents.get("omp_out");
752 }
753 llvm::Function *Combiner = emitCombinerOrInitializer(
754 CGM, D->getType(), D->getCombiner(), cast<VarDecl>(D->lookup(In).front()),
755 cast<VarDecl>(D->lookup(Out).front()),
756 /*IsCombiner=*/true);
757 llvm::Function *Initializer = nullptr;
758 if (auto *Init = D->getInitializer()) {
759 if (!Priv || !Orig) {
760 Priv = &C.Idents.get("omp_priv");
761 Orig = &C.Idents.get("omp_orig");
762 }
763 Initializer = emitCombinerOrInitializer(
764 CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()),
765 cast<VarDecl>(D->lookup(Priv).front()),
766 /*IsCombiner=*/false);
767 }
768 UDRMap.insert(std::make_pair(D, std::make_pair(Combiner, Initializer)));
769 if (CGF) {
770 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
771 Decls.second.push_back(D);
772 }
773}
774
Alexey Bataeva839ddd2016-03-17 10:19:46 +0000775std::pair<llvm::Function *, llvm::Function *>
776CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
777 auto I = UDRMap.find(D);
778 if (I != UDRMap.end())
779 return I->second;
780 emitUserDefinedReduction(/*CGF=*/nullptr, D);
781 return UDRMap.lookup(D);
782}
783
John McCall7f416cc2015-09-08 08:05:57 +0000784// Layout information for ident_t.
785static CharUnits getIdentAlign(CodeGenModule &CGM) {
786 return CGM.getPointerAlign();
787}
788static CharUnits getIdentSize(CodeGenModule &CGM) {
789 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign()));
790 return CharUnits::fromQuantity(16) + CGM.getPointerSize();
791}
Alexey Bataev50b3c952016-02-19 10:38:26 +0000792static CharUnits getOffsetOfIdentField(IdentFieldIndex Field) {
John McCall7f416cc2015-09-08 08:05:57 +0000793 // All the fields except the last are i32, so this works beautifully.
794 return unsigned(Field) * CharUnits::fromQuantity(4);
795}
796static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000797 IdentFieldIndex Field,
John McCall7f416cc2015-09-08 08:05:57 +0000798 const llvm::Twine &Name = "") {
799 auto Offset = getOffsetOfIdentField(Field);
800 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
801}
802
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000803llvm::Value *CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000804 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
805 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000806 assert(ThreadIDVar->getType()->isPointerType() &&
807 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +0000808 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
809 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +0000810 bool HasCancel = false;
811 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
812 HasCancel = OPD->hasCancel();
813 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
814 HasCancel = OPSD->hasCancel();
815 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
816 HasCancel = OPFD->hasCancel();
817 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
818 HasCancel);
Alexey Bataevd157d472015-06-24 03:35:38 +0000819 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000820 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +0000821}
822
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000823llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
824 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000825 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
826 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
827 bool Tied, unsigned &NumberOfParts) {
828 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
829 PrePostActionTy &) {
830 auto *ThreadID = getThreadID(CGF, D.getLocStart());
831 auto *UpLoc = emitUpdateLocation(CGF, D.getLocStart());
832 llvm::Value *TaskArgs[] = {
833 UpLoc, ThreadID,
834 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
835 TaskTVar->getType()->castAs<PointerType>())
836 .getPointer()};
837 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
838 };
839 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
840 UntiedCodeGen);
841 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +0000842 assert(!ThreadIDVar->getType()->isPointerType() &&
843 "thread id variable must be of type kmp_int32 for tasks");
844 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
845 CodeGenFunction CGF(CGM, true);
Alexey Bataev48591dd2016-04-20 04:01:36 +0000846 CGOpenMPTaskOutlinedRegionInfo CGInfo(
847 *CS, ThreadIDVar, CodeGen, InnermostKind,
848 cast<OMPTaskDirective>(D).hasCancel(), Action);
Alexey Bataevd157d472015-06-24 03:35:38 +0000849 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev48591dd2016-04-20 04:01:36 +0000850 auto *Res = CGF.GenerateCapturedStmtFunction(*CS);
851 if (!Tied)
852 NumberOfParts = Action.getNumberOfParts();
853 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000854}
855
Alexey Bataev50b3c952016-02-19 10:38:26 +0000856Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
John McCall7f416cc2015-09-08 08:05:57 +0000857 CharUnits Align = getIdentAlign(CGM);
Alexey Bataev15007ba2014-05-07 06:18:01 +0000858 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000859 if (!Entry) {
860 if (!DefaultOpenMPPSource) {
861 // Initialize default location for psource field of ident_t structure of
862 // all ident_t objects. Format is ";file;function;line;column;;".
863 // Taken from
864 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
865 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +0000866 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000867 DefaultOpenMPPSource =
868 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
869 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000870 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
871 CGM.getModule(), IdentTy, /*isConstant*/ true,
872 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000873 DefaultOpenMPLocation->setUnnamedAddr(true);
John McCall7f416cc2015-09-08 08:05:57 +0000874 DefaultOpenMPLocation->setAlignment(Align.getQuantity());
Alexey Bataev9959db52014-05-06 10:08:46 +0000875
876 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000877 llvm::Constant *Values[] = {Zero,
878 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
879 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000880 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
881 DefaultOpenMPLocation->setInitializer(Init);
John McCall7f416cc2015-09-08 08:05:57 +0000882 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000883 }
John McCall7f416cc2015-09-08 08:05:57 +0000884 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +0000885}
886
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000887llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
888 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000889 unsigned Flags) {
890 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +0000891 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +0000892 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +0000893 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +0000894 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000895
896 assert(CGF.CurFn && "No function in current CodeGenFunction.");
897
John McCall7f416cc2015-09-08 08:05:57 +0000898 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000899 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
900 if (I != OpenMPLocThreadIDMap.end())
John McCall7f416cc2015-09-08 08:05:57 +0000901 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
902
Alexander Musmanc6388682014-12-15 07:07:06 +0000903 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
904 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +0000905 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000906 // Generate "ident_t .kmpc_loc.addr;"
John McCall7f416cc2015-09-08 08:05:57 +0000907 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
908 ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +0000909 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +0000910 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000911 LocValue = AI;
912
913 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
914 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000915 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
John McCall7f416cc2015-09-08 08:05:57 +0000916 CGM.getSize(getIdentSize(CGF.CGM)));
Alexey Bataev9959db52014-05-06 10:08:46 +0000917 }
918
919 // char **psource = &.kmpc_loc_<flags>.addr.psource;
John McCall7f416cc2015-09-08 08:05:57 +0000920 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
Alexey Bataev9959db52014-05-06 10:08:46 +0000921
Alexey Bataevf002aca2014-05-30 05:48:40 +0000922 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
923 if (OMPDebugLoc == nullptr) {
924 SmallString<128> Buffer2;
925 llvm::raw_svector_ostream OS2(Buffer2);
926 // Build debug location
927 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
928 OS2 << ";" << PLoc.getFilename() << ";";
929 if (const FunctionDecl *FD =
930 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
931 OS2 << FD->getQualifiedNameAsString();
932 }
933 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
934 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
935 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000936 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000937 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000938 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
939
John McCall7f416cc2015-09-08 08:05:57 +0000940 // Our callers always pass this to a runtime function, so for
941 // convenience, go ahead and return a naked pointer.
942 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +0000943}
944
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000945llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
946 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000947 assert(CGF.CurFn && "No function in current CodeGenFunction.");
948
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000949 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000950 // Check whether we've already cached a load of the thread id in this
951 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000952 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000953 if (I != OpenMPLocThreadIDMap.end()) {
954 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000955 if (ThreadID != nullptr)
956 return ThreadID;
957 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +0000958 if (auto *OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000959 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000960 if (OMPRegionInfo->getThreadIDVariable()) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000961 // Check if this an outlined function with thread id passed as argument.
962 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000963 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
964 // If value loaded in entry block, cache it and use it everywhere in
965 // function.
966 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
967 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
968 Elem.second.ThreadID = ThreadID;
969 }
970 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000971 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000972 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000973
974 // This is not an outlined function region - need to call __kmpc_int32
975 // kmpc_global_thread_num(ident_t *loc).
976 // Generate thread id value and cache this value for use across the
977 // function.
978 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
979 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
980 ThreadID =
981 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
982 emitUpdateLocation(CGF, Loc));
983 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
984 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000985 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000986}
987
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000988void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000989 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000990 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
991 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevc5b1d322016-03-04 09:22:22 +0000992 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
993 for(auto *D : FunctionUDRMap[CGF.CurFn]) {
994 UDRMap.erase(D);
995 }
996 FunctionUDRMap.erase(CGF.CurFn);
997 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000998}
999
1000llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001001 if (!IdentTy) {
1002 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001003 return llvm::PointerType::getUnqual(IdentTy);
1004}
1005
1006llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001007 if (!Kmpc_MicroTy) {
1008 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1009 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1010 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1011 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1012 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001013 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1014}
1015
1016llvm::Constant *
Alexey Bataev50b3c952016-02-19 10:38:26 +00001017CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001018 llvm::Constant *RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001019 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001020 case OMPRTL__kmpc_fork_call: {
1021 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1022 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001023 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1024 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +00001025 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001026 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001027 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
1028 break;
1029 }
1030 case OMPRTL__kmpc_global_thread_num: {
1031 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001032 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +00001033 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001034 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001035 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1036 break;
1037 }
Alexey Bataev97720002014-11-11 04:05:39 +00001038 case OMPRTL__kmpc_threadprivate_cached: {
1039 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1040 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1041 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1042 CGM.VoidPtrTy, CGM.SizeTy,
1043 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
1044 llvm::FunctionType *FnTy =
1045 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1046 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1047 break;
1048 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001049 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001050 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1051 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001052 llvm::Type *TypeParams[] = {
1053 getIdentTyPointerTy(), CGM.Int32Ty,
1054 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1055 llvm::FunctionType *FnTy =
1056 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1057 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1058 break;
1059 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001060 case OMPRTL__kmpc_critical_with_hint: {
1061 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1062 // kmp_critical_name *crit, uintptr_t hint);
1063 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1064 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1065 CGM.IntPtrTy};
1066 llvm::FunctionType *FnTy =
1067 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1068 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1069 break;
1070 }
Alexey Bataev97720002014-11-11 04:05:39 +00001071 case OMPRTL__kmpc_threadprivate_register: {
1072 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1073 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1074 // typedef void *(*kmpc_ctor)(void *);
1075 auto KmpcCtorTy =
1076 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1077 /*isVarArg*/ false)->getPointerTo();
1078 // typedef void *(*kmpc_cctor)(void *, void *);
1079 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1080 auto KmpcCopyCtorTy =
1081 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
1082 /*isVarArg*/ false)->getPointerTo();
1083 // typedef void (*kmpc_dtor)(void *);
1084 auto KmpcDtorTy =
1085 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1086 ->getPointerTo();
1087 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1088 KmpcCopyCtorTy, KmpcDtorTy};
1089 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
1090 /*isVarArg*/ false);
1091 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1092 break;
1093 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001094 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001095 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1096 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001097 llvm::Type *TypeParams[] = {
1098 getIdentTyPointerTy(), CGM.Int32Ty,
1099 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1100 llvm::FunctionType *FnTy =
1101 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1102 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1103 break;
1104 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001105 case OMPRTL__kmpc_cancel_barrier: {
1106 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1107 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001108 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1109 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001110 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1111 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001112 break;
1113 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001114 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001115 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001116 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1117 llvm::FunctionType *FnTy =
1118 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1119 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1120 break;
1121 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001122 case OMPRTL__kmpc_for_static_fini: {
1123 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1124 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1125 llvm::FunctionType *FnTy =
1126 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1127 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1128 break;
1129 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001130 case OMPRTL__kmpc_push_num_threads: {
1131 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1132 // kmp_int32 num_threads)
1133 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1134 CGM.Int32Ty};
1135 llvm::FunctionType *FnTy =
1136 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1137 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1138 break;
1139 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001140 case OMPRTL__kmpc_serialized_parallel: {
1141 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1142 // global_tid);
1143 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1144 llvm::FunctionType *FnTy =
1145 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1146 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1147 break;
1148 }
1149 case OMPRTL__kmpc_end_serialized_parallel: {
1150 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1151 // global_tid);
1152 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1153 llvm::FunctionType *FnTy =
1154 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1155 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1156 break;
1157 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001158 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001159 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001160 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
1161 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001162 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001163 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1164 break;
1165 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001166 case OMPRTL__kmpc_master: {
1167 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1168 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1169 llvm::FunctionType *FnTy =
1170 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1171 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1172 break;
1173 }
1174 case OMPRTL__kmpc_end_master: {
1175 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1176 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1177 llvm::FunctionType *FnTy =
1178 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1179 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1180 break;
1181 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001182 case OMPRTL__kmpc_omp_taskyield: {
1183 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1184 // int end_part);
1185 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1186 llvm::FunctionType *FnTy =
1187 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1188 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1189 break;
1190 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001191 case OMPRTL__kmpc_single: {
1192 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1193 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1194 llvm::FunctionType *FnTy =
1195 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1196 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1197 break;
1198 }
1199 case OMPRTL__kmpc_end_single: {
1200 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1201 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1202 llvm::FunctionType *FnTy =
1203 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1204 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1205 break;
1206 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001207 case OMPRTL__kmpc_omp_task_alloc: {
1208 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1209 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1210 // kmp_routine_entry_t *task_entry);
1211 assert(KmpRoutineEntryPtrTy != nullptr &&
1212 "Type kmp_routine_entry_t must be created.");
1213 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1214 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1215 // Return void * and then cast to particular kmp_task_t type.
1216 llvm::FunctionType *FnTy =
1217 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1218 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1219 break;
1220 }
1221 case OMPRTL__kmpc_omp_task: {
1222 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1223 // *new_task);
1224 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1225 CGM.VoidPtrTy};
1226 llvm::FunctionType *FnTy =
1227 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1228 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
1229 break;
1230 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001231 case OMPRTL__kmpc_copyprivate: {
1232 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00001233 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001234 // kmp_int32 didit);
1235 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1236 auto *CpyFnTy =
1237 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001238 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001239 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
1240 CGM.Int32Ty};
1241 llvm::FunctionType *FnTy =
1242 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1243 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
1244 break;
1245 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001246 case OMPRTL__kmpc_reduce: {
1247 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
1248 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
1249 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
1250 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1251 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1252 /*isVarArg=*/false);
1253 llvm::Type *TypeParams[] = {
1254 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1255 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1256 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1257 llvm::FunctionType *FnTy =
1258 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1259 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
1260 break;
1261 }
1262 case OMPRTL__kmpc_reduce_nowait: {
1263 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
1264 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
1265 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
1266 // *lck);
1267 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1268 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1269 /*isVarArg=*/false);
1270 llvm::Type *TypeParams[] = {
1271 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1272 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1273 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1274 llvm::FunctionType *FnTy =
1275 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1276 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
1277 break;
1278 }
1279 case OMPRTL__kmpc_end_reduce: {
1280 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
1281 // kmp_critical_name *lck);
1282 llvm::Type *TypeParams[] = {
1283 getIdentTyPointerTy(), CGM.Int32Ty,
1284 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1285 llvm::FunctionType *FnTy =
1286 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1287 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
1288 break;
1289 }
1290 case OMPRTL__kmpc_end_reduce_nowait: {
1291 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
1292 // kmp_critical_name *lck);
1293 llvm::Type *TypeParams[] = {
1294 getIdentTyPointerTy(), CGM.Int32Ty,
1295 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
1296 llvm::FunctionType *FnTy =
1297 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1298 RTLFn =
1299 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
1300 break;
1301 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001302 case OMPRTL__kmpc_omp_task_begin_if0: {
1303 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1304 // *new_task);
1305 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1306 CGM.VoidPtrTy};
1307 llvm::FunctionType *FnTy =
1308 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1309 RTLFn =
1310 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
1311 break;
1312 }
1313 case OMPRTL__kmpc_omp_task_complete_if0: {
1314 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1315 // *new_task);
1316 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1317 CGM.VoidPtrTy};
1318 llvm::FunctionType *FnTy =
1319 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1320 RTLFn = CGM.CreateRuntimeFunction(FnTy,
1321 /*Name=*/"__kmpc_omp_task_complete_if0");
1322 break;
1323 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001324 case OMPRTL__kmpc_ordered: {
1325 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
1326 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1327 llvm::FunctionType *FnTy =
1328 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1329 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
1330 break;
1331 }
1332 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001333 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001334 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1335 llvm::FunctionType *FnTy =
1336 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1337 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
1338 break;
1339 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00001340 case OMPRTL__kmpc_omp_taskwait: {
1341 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
1342 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1343 llvm::FunctionType *FnTy =
1344 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1345 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
1346 break;
1347 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001348 case OMPRTL__kmpc_taskgroup: {
1349 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
1350 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1351 llvm::FunctionType *FnTy =
1352 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1353 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
1354 break;
1355 }
1356 case OMPRTL__kmpc_end_taskgroup: {
1357 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
1358 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
1359 llvm::FunctionType *FnTy =
1360 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1361 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
1362 break;
1363 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00001364 case OMPRTL__kmpc_push_proc_bind: {
1365 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
1366 // int proc_bind)
1367 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1368 llvm::FunctionType *FnTy =
1369 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1370 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
1371 break;
1372 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00001373 case OMPRTL__kmpc_omp_task_with_deps: {
1374 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
1375 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
1376 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
1377 llvm::Type *TypeParams[] = {
1378 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
1379 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
1380 llvm::FunctionType *FnTy =
1381 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1382 RTLFn =
1383 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
1384 break;
1385 }
1386 case OMPRTL__kmpc_omp_wait_deps: {
1387 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
1388 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
1389 // kmp_depend_info_t *noalias_dep_list);
1390 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1391 CGM.Int32Ty, CGM.VoidPtrTy,
1392 CGM.Int32Ty, CGM.VoidPtrTy};
1393 llvm::FunctionType *FnTy =
1394 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1395 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
1396 break;
1397 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00001398 case OMPRTL__kmpc_cancellationpoint: {
1399 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
1400 // global_tid, kmp_int32 cncl_kind)
1401 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1402 llvm::FunctionType *FnTy =
1403 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1404 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
1405 break;
1406 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001407 case OMPRTL__kmpc_cancel: {
1408 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
1409 // kmp_int32 cncl_kind)
1410 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
1411 llvm::FunctionType *FnTy =
1412 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1413 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
1414 break;
1415 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00001416 case OMPRTL__kmpc_push_num_teams: {
1417 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
1418 // kmp_int32 num_teams, kmp_int32 num_threads)
1419 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1420 CGM.Int32Ty};
1421 llvm::FunctionType *FnTy =
1422 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1423 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
1424 break;
1425 }
1426 case OMPRTL__kmpc_fork_teams: {
1427 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
1428 // microtask, ...);
1429 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1430 getKmpc_MicroPointerTy()};
1431 llvm::FunctionType *FnTy =
1432 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
1433 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
1434 break;
1435 }
Samuel Antaobed3c462015-10-02 16:14:20 +00001436 case OMPRTL__tgt_target: {
1437 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
1438 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
1439 // *arg_types);
1440 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1441 CGM.VoidPtrTy,
1442 CGM.Int32Ty,
1443 CGM.VoidPtrPtrTy,
1444 CGM.VoidPtrPtrTy,
1445 CGM.SizeTy->getPointerTo(),
1446 CGM.Int32Ty->getPointerTo()};
1447 llvm::FunctionType *FnTy =
1448 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1449 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
1450 break;
1451 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00001452 case OMPRTL__tgt_target_teams: {
1453 // Build int32_t __tgt_target_teams(int32_t device_id, void *host_ptr,
1454 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
1455 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit);
1456 llvm::Type *TypeParams[] = {CGM.Int32Ty,
1457 CGM.VoidPtrTy,
1458 CGM.Int32Ty,
1459 CGM.VoidPtrPtrTy,
1460 CGM.VoidPtrPtrTy,
1461 CGM.SizeTy->getPointerTo(),
1462 CGM.Int32Ty->getPointerTo(),
1463 CGM.Int32Ty,
1464 CGM.Int32Ty};
1465 llvm::FunctionType *FnTy =
1466 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1467 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
1468 break;
1469 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00001470 case OMPRTL__tgt_register_lib: {
1471 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
1472 QualType ParamTy =
1473 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1474 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1475 llvm::FunctionType *FnTy =
1476 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1477 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
1478 break;
1479 }
1480 case OMPRTL__tgt_unregister_lib: {
1481 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
1482 QualType ParamTy =
1483 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
1484 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
1485 llvm::FunctionType *FnTy =
1486 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1487 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
1488 break;
1489 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001490 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00001491 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00001492 return RTLFn;
1493}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001494
Alexander Musman21212e42015-03-13 10:38:23 +00001495llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
1496 bool IVSigned) {
1497 assert((IVSize == 32 || IVSize == 64) &&
1498 "IV size is not compatible with the omp runtime");
1499 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
1500 : "__kmpc_for_static_init_4u")
1501 : (IVSigned ? "__kmpc_for_static_init_8"
1502 : "__kmpc_for_static_init_8u");
1503 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1504 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1505 llvm::Type *TypeParams[] = {
1506 getIdentTyPointerTy(), // loc
1507 CGM.Int32Ty, // tid
1508 CGM.Int32Ty, // schedtype
1509 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1510 PtrTy, // p_lower
1511 PtrTy, // p_upper
1512 PtrTy, // p_stride
1513 ITy, // incr
1514 ITy // chunk
1515 };
1516 llvm::FunctionType *FnTy =
1517 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1518 return CGM.CreateRuntimeFunction(FnTy, Name);
1519}
1520
Alexander Musman92bdaab2015-03-12 13:37:50 +00001521llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize,
1522 bool IVSigned) {
1523 assert((IVSize == 32 || IVSize == 64) &&
1524 "IV size is not compatible with the omp runtime");
1525 auto Name =
1526 IVSize == 32
1527 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
1528 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
1529 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1530 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
1531 CGM.Int32Ty, // tid
1532 CGM.Int32Ty, // schedtype
1533 ITy, // lower
1534 ITy, // upper
1535 ITy, // stride
1536 ITy // chunk
1537 };
1538 llvm::FunctionType *FnTy =
1539 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1540 return CGM.CreateRuntimeFunction(FnTy, Name);
1541}
1542
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001543llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize,
1544 bool IVSigned) {
1545 assert((IVSize == 32 || IVSize == 64) &&
1546 "IV size is not compatible with the omp runtime");
1547 auto Name =
1548 IVSize == 32
1549 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
1550 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
1551 llvm::Type *TypeParams[] = {
1552 getIdentTyPointerTy(), // loc
1553 CGM.Int32Ty, // tid
1554 };
1555 llvm::FunctionType *FnTy =
1556 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1557 return CGM.CreateRuntimeFunction(FnTy, Name);
1558}
1559
Alexander Musman92bdaab2015-03-12 13:37:50 +00001560llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize,
1561 bool IVSigned) {
1562 assert((IVSize == 32 || IVSize == 64) &&
1563 "IV size is not compatible with the omp runtime");
1564 auto Name =
1565 IVSize == 32
1566 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
1567 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
1568 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
1569 auto PtrTy = llvm::PointerType::getUnqual(ITy);
1570 llvm::Type *TypeParams[] = {
1571 getIdentTyPointerTy(), // loc
1572 CGM.Int32Ty, // tid
1573 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
1574 PtrTy, // p_lower
1575 PtrTy, // p_upper
1576 PtrTy // p_stride
1577 };
1578 llvm::FunctionType *FnTy =
1579 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1580 return CGM.CreateRuntimeFunction(FnTy, Name);
1581}
1582
Alexey Bataev97720002014-11-11 04:05:39 +00001583llvm::Constant *
1584CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001585 assert(!CGM.getLangOpts().OpenMPUseTLS ||
1586 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00001587 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001588 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001589 Twine(CGM.getMangledName(VD)) + ".cache.");
1590}
1591
John McCall7f416cc2015-09-08 08:05:57 +00001592Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
1593 const VarDecl *VD,
1594 Address VDAddr,
1595 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001596 if (CGM.getLangOpts().OpenMPUseTLS &&
1597 CGM.getContext().getTargetInfo().isTLSSupported())
1598 return VDAddr;
1599
John McCall7f416cc2015-09-08 08:05:57 +00001600 auto VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001601 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00001602 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1603 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001604 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
1605 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00001606 return Address(CGF.EmitRuntimeCall(
1607 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
1608 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00001609}
1610
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001611void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00001612 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00001613 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
1614 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
1615 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001616 auto OMPLoc = emitUpdateLocation(CGF, Loc);
1617 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00001618 OMPLoc);
1619 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
1620 // to register constructor/destructor for variable.
1621 llvm::Value *Args[] = {OMPLoc,
John McCall7f416cc2015-09-08 08:05:57 +00001622 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
1623 CGM.VoidPtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00001624 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001625 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001626 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001627}
1628
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001629llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00001630 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00001631 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00001632 if (CGM.getLangOpts().OpenMPUseTLS &&
1633 CGM.getContext().getTargetInfo().isTLSSupported())
1634 return nullptr;
1635
Alexey Bataev97720002014-11-11 04:05:39 +00001636 VD = VD->getDefinition(CGM.getContext());
1637 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
1638 ThreadPrivateWithDefinition.insert(VD);
1639 QualType ASTTy = VD->getType();
1640
1641 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
1642 auto Init = VD->getAnyInitializer();
1643 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
1644 // Generate function that re-emits the declaration's initializer into the
1645 // threadprivate copy of the variable VD
1646 CodeGenFunction CtorCGF(CGM);
1647 FunctionArgList Args;
1648 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1649 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1650 Args.push_back(&Dst);
1651
John McCallc56a8b32016-03-11 04:30:31 +00001652 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1653 CGM.getContext().VoidPtrTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001654 auto FTy = CGM.getTypes().GetFunctionType(FI);
1655 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001656 FTy, ".__kmpc_global_ctor_.", FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001657 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
1658 Args, SourceLocation());
1659 auto ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001660 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001661 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00001662 Address Arg = Address(ArgVal, VDAddr.getAlignment());
1663 Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
1664 CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00001665 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
1666 /*IsInitializer=*/true);
1667 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00001668 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00001669 CGM.getContext().VoidPtrTy, Dst.getLocation());
1670 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
1671 CtorCGF.FinishFunction();
1672 Ctor = Fn;
1673 }
1674 if (VD->getType().isDestructedType() != QualType::DK_none) {
1675 // Generate function that emits destructor call for the threadprivate copy
1676 // of the variable VD
1677 CodeGenFunction DtorCGF(CGM);
1678 FunctionArgList Args;
1679 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
1680 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
1681 Args.push_back(&Dst);
1682
John McCallc56a8b32016-03-11 04:30:31 +00001683 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1684 CGM.getContext().VoidTy, Args);
Alexey Bataev97720002014-11-11 04:05:39 +00001685 auto FTy = CGM.getTypes().GetFunctionType(FI);
1686 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001687 FTy, ".__kmpc_global_dtor_.", FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00001688 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00001689 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
1690 SourceLocation());
Adrian Prantl1858c662016-04-24 22:22:29 +00001691 // Create a scope with an artificial location for the body of this function.
1692 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00001693 auto ArgVal = DtorCGF.EmitLoadOfScalar(
1694 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00001695 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
1696 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00001697 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
1698 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
1699 DtorCGF.FinishFunction();
1700 Dtor = Fn;
1701 }
1702 // Do not emit init function if it is not required.
1703 if (!Ctor && !Dtor)
1704 return nullptr;
1705
1706 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1707 auto CopyCtorTy =
1708 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
1709 /*isVarArg=*/false)->getPointerTo();
1710 // Copying constructor for the threadprivate variable.
1711 // Must be NULL - reserved by runtime, but currently it requires that this
1712 // parameter is always NULL. Otherwise it fires assertion.
1713 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
1714 if (Ctor == nullptr) {
1715 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1716 /*isVarArg=*/false)->getPointerTo();
1717 Ctor = llvm::Constant::getNullValue(CtorTy);
1718 }
1719 if (Dtor == nullptr) {
1720 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
1721 /*isVarArg=*/false)->getPointerTo();
1722 Dtor = llvm::Constant::getNullValue(DtorTy);
1723 }
1724 if (!CGF) {
1725 auto InitFunctionTy =
1726 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
1727 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Akira Hatanaka7791f1a42015-10-31 01:28:07 +00001728 InitFunctionTy, ".__omp_threadprivate_init_.",
1729 CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00001730 CodeGenFunction InitCGF(CGM);
1731 FunctionArgList ArgList;
1732 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
1733 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1734 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001735 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001736 InitCGF.FinishFunction();
1737 return InitFunction;
1738 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001739 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00001740 }
1741 return nullptr;
1742}
1743
Alexey Bataev1d677132015-04-22 13:57:31 +00001744/// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
1745/// function. Here is the logic:
1746/// if (Cond) {
1747/// ThenGen();
1748/// } else {
1749/// ElseGen();
1750/// }
1751static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
1752 const RegionCodeGenTy &ThenGen,
1753 const RegionCodeGenTy &ElseGen) {
1754 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
1755
1756 // If the condition constant folds and can be elided, try to avoid emitting
1757 // the condition and the dead arm of the if/else.
1758 bool CondConstant;
1759 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001760 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00001761 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001762 else
Alexey Bataev1d677132015-04-22 13:57:31 +00001763 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001764 return;
1765 }
1766
1767 // Otherwise, the condition did not fold, or we couldn't elide it. Just
1768 // emit the conditional branch.
1769 auto ThenBlock = CGF.createBasicBlock("omp_if.then");
1770 auto ElseBlock = CGF.createBasicBlock("omp_if.else");
1771 auto ContBlock = CGF.createBasicBlock("omp_if.end");
1772 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
1773
1774 // Emit the 'then' code.
1775 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001776 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00001777 CGF.EmitBranch(ContBlock);
1778 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001779 // There is no need to emit line number for unconditional branch.
1780 (void)ApplyDebugLocation::CreateEmpty(CGF);
1781 CGF.EmitBlock(ElseBlock);
1782 ElseGen(CGF);
1783 // There is no need to emit line number for unconditional branch.
1784 (void)ApplyDebugLocation::CreateEmpty(CGF);
1785 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00001786 // Emit the continuation block for code after the if.
1787 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001788}
1789
Alexey Bataev1d677132015-04-22 13:57:31 +00001790void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
1791 llvm::Value *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001792 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00001793 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001794 if (!CGF.HaveInsertPoint())
1795 return;
Alexey Bataev1d677132015-04-22 13:57:31 +00001796 auto *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001797 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
1798 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001799 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001800 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00001801 llvm::Value *Args[] = {
1802 RTLoc,
1803 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001804 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00001805 llvm::SmallVector<llvm::Value *, 16> RealArgs;
1806 RealArgs.append(std::begin(Args), std::end(Args));
1807 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1808
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001809 auto RTLFn = RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001810 CGF.EmitRuntimeCall(RTLFn, RealArgs);
1811 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001812 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
1813 PrePostActionTy &) {
1814 auto &RT = CGF.CGM.getOpenMPRuntime();
1815 auto ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00001816 // Build calls:
1817 // __kmpc_serialized_parallel(&Loc, GTid);
1818 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001819 CGF.EmitRuntimeCall(
1820 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001821
Alexey Bataev1d677132015-04-22 13:57:31 +00001822 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001823 auto ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00001824 Address ZeroAddr =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001825 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
1826 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00001827 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00001828 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
1829 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
1830 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
1831 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev1d677132015-04-22 13:57:31 +00001832 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001833
Alexey Bataev1d677132015-04-22 13:57:31 +00001834 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001835 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00001836 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001837 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
1838 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00001839 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001840 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00001841 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001842 else {
1843 RegionCodeGenTy ThenRCG(ThenGen);
1844 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00001845 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001846}
1847
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00001848// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00001849// thread-ID variable (it is passed in a first argument of the outlined function
1850// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
1851// regular serial code region, get thread ID by calling kmp_int32
1852// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
1853// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00001854Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
1855 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00001856 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001857 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001858 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00001859 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001860
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001861 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +00001862 auto Int32Ty =
1863 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
1864 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
1865 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00001866 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00001867
1868 return ThreadIDTemp;
1869}
1870
Alexey Bataev97720002014-11-11 04:05:39 +00001871llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001872CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +00001873 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001874 SmallString<256> Buffer;
1875 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00001876 Out << Name;
1877 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +00001878 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
1879 if (Elem.second) {
1880 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00001881 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00001882 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00001883 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001884
David Blaikie13156b62014-11-19 03:06:06 +00001885 return Elem.second = new llvm::GlobalVariable(
1886 CGM.getModule(), Ty, /*IsConstant*/ false,
1887 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
1888 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +00001889}
1890
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001891llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +00001892 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001893 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001894}
1895
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001896namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001897/// Common pre(post)-action for different OpenMP constructs.
1898class CommonActionTy final : public PrePostActionTy {
1899 llvm::Value *EnterCallee;
1900 ArrayRef<llvm::Value *> EnterArgs;
1901 llvm::Value *ExitCallee;
1902 ArrayRef<llvm::Value *> ExitArgs;
1903 bool Conditional;
1904 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001905
1906public:
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001907 CommonActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs,
1908 llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs,
1909 bool Conditional = false)
1910 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1911 ExitArgs(ExitArgs), Conditional(Conditional) {}
1912 void Enter(CodeGenFunction &CGF) override {
1913 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
1914 if (Conditional) {
1915 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
1916 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
1917 ContBlock = CGF.createBasicBlock("omp_if.end");
1918 // Generate the branch (If-stmt)
1919 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1920 CGF.EmitBlock(ThenBlock);
1921 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00001922 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001923 void Done(CodeGenFunction &CGF) {
1924 // Emit the rest of blocks/branches
1925 CGF.EmitBranch(ContBlock);
1926 CGF.EmitBlock(ContBlock, true);
1927 }
1928 void Exit(CodeGenFunction &CGF) override {
1929 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00001930 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001931};
Hans Wennborg7eb54642015-09-10 17:07:54 +00001932} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001933
1934void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
1935 StringRef CriticalName,
1936 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00001937 SourceLocation Loc, const Expr *Hint) {
1938 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00001939 // CriticalOpGen();
1940 // __kmpc_end_critical(ident_t *, gtid, Lock);
1941 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00001942 if (!CGF.HaveInsertPoint())
1943 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00001944 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
1945 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001946 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
1947 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00001948 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001949 EnterArgs.push_back(CGF.Builder.CreateIntCast(
1950 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
1951 }
1952 CommonActionTy Action(
1953 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
1954 : OMPRTL__kmpc_critical),
1955 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
1956 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00001957 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001958}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001959
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001960void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001961 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001962 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001963 if (!CGF.HaveInsertPoint())
1964 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00001965 // if(__kmpc_master(ident_t *, gtid)) {
1966 // MasterOpGen();
1967 // __kmpc_end_master(ident_t *, gtid);
1968 // }
1969 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00001970 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001971 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
1972 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
1973 /*Conditional=*/true);
1974 MasterOpGen.setAction(Action);
1975 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
1976 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00001977}
1978
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001979void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
1980 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001981 if (!CGF.HaveInsertPoint())
1982 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00001983 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
1984 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001985 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00001986 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001987 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00001988 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
1989 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00001990}
1991
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001992void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
1993 const RegionCodeGenTy &TaskgroupOpGen,
1994 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001995 if (!CGF.HaveInsertPoint())
1996 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00001997 // __kmpc_taskgroup(ident_t *, gtid);
1998 // TaskgroupOpGen();
1999 // __kmpc_end_taskgroup(ident_t *, gtid);
2000 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002001 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
2002 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
2003 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
2004 Args);
2005 TaskgroupOpGen.setAction(Action);
2006 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002007}
2008
John McCall7f416cc2015-09-08 08:05:57 +00002009/// Given an array of pointers to variables, project the address of a
2010/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002011static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
2012 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00002013 // Pull out the pointer to the variable.
2014 Address PtrAddr =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002015 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00002016 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
2017
2018 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00002019 Addr = CGF.Builder.CreateElementBitCast(
2020 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00002021 return Addr;
2022}
2023
Alexey Bataeva63048e2015-03-23 06:18:07 +00002024static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00002025 CodeGenModule &CGM, llvm::Type *ArgsType,
2026 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
2027 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002028 auto &C = CGM.getContext();
2029 // void copy_func(void *LHSArg, void *RHSArg);
2030 FunctionArgList Args;
2031 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2032 C.VoidPtrTy);
2033 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
2034 C.VoidPtrTy);
2035 Args.push_back(&LHSArg);
2036 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00002037 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002038 auto *Fn = llvm::Function::Create(
2039 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
2040 ".omp.copyprivate.copy_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00002041 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002042 CodeGenFunction CGF(CGM);
2043 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
Alexey Bataev420d45b2015-04-14 05:11:24 +00002044 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002045 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00002046 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2047 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
2048 ArgsType), CGF.getPointerAlign());
2049 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2050 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
2051 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00002052 // *(Type0*)Dst[0] = *(Type0*)Src[0];
2053 // *(Type1*)Dst[1] = *(Type1*)Src[1];
2054 // ...
2055 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00002056 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002057 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
2058 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
2059
2060 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
2061 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
2062
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002063 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
2064 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00002065 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002066 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002067 CGF.FinishFunction();
2068 return Fn;
2069}
2070
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002071void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002072 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002073 SourceLocation Loc,
2074 ArrayRef<const Expr *> CopyprivateVars,
2075 ArrayRef<const Expr *> SrcExprs,
2076 ArrayRef<const Expr *> DstExprs,
2077 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002078 if (!CGF.HaveInsertPoint())
2079 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00002080 assert(CopyprivateVars.size() == SrcExprs.size() &&
2081 CopyprivateVars.size() == DstExprs.size() &&
2082 CopyprivateVars.size() == AssignmentOps.size());
2083 auto &C = CGM.getContext();
2084 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002085 // if(__kmpc_single(ident_t *, gtid)) {
2086 // SingleOpGen();
2087 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002088 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002089 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002090 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2091 // <copy_func>, did_it);
2092
John McCall7f416cc2015-09-08 08:05:57 +00002093 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00002094 if (!CopyprivateVars.empty()) {
2095 // int32 did_it = 0;
2096 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
2097 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00002098 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002099 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002100 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00002101 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002102 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
2103 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
2104 /*Conditional=*/true);
2105 SingleOpGen.setAction(Action);
2106 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
2107 if (DidIt.isValid()) {
2108 // did_it = 1;
2109 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
2110 }
2111 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002112 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
2113 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00002114 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00002115 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
2116 auto CopyprivateArrayTy =
2117 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
2118 /*IndexTypeQuals=*/0);
2119 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00002120 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002121 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
2122 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
John McCall7f416cc2015-09-08 08:05:57 +00002123 Address Elem = CGF.Builder.CreateConstArrayGEP(
2124 CopyprivateList, I, CGF.getPointerSize());
2125 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00002126 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00002127 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
2128 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002129 }
2130 // Build function that copies private values from single region to all other
2131 // threads in the corresponding parallel region.
2132 auto *CpyFn = emitCopyprivateCopyFunction(
2133 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev420d45b2015-04-14 05:11:24 +00002134 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
Alexey Bataev1189bd02016-01-26 12:20:39 +00002135 auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00002136 Address CL =
2137 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
2138 CGF.VoidPtrTy);
2139 auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00002140 llvm::Value *Args[] = {
2141 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
2142 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00002143 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00002144 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00002145 CpyFn, // void (*) (void *, void *) <copy_func>
2146 DidItVal // i32 did_it
2147 };
2148 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
2149 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002150}
2151
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002152void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
2153 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00002154 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002155 if (!CGF.HaveInsertPoint())
2156 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002157 // __kmpc_ordered(ident_t *, gtid);
2158 // OrderedOpGen();
2159 // __kmpc_end_ordered(ident_t *, gtid);
2160 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00002161 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002162 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002163 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
2164 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
2165 Args);
2166 OrderedOpGen.setAction(Action);
2167 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
2168 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002169 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00002170 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002171}
2172
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002173void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev25e5b442015-09-15 12:52:43 +00002174 OpenMPDirectiveKind Kind, bool EmitChecks,
2175 bool ForceSimpleCall) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002176 if (!CGF.HaveInsertPoint())
2177 return;
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00002178 // Build call __kmpc_cancel_barrier(loc, thread_id);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002179 // Build call __kmpc_barrier(loc, thread_id);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002180 unsigned Flags;
2181 if (Kind == OMPD_for)
2182 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2183 else if (Kind == OMPD_sections)
2184 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2185 else if (Kind == OMPD_single)
2186 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2187 else if (Kind == OMPD_barrier)
2188 Flags = OMP_IDENT_BARRIER_EXPL;
2189 else
2190 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002191 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
2192 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002193 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
2194 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002195 if (auto *OMPRegionInfo =
2196 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00002197 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002198 auto *Result = CGF.EmitRuntimeCall(
2199 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00002200 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002201 // if (__kmpc_cancel_barrier()) {
2202 // exit from construct;
2203 // }
2204 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
2205 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
2206 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
2207 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2208 CGF.EmitBlock(ExitBB);
2209 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00002210 auto CancelDestination =
2211 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00002212 CGF.EmitBranchThroughCleanup(CancelDestination);
2213 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
2214 }
2215 return;
2216 }
2217 }
2218 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002219}
2220
Alexander Musmanc6388682014-12-15 07:07:06 +00002221/// \brief Map the OpenMP loop schedule to the runtime enumeration.
2222static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002223 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002224 switch (ScheduleKind) {
2225 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002226 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2227 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00002228 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002229 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002230 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002231 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00002232 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002233 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2234 case OMPC_SCHEDULE_auto:
2235 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00002236 case OMPC_SCHEDULE_unknown:
2237 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002238 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00002239 }
2240 llvm_unreachable("Unexpected runtime schedule");
2241}
2242
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002243/// \brief Map the OpenMP distribute schedule to the runtime enumeration.
2244static OpenMPSchedType
2245getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
2246 // only static is allowed for dist_schedule
2247 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2248}
2249
Alexander Musmanc6388682014-12-15 07:07:06 +00002250bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
2251 bool Chunked) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002252 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00002253 return Schedule == OMP_sch_static;
2254}
2255
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002256bool CGOpenMPRuntime::isStaticNonchunked(
2257 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
2258 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
2259 return Schedule == OMP_dist_sch_static;
2260}
2261
2262
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002263bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002264 auto Schedule =
2265 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002266 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
2267 return Schedule != OMP_sch_static;
2268}
2269
John McCall7f416cc2015-09-08 08:05:57 +00002270void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
2271 SourceLocation Loc,
2272 OpenMPScheduleClauseKind ScheduleKind,
2273 unsigned IVSize, bool IVSigned,
2274 bool Ordered, llvm::Value *UB,
2275 llvm::Value *Chunk) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002276 if (!CGF.HaveInsertPoint())
2277 return;
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002278 OpenMPSchedType Schedule =
2279 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00002280 assert(Ordered ||
2281 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2282 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
2283 // Call __kmpc_dispatch_init(
2284 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
2285 // kmp_int[32|64] lower, kmp_int[32|64] upper,
2286 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002287
John McCall7f416cc2015-09-08 08:05:57 +00002288 // If the Chunk was not specified in the clause - use default value 1.
2289 if (Chunk == nullptr)
2290 Chunk = CGF.Builder.getIntN(IVSize, 1);
2291 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002292 emitUpdateLocation(CGF, Loc),
2293 getThreadID(CGF, Loc),
2294 CGF.Builder.getInt32(Schedule), // Schedule type
2295 CGF.Builder.getIntN(IVSize, 0), // Lower
2296 UB, // Upper
2297 CGF.Builder.getIntN(IVSize, 1), // Stride
2298 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00002299 };
2300 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
2301}
2302
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002303static void emitForStaticInitCall(CodeGenFunction &CGF,
2304 SourceLocation Loc,
2305 llvm::Value * UpdateLocation,
2306 llvm::Value * ThreadId,
2307 llvm::Constant * ForStaticInitFunction,
2308 OpenMPSchedType Schedule,
2309 unsigned IVSize, bool IVSigned, bool Ordered,
2310 Address IL, Address LB, Address UB,
2311 Address ST, llvm::Value *Chunk) {
2312 if (!CGF.HaveInsertPoint())
2313 return;
2314
2315 assert(!Ordered);
2316 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2317 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2318 Schedule == OMP_dist_sch_static ||
2319 Schedule == OMP_dist_sch_static_chunked);
2320
2321 // Call __kmpc_for_static_init(
2322 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
2323 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
2324 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
2325 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
2326 if (Chunk == nullptr) {
2327 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2328 Schedule == OMP_dist_sch_static) &&
2329 "expected static non-chunked schedule");
2330 // If the Chunk was not specified in the clause - use default value 1.
2331 Chunk = CGF.Builder.getIntN(IVSize, 1);
2332 } else {
2333 assert((Schedule == OMP_sch_static_chunked ||
2334 Schedule == OMP_ord_static_chunked ||
2335 Schedule == OMP_dist_sch_static_chunked) &&
2336 "expected static chunked schedule");
2337 }
2338 llvm::Value *Args[] = {
2339 UpdateLocation,
2340 ThreadId,
2341 CGF.Builder.getInt32(Schedule), // Schedule type
2342 IL.getPointer(), // &isLastIter
2343 LB.getPointer(), // &LB
2344 UB.getPointer(), // &UB
2345 ST.getPointer(), // &Stride
2346 CGF.Builder.getIntN(IVSize, 1), // Incr
2347 Chunk // Chunk
2348 };
2349 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
2350}
2351
John McCall7f416cc2015-09-08 08:05:57 +00002352void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
2353 SourceLocation Loc,
2354 OpenMPScheduleClauseKind ScheduleKind,
2355 unsigned IVSize, bool IVSigned,
2356 bool Ordered, Address IL, Address LB,
2357 Address UB, Address ST,
2358 llvm::Value *Chunk) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002359 OpenMPSchedType ScheduleNum = getRuntimeSchedule(ScheduleKind, Chunk != nullptr,
2360 Ordered);
2361 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2362 auto *ThreadId = getThreadID(CGF, Loc);
2363 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
2364 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction,
2365 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
2366}
John McCall7f416cc2015-09-08 08:05:57 +00002367
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002368void CGOpenMPRuntime::emitDistributeStaticInit(CodeGenFunction &CGF,
2369 SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind,
2370 unsigned IVSize, bool IVSigned,
2371 bool Ordered, Address IL, Address LB,
2372 Address UB, Address ST,
2373 llvm::Value *Chunk) {
2374 OpenMPSchedType ScheduleNum = getRuntimeSchedule(SchedKind, Chunk != nullptr);
2375 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc);
2376 auto *ThreadId = getThreadID(CGF, Loc);
2377 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned);
2378 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction,
2379 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00002380}
2381
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002382void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
2383 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002384 if (!CGF.HaveInsertPoint())
2385 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00002386 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002387 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002388 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
2389 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00002390}
2391
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002392void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
2393 SourceLocation Loc,
2394 unsigned IVSize,
2395 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002396 if (!CGF.HaveInsertPoint())
2397 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002398 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00002399 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002400 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
2401}
2402
Alexander Musman92bdaab2015-03-12 13:37:50 +00002403llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
2404 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00002405 bool IVSigned, Address IL,
2406 Address LB, Address UB,
2407 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002408 // Call __kmpc_dispatch_next(
2409 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
2410 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
2411 // kmp_int[32|64] *p_stride);
2412 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00002413 emitUpdateLocation(CGF, Loc),
2414 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002415 IL.getPointer(), // &isLastIter
2416 LB.getPointer(), // &Lower
2417 UB.getPointer(), // &Upper
2418 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00002419 };
2420 llvm::Value *Call =
2421 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
2422 return CGF.EmitScalarConversion(
2423 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00002424 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002425}
2426
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002427void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
2428 llvm::Value *NumThreads,
2429 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002430 if (!CGF.HaveInsertPoint())
2431 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00002432 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
2433 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002434 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00002435 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002436 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
2437 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00002438}
2439
Alexey Bataev7f210c62015-06-18 13:40:03 +00002440void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
2441 OpenMPProcBindClauseKind ProcBind,
2442 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002443 if (!CGF.HaveInsertPoint())
2444 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00002445 // Constants for proc bind value accepted by the runtime.
2446 enum ProcBindTy {
2447 ProcBindFalse = 0,
2448 ProcBindTrue,
2449 ProcBindMaster,
2450 ProcBindClose,
2451 ProcBindSpread,
2452 ProcBindIntel,
2453 ProcBindDefault
2454 } RuntimeProcBind;
2455 switch (ProcBind) {
2456 case OMPC_PROC_BIND_master:
2457 RuntimeProcBind = ProcBindMaster;
2458 break;
2459 case OMPC_PROC_BIND_close:
2460 RuntimeProcBind = ProcBindClose;
2461 break;
2462 case OMPC_PROC_BIND_spread:
2463 RuntimeProcBind = ProcBindSpread;
2464 break;
2465 case OMPC_PROC_BIND_unknown:
2466 llvm_unreachable("Unsupported proc_bind value.");
2467 }
2468 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
2469 llvm::Value *Args[] = {
2470 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
2471 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
2472 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
2473}
2474
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002475void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
2476 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002477 if (!CGF.HaveInsertPoint())
2478 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00002479 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002480 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
2481 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00002482}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002483
Alexey Bataev62b63b12015-03-10 07:28:44 +00002484namespace {
2485/// \brief Indexes of fields for type kmp_task_t.
2486enum KmpTaskTFields {
2487 /// \brief List of shared variables.
2488 KmpTaskTShareds,
2489 /// \brief Task routine.
2490 KmpTaskTRoutine,
2491 /// \brief Partition id for the untied tasks.
2492 KmpTaskTPartId,
2493 /// \brief Function with call of destructors for private variables.
2494 KmpTaskTDestructors,
2495};
Hans Wennborg7eb54642015-09-10 17:07:54 +00002496} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00002497
Samuel Antaoee8fb302016-01-06 13:42:12 +00002498bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
2499 // FIXME: Add other entries type when they become supported.
2500 return OffloadEntriesTargetRegion.empty();
2501}
2502
2503/// \brief Initialize target region entry.
2504void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2505 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2506 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002507 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002508 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
2509 "only required for the device "
2510 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002511 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002512 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr);
2513 ++OffloadingEntriesNum;
2514}
2515
2516void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
2517 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
2518 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00002519 llvm::Constant *Addr, llvm::Constant *ID) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002520 // If we are emitting code for a target, the entry is already initialized,
2521 // only has to be registered.
2522 if (CGM.getLangOpts().OpenMPIsDevice) {
Samuel Antao2de62b02016-02-13 23:35:10 +00002523 assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) &&
Samuel Antaoee8fb302016-01-06 13:42:12 +00002524 "Entry must exist.");
Samuel Antao2de62b02016-02-13 23:35:10 +00002525 auto &Entry =
2526 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00002527 assert(Entry.isValid() && "Entry not initialized!");
2528 Entry.setAddress(Addr);
2529 Entry.setID(ID);
2530 return;
2531 } else {
2532 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID);
Samuel Antao2de62b02016-02-13 23:35:10 +00002533 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002534 }
2535}
2536
2537bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00002538 unsigned DeviceID, unsigned FileID, StringRef ParentName,
2539 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002540 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
2541 if (PerDevice == OffloadEntriesTargetRegion.end())
2542 return false;
2543 auto PerFile = PerDevice->second.find(FileID);
2544 if (PerFile == PerDevice->second.end())
2545 return false;
2546 auto PerParentName = PerFile->second.find(ParentName);
2547 if (PerParentName == PerFile->second.end())
2548 return false;
2549 auto PerLine = PerParentName->second.find(LineNum);
2550 if (PerLine == PerParentName->second.end())
2551 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00002552 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00002553 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00002554 return false;
2555 return true;
2556}
2557
2558void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
2559 const OffloadTargetRegionEntryInfoActTy &Action) {
2560 // Scan all target region entries and perform the provided action.
2561 for (auto &D : OffloadEntriesTargetRegion)
2562 for (auto &F : D.second)
2563 for (auto &P : F.second)
2564 for (auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00002565 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002566}
2567
2568/// \brief Create a Ctor/Dtor-like function whose body is emitted through
2569/// \a Codegen. This is used to emit the two functions that register and
2570/// unregister the descriptor of the current compilation unit.
2571static llvm::Function *
2572createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
2573 const RegionCodeGenTy &Codegen) {
2574 auto &C = CGM.getContext();
2575 FunctionArgList Args;
2576 ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(),
2577 /*Id=*/nullptr, C.VoidPtrTy);
2578 Args.push_back(&DummyPtr);
2579
2580 CodeGenFunction CGF(CGM);
2581 GlobalDecl();
John McCallc56a8b32016-03-11 04:30:31 +00002582 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002583 auto FTy = CGM.getTypes().GetFunctionType(FI);
2584 auto *Fn =
2585 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation());
2586 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation());
2587 Codegen(CGF);
2588 CGF.FinishFunction();
2589 return Fn;
2590}
2591
2592llvm::Function *
2593CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
2594
2595 // If we don't have entries or if we are emitting code for the device, we
2596 // don't need to do anything.
2597 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
2598 return nullptr;
2599
2600 auto &M = CGM.getModule();
2601 auto &C = CGM.getContext();
2602
2603 // Get list of devices we care about
2604 auto &Devices = CGM.getLangOpts().OMPTargetTriples;
2605
2606 // We should be creating an offloading descriptor only if there are devices
2607 // specified.
2608 assert(!Devices.empty() && "No OpenMP offloading devices??");
2609
2610 // Create the external variables that will point to the begin and end of the
2611 // host entries section. These will be defined by the linker.
2612 auto *OffloadEntryTy =
2613 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
2614 llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable(
2615 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002616 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002617 ".omp_offloading.entries_begin");
2618 llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable(
2619 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002620 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002621 ".omp_offloading.entries_end");
2622
2623 // Create all device images
2624 llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires;
2625 auto *DeviceImageTy = cast<llvm::StructType>(
2626 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
2627
2628 for (unsigned i = 0; i < Devices.size(); ++i) {
2629 StringRef T = Devices[i].getTriple();
2630 auto *ImgBegin = new llvm::GlobalVariable(
2631 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002632 /*Initializer=*/nullptr,
2633 Twine(".omp_offloading.img_start.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002634 auto *ImgEnd = new llvm::GlobalVariable(
2635 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00002636 /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002637
2638 llvm::Constant *Dev =
2639 llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd,
2640 HostEntriesBegin, HostEntriesEnd, nullptr);
2641 DeviceImagesEntires.push_back(Dev);
2642 }
2643
2644 // Create device images global array.
2645 llvm::ArrayType *DeviceImagesInitTy =
2646 llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size());
2647 llvm::Constant *DeviceImagesInit =
2648 llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires);
2649
2650 llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable(
2651 M, DeviceImagesInitTy, /*isConstant=*/true,
2652 llvm::GlobalValue::InternalLinkage, DeviceImagesInit,
2653 ".omp_offloading.device_images");
2654 DeviceImages->setUnnamedAddr(true);
2655
2656 // This is a Zero array to be used in the creation of the constant expressions
2657 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
2658 llvm::Constant::getNullValue(CGM.Int32Ty)};
2659
2660 // Create the target region descriptor.
2661 auto *BinaryDescriptorTy = cast<llvm::StructType>(
2662 CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
2663 llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get(
2664 BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
2665 llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages,
2666 Index),
2667 HostEntriesBegin, HostEntriesEnd, nullptr);
2668
2669 auto *Desc = new llvm::GlobalVariable(
2670 M, BinaryDescriptorTy, /*isConstant=*/true,
2671 llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit,
2672 ".omp_offloading.descriptor");
2673
2674 // Emit code to register or unregister the descriptor at execution
2675 // startup or closing, respectively.
2676
2677 // Create a variable to drive the registration and unregistration of the
2678 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
2679 auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var");
2680 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(),
2681 IdentInfo, C.CharTy);
2682
2683 auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002684 CGM, ".omp_offloading.descriptor_unreg",
2685 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002686 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
2687 Desc);
2688 });
2689 auto *RegFn = createOffloadingBinaryDescriptorFunction(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002690 CGM, ".omp_offloading.descriptor_reg",
2691 [&](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00002692 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib),
2693 Desc);
2694 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
2695 });
2696 return RegFn;
2697}
2698
Samuel Antao2de62b02016-02-13 23:35:10 +00002699void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID,
2700 llvm::Constant *Addr, uint64_t Size) {
2701 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00002702 auto *TgtOffloadEntryType = cast<llvm::StructType>(
2703 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()));
2704 llvm::LLVMContext &C = CGM.getModule().getContext();
2705 llvm::Module &M = CGM.getModule();
2706
2707 // Make sure the address has the right type.
Samuel Antao2de62b02016-02-13 23:35:10 +00002708 llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002709
2710 // Create constant string with the name.
2711 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
2712
2713 llvm::GlobalVariable *Str =
2714 new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true,
2715 llvm::GlobalValue::InternalLinkage, StrPtrInit,
2716 ".omp_offloading.entry_name");
2717 Str->setUnnamedAddr(true);
2718 llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy);
2719
2720 // Create the entry struct.
2721 llvm::Constant *EntryInit = llvm::ConstantStruct::get(
2722 TgtOffloadEntryType, AddrPtr, StrPtr,
2723 llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr);
2724 llvm::GlobalVariable *Entry = new llvm::GlobalVariable(
2725 M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage,
2726 EntryInit, ".omp_offloading.entry");
2727
2728 // The entry has to be created in the section the linker expects it to be.
2729 Entry->setSection(".omp_offloading.entries");
2730 // We can't have any padding between symbols, so we need to have 1-byte
2731 // alignment.
2732 Entry->setAlignment(1);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002733}
2734
2735void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
2736 // Emit the offloading entries and metadata so that the device codegen side
2737 // can
2738 // easily figure out what to emit. The produced metadata looks like this:
2739 //
2740 // !omp_offload.info = !{!1, ...}
2741 //
2742 // Right now we only generate metadata for function that contain target
2743 // regions.
2744
2745 // If we do not have entries, we dont need to do anything.
2746 if (OffloadEntriesInfoManager.empty())
2747 return;
2748
2749 llvm::Module &M = CGM.getModule();
2750 llvm::LLVMContext &C = M.getContext();
2751 SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
2752 OrderedEntries(OffloadEntriesInfoManager.size());
2753
2754 // Create the offloading info metadata node.
2755 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
2756
2757 // Auxiliar methods to create metadata values and strings.
2758 auto getMDInt = [&](unsigned v) {
2759 return llvm::ConstantAsMetadata::get(
2760 llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v));
2761 };
2762
2763 auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); };
2764
2765 // Create function that emits metadata for each target region entry;
2766 auto &&TargetRegionMetadataEmitter = [&](
2767 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line,
Samuel Antaoee8fb302016-01-06 13:42:12 +00002768 OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
2769 llvm::SmallVector<llvm::Metadata *, 32> Ops;
2770 // Generate metadata for target regions. Each entry of this metadata
2771 // contains:
2772 // - Entry 0 -> Kind of this type of metadata (0).
2773 // - Entry 1 -> Device ID of the file where the entry was identified.
2774 // - Entry 2 -> File ID of the file where the entry was identified.
2775 // - Entry 3 -> Mangled name of the function where the entry was identified.
2776 // - Entry 4 -> Line in the file where the entry was identified.
Samuel Antao2de62b02016-02-13 23:35:10 +00002777 // - Entry 5 -> Order the entry was created.
Samuel Antaoee8fb302016-01-06 13:42:12 +00002778 // The first element of the metadata node is the kind.
2779 Ops.push_back(getMDInt(E.getKind()));
2780 Ops.push_back(getMDInt(DeviceID));
2781 Ops.push_back(getMDInt(FileID));
2782 Ops.push_back(getMDString(ParentName));
2783 Ops.push_back(getMDInt(Line));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002784 Ops.push_back(getMDInt(E.getOrder()));
2785
2786 // Save this entry in the right position of the ordered entries array.
2787 OrderedEntries[E.getOrder()] = &E;
2788
2789 // Add metadata to the named metadata node.
2790 MD->addOperand(llvm::MDNode::get(C, Ops));
2791 };
2792
2793 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
2794 TargetRegionMetadataEmitter);
2795
2796 for (auto *E : OrderedEntries) {
2797 assert(E && "All ordered entries must exist!");
2798 if (auto *CE =
2799 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
2800 E)) {
2801 assert(CE->getID() && CE->getAddress() &&
2802 "Entry ID and Addr are invalid!");
Samuel Antao2de62b02016-02-13 23:35:10 +00002803 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0);
Samuel Antaoee8fb302016-01-06 13:42:12 +00002804 } else
2805 llvm_unreachable("Unsupported entry kind.");
2806 }
2807}
2808
2809/// \brief Loads all the offload entries information from the host IR
2810/// metadata.
2811void CGOpenMPRuntime::loadOffloadInfoMetadata() {
2812 // If we are in target mode, load the metadata from the host IR. This code has
2813 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
2814
2815 if (!CGM.getLangOpts().OpenMPIsDevice)
2816 return;
2817
2818 if (CGM.getLangOpts().OMPHostIRFile.empty())
2819 return;
2820
2821 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
2822 if (Buf.getError())
2823 return;
2824
2825 llvm::LLVMContext C;
2826 auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C);
2827
2828 if (ME.getError())
2829 return;
2830
2831 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
2832 if (!MD)
2833 return;
2834
2835 for (auto I : MD->operands()) {
2836 llvm::MDNode *MN = cast<llvm::MDNode>(I);
2837
2838 auto getMDInt = [&](unsigned Idx) {
2839 llvm::ConstantAsMetadata *V =
2840 cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
2841 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
2842 };
2843
2844 auto getMDString = [&](unsigned Idx) {
2845 llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx));
2846 return V->getString();
2847 };
2848
2849 switch (getMDInt(0)) {
2850 default:
2851 llvm_unreachable("Unexpected metadata!");
2852 break;
2853 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
2854 OFFLOAD_ENTRY_INFO_TARGET_REGION:
2855 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
2856 /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2),
2857 /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4),
Samuel Antao2de62b02016-02-13 23:35:10 +00002858 /*Order=*/getMDInt(5));
Samuel Antaoee8fb302016-01-06 13:42:12 +00002859 break;
2860 }
2861 }
2862}
2863
Alexey Bataev62b63b12015-03-10 07:28:44 +00002864void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
2865 if (!KmpRoutineEntryPtrTy) {
2866 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
2867 auto &C = CGM.getContext();
2868 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
2869 FunctionProtoType::ExtProtoInfo EPI;
2870 KmpRoutineEntryPtrQTy = C.getPointerType(
2871 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2872 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
2873 }
2874}
2875
Alexey Bataevc71a4092015-09-11 10:29:41 +00002876static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
2877 QualType FieldTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00002878 auto *Field = FieldDecl::Create(
2879 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
2880 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
2881 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
2882 Field->setAccess(AS_public);
2883 DC->addDecl(Field);
Alexey Bataevc71a4092015-09-11 10:29:41 +00002884 return Field;
Alexey Bataev62b63b12015-03-10 07:28:44 +00002885}
2886
Samuel Antaoee8fb302016-01-06 13:42:12 +00002887QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
2888
2889 // Make sure the type of the entry is already created. This is the type we
2890 // have to create:
2891 // struct __tgt_offload_entry{
2892 // void *addr; // Pointer to the offload entry info.
2893 // // (function or global)
2894 // char *name; // Name of the function or global.
2895 // size_t size; // Size of the entry info (0 if it a function).
2896 // };
2897 if (TgtOffloadEntryQTy.isNull()) {
2898 ASTContext &C = CGM.getContext();
2899 auto *RD = C.buildImplicitRecord("__tgt_offload_entry");
2900 RD->startDefinition();
2901 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2902 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
2903 addFieldToRecordDecl(C, RD, C.getSizeType());
2904 RD->completeDefinition();
2905 TgtOffloadEntryQTy = C.getRecordType(RD);
2906 }
2907 return TgtOffloadEntryQTy;
2908}
2909
2910QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
2911 // These are the types we need to build:
2912 // struct __tgt_device_image{
2913 // void *ImageStart; // Pointer to the target code start.
2914 // void *ImageEnd; // Pointer to the target code end.
2915 // // We also add the host entries to the device image, as it may be useful
2916 // // for the target runtime to have access to that information.
2917 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
2918 // // the entries.
2919 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2920 // // entries (non inclusive).
2921 // };
2922 if (TgtDeviceImageQTy.isNull()) {
2923 ASTContext &C = CGM.getContext();
2924 auto *RD = C.buildImplicitRecord("__tgt_device_image");
2925 RD->startDefinition();
2926 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2927 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
2928 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2929 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2930 RD->completeDefinition();
2931 TgtDeviceImageQTy = C.getRecordType(RD);
2932 }
2933 return TgtDeviceImageQTy;
2934}
2935
2936QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
2937 // struct __tgt_bin_desc{
2938 // int32_t NumDevices; // Number of devices supported.
2939 // __tgt_device_image *DeviceImages; // Arrays of device images
2940 // // (one per device).
2941 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
2942 // // entries.
2943 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
2944 // // entries (non inclusive).
2945 // };
2946 if (TgtBinaryDescriptorQTy.isNull()) {
2947 ASTContext &C = CGM.getContext();
2948 auto *RD = C.buildImplicitRecord("__tgt_bin_desc");
2949 RD->startDefinition();
2950 addFieldToRecordDecl(
2951 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
2952 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
2953 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2954 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
2955 RD->completeDefinition();
2956 TgtBinaryDescriptorQTy = C.getRecordType(RD);
2957 }
2958 return TgtBinaryDescriptorQTy;
2959}
2960
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002961namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00002962struct PrivateHelpersTy {
2963 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
2964 const VarDecl *PrivateElemInit)
2965 : Original(Original), PrivateCopy(PrivateCopy),
2966 PrivateElemInit(PrivateElemInit) {}
2967 const VarDecl *Original;
2968 const VarDecl *PrivateCopy;
2969 const VarDecl *PrivateElemInit;
2970};
2971typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00002972} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002973
Alexey Bataev9e034042015-05-05 04:05:12 +00002974static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00002975createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002976 if (!Privates.empty()) {
2977 auto &C = CGM.getContext();
2978 // Build struct .kmp_privates_t. {
2979 // /* private vars */
2980 // };
2981 auto *RD = C.buildImplicitRecord(".kmp_privates.t");
2982 RD->startDefinition();
2983 for (auto &&Pair : Privates) {
Alexey Bataevc71a4092015-09-11 10:29:41 +00002984 auto *VD = Pair.second.Original;
2985 auto Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00002986 Type = Type.getNonReferenceType();
Alexey Bataevc71a4092015-09-11 10:29:41 +00002987 auto *FD = addFieldToRecordDecl(C, RD, Type);
2988 if (VD->hasAttrs()) {
2989 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
2990 E(VD->getAttrs().end());
2991 I != E; ++I)
2992 FD->addAttr(*I);
2993 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002994 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00002995 RD->completeDefinition();
2996 return RD;
2997 }
2998 return nullptr;
2999}
3000
Alexey Bataev9e034042015-05-05 04:05:12 +00003001static RecordDecl *
3002createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003003 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003004 auto &C = CGM.getContext();
3005 // Build struct kmp_task_t {
3006 // void * shareds;
3007 // kmp_routine_entry_t routine;
3008 // kmp_int32 part_id;
3009 // kmp_routine_entry_t destructors;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003010 // };
3011 auto *RD = C.buildImplicitRecord("kmp_task_t");
3012 RD->startDefinition();
3013 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
3014 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
3015 addFieldToRecordDecl(C, RD, KmpInt32Ty);
3016 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003017 RD->completeDefinition();
3018 return RD;
3019}
3020
3021static RecordDecl *
3022createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003023 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003024 auto &C = CGM.getContext();
3025 // Build struct kmp_task_t_with_privates {
3026 // kmp_task_t task_data;
3027 // .kmp_privates_t. privates;
3028 // };
3029 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
3030 RD->startDefinition();
3031 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003032 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
3033 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
3034 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003035 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003036 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00003037}
3038
3039/// \brief Emit a proxy function which accepts kmp_task_t as the second
3040/// argument.
3041/// \code
3042/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003043/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003044/// tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003045/// return 0;
3046/// }
3047/// \endcode
3048static llvm::Value *
3049emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003050 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
3051 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003052 QualType SharedsPtrTy, llvm::Value *TaskFunction,
3053 llvm::Value *TaskPrivatesMap) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003054 auto &C = CGM.getContext();
3055 FunctionArgList Args;
3056 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3057 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003058 /*Id=*/nullptr,
3059 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003060 Args.push_back(&GtidArg);
3061 Args.push_back(&TaskTypeArg);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003062 auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003063 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003064 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
3065 auto *TaskEntry =
3066 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
3067 ".omp_task_entry.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003068 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003069 CodeGenFunction CGF(CGM);
3070 CGF.disableDebugInfo();
3071 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
3072
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003073 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev48591dd2016-04-20 04:01:36 +00003074 // tt, tt->task_data.shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003075 auto *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00003076 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00003077 LValue TDBase = CGF.EmitLoadOfPointerLValue(
3078 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3079 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003080 auto *KmpTaskTWithPrivatesQTyRD =
3081 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003082 LValue Base =
3083 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003084 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
3085 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3086 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003087 auto *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003088
3089 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3090 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003091 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003092 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003093 CGF.ConvertTypeForMem(SharedsPtrTy));
3094
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003095 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3096 llvm::Value *PrivatesParam;
3097 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3098 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
3099 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003100 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003101 } else {
3102 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3103 }
3104
3105 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam,
Alexey Bataev48591dd2016-04-20 04:01:36 +00003106 TaskPrivatesMap,
3107 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3108 TDBase.getAddress(), CGF.VoidPtrTy)
3109 .getPointer(),
3110 SharedsParam};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003111 CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
3112 CGF.EmitStoreThroughLValue(
3113 RValue::get(CGF.Builder.getInt32(/*C=*/0)),
John McCall7f416cc2015-09-08 08:05:57 +00003114 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00003115 CGF.FinishFunction();
3116 return TaskEntry;
3117}
3118
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003119static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
3120 SourceLocation Loc,
3121 QualType KmpInt32Ty,
3122 QualType KmpTaskTWithPrivatesPtrQTy,
3123 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003124 auto &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003125 FunctionArgList Args;
3126 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
3127 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003128 /*Id=*/nullptr,
3129 KmpTaskTWithPrivatesPtrQTy.withRestrict());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003130 Args.push_back(&GtidArg);
3131 Args.push_back(&TaskTypeArg);
3132 FunctionType::ExtInfo Info;
3133 auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003134 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003135 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo);
3136 auto *DestructorFn =
3137 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3138 ".omp_task_destructor.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003139 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
3140 DestructorFnInfo);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003141 CodeGenFunction CGF(CGM);
3142 CGF.disableDebugInfo();
3143 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
3144 Args);
3145
Alexey Bataev31300ed2016-02-04 11:27:03 +00003146 LValue Base = CGF.EmitLoadOfPointerLValue(
3147 CGF.GetAddrOfLocalVar(&TaskTypeArg),
3148 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003149 auto *KmpTaskTWithPrivatesQTyRD =
3150 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
3151 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003152 Base = CGF.EmitLValueForField(Base, *FI);
3153 for (auto *Field :
3154 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
3155 if (auto DtorKind = Field->getType().isDestructedType()) {
3156 auto FieldLValue = CGF.EmitLValueForField(Base, Field);
3157 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3158 }
3159 }
3160 CGF.FinishFunction();
3161 return DestructorFn;
3162}
3163
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003164/// \brief Emit a privates mapping function for correct handling of private and
3165/// firstprivate variables.
3166/// \code
3167/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
3168/// **noalias priv1,..., <tyn> **noalias privn) {
3169/// *priv1 = &.privates.priv1;
3170/// ...;
3171/// *privn = &.privates.privn;
3172/// }
3173/// \endcode
3174static llvm::Value *
3175emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00003176 ArrayRef<const Expr *> PrivateVars,
3177 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003178 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00003179 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003180 auto &C = CGM.getContext();
3181 FunctionArgList Args;
3182 ImplicitParamDecl TaskPrivatesArg(
3183 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
3184 C.getPointerType(PrivatesQTy).withConst().withRestrict());
3185 Args.push_back(&TaskPrivatesArg);
3186 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
3187 unsigned Counter = 1;
3188 for (auto *E: PrivateVars) {
3189 Args.push_back(ImplicitParamDecl::Create(
3190 C, /*DC=*/nullptr, Loc,
3191 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3192 .withConst()
3193 .withRestrict()));
3194 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3195 PrivateVarsPos[VD] = Counter;
3196 ++Counter;
3197 }
3198 for (auto *E : FirstprivateVars) {
3199 Args.push_back(ImplicitParamDecl::Create(
3200 C, /*DC=*/nullptr, Loc,
3201 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
3202 .withConst()
3203 .withRestrict()));
3204 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3205 PrivateVarsPos[VD] = Counter;
3206 ++Counter;
3207 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003208 auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00003209 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003210 auto *TaskPrivatesMapTy =
3211 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
3212 auto *TaskPrivatesMap = llvm::Function::Create(
3213 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
3214 ".omp_task_privates_map.", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003215 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
3216 TaskPrivatesMapFnInfo);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00003217 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003218 CodeGenFunction CGF(CGM);
3219 CGF.disableDebugInfo();
3220 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
3221 TaskPrivatesMapFnInfo, Args);
3222
3223 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00003224 LValue Base = CGF.EmitLoadOfPointerLValue(
3225 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
3226 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003227 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
3228 Counter = 0;
3229 for (auto *Field : PrivatesQTyRD->fields()) {
3230 auto FieldLVal = CGF.EmitLValueForField(Base, Field);
3231 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
John McCall7f416cc2015-09-08 08:05:57 +00003232 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
Alexey Bataev31300ed2016-02-04 11:27:03 +00003233 auto RefLoadLVal = CGF.EmitLoadOfPointerLValue(
3234 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003235 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003236 ++Counter;
3237 }
3238 CGF.FinishFunction();
3239 return TaskPrivatesMap;
3240}
3241
Alexey Bataev9e034042015-05-05 04:05:12 +00003242static int array_pod_sort_comparator(const PrivateDataTy *P1,
3243 const PrivateDataTy *P2) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003244 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
3245}
3246
3247void CGOpenMPRuntime::emitTaskCall(
3248 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
3249 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
Alexey Bataev48591dd2016-04-20 04:01:36 +00003250 unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy,
3251 Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003252 ArrayRef<const Expr *> PrivateCopies,
3253 ArrayRef<const Expr *> FirstprivateVars,
3254 ArrayRef<const Expr *> FirstprivateCopies,
3255 ArrayRef<const Expr *> FirstprivateInits,
3256 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003257 if (!CGF.HaveInsertPoint())
3258 return;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003259 auto &C = CGM.getContext();
Alexey Bataev9e034042015-05-05 04:05:12 +00003260 llvm::SmallVector<PrivateDataTy, 8> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003261 // Aggregate privates and sort them by the alignment.
Alexey Bataev9e034042015-05-05 04:05:12 +00003262 auto I = PrivateCopies.begin();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003263 for (auto *E : PrivateVars) {
3264 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3265 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003266 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003267 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3268 /*PrivateElemInit=*/nullptr)));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003269 ++I;
3270 }
Alexey Bataev9e034042015-05-05 04:05:12 +00003271 I = FirstprivateCopies.begin();
3272 auto IElemInitRef = FirstprivateInits.begin();
3273 for (auto *E : FirstprivateVars) {
3274 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3275 Privates.push_back(std::make_pair(
Alexey Bataevc71a4092015-09-11 10:29:41 +00003276 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00003277 PrivateHelpersTy(
3278 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
3279 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
Richard Trieucc3949d2016-02-18 22:34:54 +00003280 ++I;
3281 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00003282 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003283 llvm::array_pod_sort(Privates.begin(), Privates.end(),
3284 array_pod_sort_comparator);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003285 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
3286 // Build type kmp_routine_entry_t (if not built yet).
3287 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003288 // Build type kmp_task_t (if not built yet).
3289 if (KmpTaskTQTy.isNull()) {
3290 KmpTaskTQTy = C.getRecordType(
3291 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
3292 }
3293 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003294 // Build particular struct kmp_task_t for the given task.
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003295 auto *KmpTaskTWithPrivatesQTyRD =
3296 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
3297 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
3298 QualType KmpTaskTWithPrivatesPtrQTy =
3299 C.getPointerType(KmpTaskTWithPrivatesQTy);
3300 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
3301 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003302 auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003303 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
3304
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003305 // Emit initial values for private copies (if any).
3306 llvm::Value *TaskPrivatesMap = nullptr;
3307 auto *TaskPrivatesMapTy =
3308 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(),
3309 3)
3310 ->getType();
3311 if (!Privates.empty()) {
3312 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3313 TaskPrivatesMap = emitTaskPrivateMappingFunction(
3314 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates);
3315 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3316 TaskPrivatesMap, TaskPrivatesMapTy);
3317 } else {
3318 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3319 cast<llvm::PointerType>(TaskPrivatesMapTy));
3320 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003321 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
3322 // kmp_task_t *tt);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003323 auto *TaskEntry = emitProxyTaskFunction(
3324 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003325 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00003326
3327 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
3328 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
3329 // kmp_routine_entry_t *task_entry);
3330 // Task flags. Format is taken from
3331 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h,
3332 // description of kmp_tasking_flags struct.
3333 const unsigned TiedFlag = 0x1;
3334 const unsigned FinalFlag = 0x2;
3335 unsigned Flags = Tied ? TiedFlag : 0;
3336 auto *TaskFlags =
3337 Final.getPointer()
3338 ? CGF.Builder.CreateSelect(Final.getPointer(),
3339 CGF.Builder.getInt32(FinalFlag),
3340 CGF.Builder.getInt32(/*C=*/0))
3341 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
3342 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataev40e36f12015-11-24 13:01:44 +00003343 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003344 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
3345 getThreadID(CGF, Loc), TaskFlags,
3346 KmpTaskTWithPrivatesTySize, SharedsSize,
3347 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3348 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataev62b63b12015-03-10 07:28:44 +00003349 auto *NewTask = CGF.EmitRuntimeCall(
3350 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003351 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3352 NewTask, KmpTaskTWithPrivatesPtrTy);
3353 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
3354 KmpTaskTWithPrivatesQTy);
3355 LValue TDBase =
3356 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00003357 // Fill the data in the resulting kmp_task_t record.
3358 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00003359 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003360 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003361 KmpTaskSharedsPtr =
3362 Address(CGF.EmitLoadOfScalar(
3363 CGF.EmitLValueForField(
3364 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
3365 KmpTaskTShareds)),
3366 Loc),
3367 CGF.getNaturalTypeAlignment(SharedsTy));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003368 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003369 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003370 // Emit initial values for private copies (if any).
3371 bool NeedsCleanup = false;
3372 if (!Privates.empty()) {
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003373 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3374 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003375 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003376 LValue SharedsBase;
3377 if (!FirstprivateVars.empty()) {
John McCall7f416cc2015-09-08 08:05:57 +00003378 SharedsBase = CGF.MakeAddrLValue(
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003379 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3380 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
3381 SharedsTy);
3382 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003383 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
3384 cast<CapturedStmt>(*D.getAssociatedStmt()));
3385 for (auto &&Pair : Privates) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003386 auto *VD = Pair.second.PrivateCopy;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003387 auto *Init = VD->getAnyInitializer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003388 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003389 if (Init) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003390 if (auto *Elem = Pair.second.PrivateElemInit) {
3391 auto *OriginalVD = Pair.second.Original;
3392 auto *SharedField = CapturesInfo.lookup(OriginalVD);
3393 auto SharedRefLValue =
3394 CGF.EmitLValueForField(SharedsBase, SharedField);
Alexey Bataevc71a4092015-09-11 10:29:41 +00003395 SharedRefLValue = CGF.MakeAddrLValue(
3396 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
3397 SharedRefLValue.getType(), AlignmentSource::Decl);
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003398 QualType Type = OriginalVD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003399 if (Type->isArrayType()) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003400 // Initialize firstprivate array.
3401 if (!isa<CXXConstructExpr>(Init) ||
3402 CGF.isTrivialInitializer(Init)) {
3403 // Perform simple memcpy.
3404 CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003405 SharedRefLValue.getAddress(), Type);
Alexey Bataev9e034042015-05-05 04:05:12 +00003406 } else {
3407 // Initialize firstprivate array using element-by-element
3408 // intialization.
3409 CGF.EmitOMPAggregateAssign(
3410 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003411 Type, [&CGF, Elem, Init, &CapturesInfo](
John McCall7f416cc2015-09-08 08:05:57 +00003412 Address DestElement, Address SrcElement) {
Alexey Bataev9e034042015-05-05 04:05:12 +00003413 // Clean up any temporaries needed by the initialization.
3414 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003415 InitScope.addPrivate(Elem, [SrcElement]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003416 return SrcElement;
3417 });
3418 (void)InitScope.Privatize();
3419 // Emit initialization for single element.
Alexey Bataevd157d472015-06-24 03:35:38 +00003420 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3421 CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003422 CGF.EmitAnyExprToMem(Init, DestElement,
3423 Init->getType().getQualifiers(),
3424 /*IsInitializer=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003425 });
3426 }
3427 } else {
3428 CodeGenFunction::OMPPrivateScope InitScope(CGF);
John McCall7f416cc2015-09-08 08:05:57 +00003429 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
Alexey Bataev9e034042015-05-05 04:05:12 +00003430 return SharedRefLValue.getAddress();
3431 });
3432 (void)InitScope.Privatize();
Alexey Bataevd157d472015-06-24 03:35:38 +00003433 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
Alexey Bataev9e034042015-05-05 04:05:12 +00003434 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
3435 /*capturedByInit=*/false);
Alexey Bataev9e034042015-05-05 04:05:12 +00003436 }
3437 } else {
3438 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
3439 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003440 }
3441 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003442 ++FI;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003443 }
3444 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003445 // Provide pointer to function with destructors for privates.
Alexey Bataev36c1eb92015-04-30 06:51:57 +00003446 llvm::Value *DestructorFn =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00003447 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
3448 KmpTaskTWithPrivatesPtrQTy,
3449 KmpTaskTWithPrivatesQTy)
3450 : llvm::ConstantPointerNull::get(
3451 cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
3452 LValue Destructor = CGF.EmitLValueForField(
3453 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
3454 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3455 DestructorFn, KmpRoutineEntryPtrTy),
3456 Destructor);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003457
3458 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00003459 Address DependenciesArray = Address::invalid();
3460 unsigned NumDependencies = Dependences.size();
3461 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003462 // Dependence kind for RTL.
Alexey Bataev92e82f92015-11-23 13:33:42 +00003463 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003464 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
3465 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003466 QualType FlagsTy =
3467 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003468 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
3469 if (KmpDependInfoTy.isNull()) {
3470 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
3471 KmpDependInfoRD->startDefinition();
3472 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
3473 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
3474 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
3475 KmpDependInfoRD->completeDefinition();
3476 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
3477 } else {
3478 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
3479 }
John McCall7f416cc2015-09-08 08:05:57 +00003480 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003481 // Define type kmp_depend_info[<Dependences.size()>];
3482 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00003483 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003484 ArrayType::Normal, /*IndexTypeQuals=*/0);
3485 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00003486 DependenciesArray =
3487 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
John McCall7f416cc2015-09-08 08:05:57 +00003488 for (unsigned i = 0; i < NumDependencies; ++i) {
3489 const Expr *E = Dependences[i].second;
3490 auto Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003491 llvm::Value *Size;
3492 QualType Ty = E->getType();
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003493 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
3494 LValue UpAddrLVal =
3495 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
3496 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00003497 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003498 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00003499 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00003500 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
3501 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003502 } else
Alexey Bataev1189bd02016-01-26 12:20:39 +00003503 Size = CGF.getTypeSize(Ty);
John McCall7f416cc2015-09-08 08:05:57 +00003504 auto Base = CGF.MakeAddrLValue(
3505 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003506 KmpDependInfoTy);
3507 // deps[i].base_addr = &<Dependences[i].second>;
3508 auto BaseAddrLVal = CGF.EmitLValueForField(
3509 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00003510 CGF.EmitStoreOfScalar(
3511 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
3512 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003513 // deps[i].len = sizeof(<Dependences[i].second>);
3514 auto LenLVal = CGF.EmitLValueForField(
3515 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
3516 CGF.EmitStoreOfScalar(Size, LenLVal);
3517 // deps[i].flags = <Dependences[i].first>;
3518 RTLDependenceKindTy DepKind;
3519 switch (Dependences[i].first) {
3520 case OMPC_DEPEND_in:
3521 DepKind = DepIn;
3522 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00003523 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003524 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003525 case OMPC_DEPEND_inout:
3526 DepKind = DepInOut;
3527 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00003528 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00003529 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003530 case OMPC_DEPEND_unknown:
3531 llvm_unreachable("Unknown task dependence type");
3532 }
3533 auto FlagsLVal = CGF.EmitLValueForField(
3534 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
3535 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
3536 FlagsLVal);
3537 }
John McCall7f416cc2015-09-08 08:05:57 +00003538 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3539 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003540 CGF.VoidPtrTy);
3541 }
3542
Alexey Bataev62b63b12015-03-10 07:28:44 +00003543 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
3544 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003545 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
3546 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
3547 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
3548 // list is not empty
Alexey Bataev1d677132015-04-22 13:57:31 +00003549 auto *ThreadID = getThreadID(CGF, Loc);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003550 auto *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00003551 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
3552 llvm::Value *DepTaskArgs[7];
3553 if (NumDependencies) {
3554 DepTaskArgs[0] = UpLoc;
3555 DepTaskArgs[1] = ThreadID;
3556 DepTaskArgs[2] = NewTask;
3557 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
3558 DepTaskArgs[4] = DependenciesArray.getPointer();
3559 DepTaskArgs[5] = CGF.Builder.getInt32(0);
3560 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3561 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00003562 auto &&ThenCodeGen = [this, Tied, Loc, NumberOfParts, TDBase, KmpTaskTQTyRD,
3563 NumDependencies, &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003564 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003565 if (!Tied) {
3566 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3567 auto PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
3568 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
3569 }
John McCall7f416cc2015-09-08 08:05:57 +00003570 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003571 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00003572 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00003573 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003574 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00003575 TaskArgs);
3576 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00003577 // Check if parent region is untied and build return for untied task;
3578 if (auto *Region =
3579 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3580 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003581 };
John McCall7f416cc2015-09-08 08:05:57 +00003582
3583 llvm::Value *DepWaitTaskArgs[6];
3584 if (NumDependencies) {
3585 DepWaitTaskArgs[0] = UpLoc;
3586 DepWaitTaskArgs[1] = ThreadID;
3587 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
3588 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
3589 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
3590 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
3591 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003592 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
3593 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF,
3594 PrePostActionTy &) {
3595 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003596 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
3597 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
3598 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
3599 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
3600 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00003601 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003602 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003603 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003604 // Call proxy_task_entry(gtid, new_task);
3605 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy](
3606 CodeGenFunction &CGF, PrePostActionTy &Action) {
3607 Action.Enter(CGF);
3608 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
3609 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
3610 };
3611
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003612 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
3613 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003614 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
3615 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003616 RegionCodeGenTy RCG(CodeGen);
3617 CommonActionTy Action(
3618 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
3619 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
3620 RCG.setAction(Action);
3621 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003622 };
John McCall7f416cc2015-09-08 08:05:57 +00003623
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003624 if (IfCond)
Alexey Bataev1d677132015-04-22 13:57:31 +00003625 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003626 else {
3627 RegionCodeGenTy ThenRCG(ThenCodeGen);
3628 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003629 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003630}
3631
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003632/// \brief Emit reduction operation for each element of array (required for
3633/// array sections) LHS op = RHS.
3634/// \param Type Type of array.
3635/// \param LHSVar Variable on the left side of the reduction operation
3636/// (references element of array in original variable).
3637/// \param RHSVar Variable on the right side of the reduction operation
3638/// (references element of array in original variable).
3639/// \param RedOpGen Generator of reduction operation with use of LHSVar and
3640/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00003641static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003642 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
3643 const VarDecl *RHSVar,
3644 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
3645 const Expr *, const Expr *)> &RedOpGen,
3646 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
3647 const Expr *UpExpr = nullptr) {
3648 // Perform element-by-element initialization.
3649 QualType ElementTy;
3650 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
3651 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
3652
3653 // Drill down to the base element type on both arrays.
3654 auto ArrayTy = Type->getAsArrayTypeUnsafe();
3655 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
3656
3657 auto RHSBegin = RHSAddr.getPointer();
3658 auto LHSBegin = LHSAddr.getPointer();
3659 // Cast from pointer to array type to pointer to single element.
3660 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
3661 // The basic structure here is a while-do loop.
3662 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
3663 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
3664 auto IsEmpty =
3665 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
3666 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
3667
3668 // Enter the loop body, making that address the current address.
3669 auto EntryBB = CGF.Builder.GetInsertBlock();
3670 CGF.EmitBlock(BodyBB);
3671
3672 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
3673
3674 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
3675 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
3676 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
3677 Address RHSElementCurrent =
3678 Address(RHSElementPHI,
3679 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3680
3681 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
3682 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
3683 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
3684 Address LHSElementCurrent =
3685 Address(LHSElementPHI,
3686 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
3687
3688 // Emit copy.
3689 CodeGenFunction::OMPPrivateScope Scope(CGF);
3690 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
3691 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
3692 Scope.Privatize();
3693 RedOpGen(CGF, XExpr, EExpr, UpExpr);
3694 Scope.ForceCleanup();
3695
3696 // Shift the address forward by one element.
3697 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
3698 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
3699 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
3700 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
3701 // Check whether we've reached the end.
3702 auto Done =
3703 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
3704 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
3705 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
3706 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
3707
3708 // Done.
3709 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
3710}
3711
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003712/// Emit reduction combiner. If the combiner is a simple expression emit it as
3713/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
3714/// UDR combiner function.
3715static void emitReductionCombiner(CodeGenFunction &CGF,
3716 const Expr *ReductionOp) {
3717 if (auto *CE = dyn_cast<CallExpr>(ReductionOp))
3718 if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
3719 if (auto *DRE =
3720 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
3721 if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
3722 std::pair<llvm::Function *, llvm::Function *> Reduction =
3723 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
3724 RValue Func = RValue::get(Reduction.first);
3725 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
3726 CGF.EmitIgnoredExpr(ReductionOp);
3727 return;
3728 }
3729 CGF.EmitIgnoredExpr(ReductionOp);
3730}
3731
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003732static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
3733 llvm::Type *ArgsType,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003734 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003735 ArrayRef<const Expr *> LHSExprs,
3736 ArrayRef<const Expr *> RHSExprs,
3737 ArrayRef<const Expr *> ReductionOps) {
3738 auto &C = CGM.getContext();
3739
3740 // void reduction_func(void *LHSArg, void *RHSArg);
3741 FunctionArgList Args;
3742 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3743 C.VoidPtrTy);
3744 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr,
3745 C.VoidPtrTy);
3746 Args.push_back(&LHSArg);
3747 Args.push_back(&RHSArg);
John McCallc56a8b32016-03-11 04:30:31 +00003748 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003749 auto *Fn = llvm::Function::Create(
3750 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
3751 ".omp.reduction.reduction_func", &CGM.getModule());
Akira Hatanaka44a59f82015-10-28 02:30:47 +00003752 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003753 CodeGenFunction CGF(CGM);
3754 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
3755
3756 // Dst = (void*[n])(LHSArg);
3757 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003758 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3759 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3760 ArgsType), CGF.getPointerAlign());
3761 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3762 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3763 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003764
3765 // ...
3766 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
3767 // ...
3768 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003769 auto IPriv = Privates.begin();
3770 unsigned Idx = 0;
3771 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003772 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
3773 Scope.addPrivate(RHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003774 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003775 });
3776 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
3777 Scope.addPrivate(LHSVar, [&]() -> Address {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003778 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00003779 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003780 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00003781 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003782 // Get array size and emit VLA type.
3783 ++Idx;
3784 Address Elem =
3785 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
3786 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003787 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy);
3788 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003789 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00003790 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003791 CGF.EmitVariablyModifiedType(PrivTy);
3792 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003793 }
3794 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003795 IPriv = Privates.begin();
3796 auto ILHS = LHSExprs.begin();
3797 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003798 for (auto *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003799 if ((*IPriv)->getType()->isArrayType()) {
3800 // Emit reduction for array section.
3801 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3802 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003803 EmitOMPAggregateReduction(
3804 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
3805 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
3806 emitReductionCombiner(CGF, E);
3807 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003808 } else
3809 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00003810 emitReductionCombiner(CGF, E);
Richard Trieucc3949d2016-02-18 22:34:54 +00003811 ++IPriv;
3812 ++ILHS;
3813 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003814 }
3815 Scope.ForceCleanup();
3816 CGF.FinishFunction();
3817 return Fn;
3818}
3819
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003820static void emitSingleReductionCombiner(CodeGenFunction &CGF,
3821 const Expr *ReductionOp,
3822 const Expr *PrivateRef,
3823 const DeclRefExpr *LHS,
3824 const DeclRefExpr *RHS) {
3825 if (PrivateRef->getType()->isArrayType()) {
3826 // Emit reduction for array section.
3827 auto *LHSVar = cast<VarDecl>(LHS->getDecl());
3828 auto *RHSVar = cast<VarDecl>(RHS->getDecl());
3829 EmitOMPAggregateReduction(
3830 CGF, PrivateRef->getType(), LHSVar, RHSVar,
3831 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
3832 emitReductionCombiner(CGF, ReductionOp);
3833 });
3834 } else
3835 // Emit reduction for array subscript or single variable.
3836 emitReductionCombiner(CGF, ReductionOp);
3837}
3838
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003839void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003840 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003841 ArrayRef<const Expr *> LHSExprs,
3842 ArrayRef<const Expr *> RHSExprs,
3843 ArrayRef<const Expr *> ReductionOps,
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003844 bool WithNowait, bool SimpleReduction) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003845 if (!CGF.HaveInsertPoint())
3846 return;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003847 // Next code should be emitted for reduction:
3848 //
3849 // static kmp_critical_name lock = { 0 };
3850 //
3851 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
3852 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
3853 // ...
3854 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
3855 // *(Type<n>-1*)rhs[<n>-1]);
3856 // }
3857 //
3858 // ...
3859 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
3860 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
3861 // RedList, reduce_func, &<lock>)) {
3862 // case 1:
3863 // ...
3864 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3865 // ...
3866 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3867 // break;
3868 // case 2:
3869 // ...
3870 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
3871 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00003872 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003873 // break;
3874 // default:;
3875 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003876 //
3877 // if SimpleReduction is true, only the next code is generated:
3878 // ...
3879 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3880 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003881
3882 auto &C = CGM.getContext();
3883
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003884 if (SimpleReduction) {
3885 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003886 auto IPriv = Privates.begin();
3887 auto ILHS = LHSExprs.begin();
3888 auto IRHS = RHSExprs.begin();
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003889 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003890 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
3891 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00003892 ++IPriv;
3893 ++ILHS;
3894 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00003895 }
3896 return;
3897 }
3898
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003899 // 1. Build a list of reduction variables.
3900 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003901 auto Size = RHSExprs.size();
3902 for (auto *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00003903 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003904 // Reserve place for array size.
3905 ++Size;
3906 }
3907 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003908 QualType ReductionArrayTy =
3909 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
3910 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00003911 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003912 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003913 auto IPriv = Privates.begin();
3914 unsigned Idx = 0;
3915 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
John McCall7f416cc2015-09-08 08:05:57 +00003916 Address Elem =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003917 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
John McCall7f416cc2015-09-08 08:05:57 +00003918 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003919 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003920 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
3921 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003922 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003923 // Store array size.
3924 ++Idx;
3925 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
3926 CGF.getPointerSize());
Alexey Bataev1189bd02016-01-26 12:20:39 +00003927 llvm::Value *Size = CGF.Builder.CreateIntCast(
3928 CGF.getVLASize(
3929 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
3930 .first,
3931 CGF.SizeTy, /*isSigned=*/false);
3932 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
3933 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003934 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003935 }
3936
3937 // 2. Emit reduce_func().
3938 auto *ReductionFn = emitReductionFunction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003939 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
3940 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003941
3942 // 3. Create static kmp_critical_name lock = { 0 };
3943 auto *Lock = getCriticalRegionLock(".reduction");
3944
3945 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
3946 // RedList, reduce_func, &<lock>);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003947 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003948 auto *ThreadId = getThreadID(CGF, Loc);
Alexey Bataev1189bd02016-01-26 12:20:39 +00003949 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003950 auto *RL =
3951 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
3952 CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003953 llvm::Value *Args[] = {
3954 IdentTLoc, // ident_t *<loc>
3955 ThreadId, // i32 <gtid>
3956 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
3957 ReductionArrayTySize, // size_type sizeof(RedList)
3958 RL, // void *RedList
3959 ReductionFn, // void (*) (void *, void *) <reduce_func>
3960 Lock // kmp_critical_name *&<lock>
3961 };
3962 auto Res = CGF.EmitRuntimeCall(
3963 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
3964 : OMPRTL__kmpc_reduce),
3965 Args);
3966
3967 // 5. Build switch(res)
3968 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
3969 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
3970
3971 // 6. Build case 1:
3972 // ...
3973 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
3974 // ...
3975 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3976 // break;
3977 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
3978 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
3979 CGF.EmitBlock(Case1BB);
3980
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003981 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
3982 llvm::Value *EndArgs[] = {
3983 IdentTLoc, // ident_t *<loc>
3984 ThreadId, // i32 <gtid>
3985 Lock // kmp_critical_name *&<lock>
3986 };
3987 auto &&CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps](
3988 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003989 auto IPriv = Privates.begin();
3990 auto ILHS = LHSExprs.begin();
3991 auto IRHS = RHSExprs.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003992 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003993 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
3994 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00003995 ++IPriv;
3996 ++ILHS;
3997 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00003998 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003999 };
4000 RegionCodeGenTy RCG(CodeGen);
4001 CommonActionTy Action(
4002 nullptr, llvm::None,
4003 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
4004 : OMPRTL__kmpc_end_reduce),
4005 EndArgs);
4006 RCG.setAction(Action);
4007 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004008
4009 CGF.EmitBranch(DefaultBB);
4010
4011 // 7. Build case 2:
4012 // ...
4013 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
4014 // ...
4015 // break;
4016 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
4017 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
4018 CGF.EmitBlock(Case2BB);
4019
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004020 auto &&AtomicCodeGen = [Loc, &Privates, &LHSExprs, &RHSExprs, &ReductionOps](
4021 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004022 auto ILHS = LHSExprs.begin();
4023 auto IRHS = RHSExprs.begin();
4024 auto IPriv = Privates.begin();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004025 for (auto *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004026 const Expr *XExpr = nullptr;
4027 const Expr *EExpr = nullptr;
4028 const Expr *UpExpr = nullptr;
4029 BinaryOperatorKind BO = BO_Comma;
4030 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
4031 if (BO->getOpcode() == BO_Assign) {
4032 XExpr = BO->getLHS();
4033 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004034 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004035 }
4036 // Try to emit update expression as a simple atomic.
4037 auto *RHSExpr = UpExpr;
4038 if (RHSExpr) {
4039 // Analyze RHS part of the whole expression.
4040 if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
4041 RHSExpr->IgnoreParenImpCasts())) {
4042 // If this is a conditional operator, analyze its condition for
4043 // min/max reduction operator.
4044 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00004045 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004046 if (auto *BORHS =
4047 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
4048 EExpr = BORHS->getRHS();
4049 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00004050 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004051 }
4052 if (XExpr) {
4053 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4054 auto &&AtomicRedGen = [BO, VD, IPriv,
4055 Loc](CodeGenFunction &CGF, const Expr *XExpr,
4056 const Expr *EExpr, const Expr *UpExpr) {
4057 LValue X = CGF.EmitLValue(XExpr);
4058 RValue E;
4059 if (EExpr)
4060 E = CGF.EmitAnyExpr(EExpr);
4061 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00004062 X, E, BO, /*IsXLHSInRHSPart=*/true,
4063 llvm::AtomicOrdering::Monotonic, Loc,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004064 [&CGF, UpExpr, VD, IPriv, Loc](RValue XRValue) {
4065 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4066 PrivateScope.addPrivate(
4067 VD, [&CGF, VD, XRValue, Loc]() -> Address {
4068 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
4069 CGF.emitOMPSimpleStore(
4070 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
4071 VD->getType().getNonReferenceType(), Loc);
4072 return LHSTemp;
4073 });
4074 (void)PrivateScope.Privatize();
4075 return CGF.EmitAnyExpr(UpExpr);
4076 });
4077 };
4078 if ((*IPriv)->getType()->isArrayType()) {
4079 // Emit atomic reduction for array section.
4080 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4081 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
4082 AtomicRedGen, XExpr, EExpr, UpExpr);
4083 } else
4084 // Emit atomic reduction for array subscript or single variable.
4085 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
4086 } else {
4087 // Emit as a critical region.
4088 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
4089 const Expr *, const Expr *) {
4090 auto &RT = CGF.CGM.getOpenMPRuntime();
4091 RT.emitCriticalRegion(
4092 CGF, ".atomic_reduction",
4093 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
4094 Action.Enter(CGF);
4095 emitReductionCombiner(CGF, E);
4096 },
4097 Loc);
4098 };
4099 if ((*IPriv)->getType()->isArrayType()) {
4100 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
4101 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
4102 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4103 CritRedGen);
4104 } else
4105 CritRedGen(CGF, nullptr, nullptr, nullptr);
4106 }
Richard Trieucc3949d2016-02-18 22:34:54 +00004107 ++ILHS;
4108 ++IRHS;
4109 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004110 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004111 };
4112 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
4113 if (!WithNowait) {
4114 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
4115 llvm::Value *EndArgs[] = {
4116 IdentTLoc, // ident_t *<loc>
4117 ThreadId, // i32 <gtid>
4118 Lock // kmp_critical_name *&<lock>
4119 };
4120 CommonActionTy Action(nullptr, llvm::None,
4121 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
4122 EndArgs);
4123 AtomicRCG.setAction(Action);
4124 AtomicRCG(CGF);
4125 } else
4126 AtomicRCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004127
4128 CGF.EmitBranch(DefaultBB);
4129 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
4130}
4131
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004132void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
4133 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004134 if (!CGF.HaveInsertPoint())
4135 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004136 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
4137 // global_tid);
4138 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
4139 // Ignore return result until untied tasks are supported.
4140 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00004141 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
4142 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00004143}
4144
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004145void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004146 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00004147 const RegionCodeGenTy &CodeGen,
4148 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004149 if (!CGF.HaveInsertPoint())
4150 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004151 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004152 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00004153}
4154
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004155namespace {
4156enum RTCancelKind {
4157 CancelNoreq = 0,
4158 CancelParallel = 1,
4159 CancelLoop = 2,
4160 CancelSections = 3,
4161 CancelTaskgroup = 4
4162};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004163} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004164
4165static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
4166 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00004167 if (CancelRegion == OMPD_parallel)
4168 CancelKind = CancelParallel;
4169 else if (CancelRegion == OMPD_for)
4170 CancelKind = CancelLoop;
4171 else if (CancelRegion == OMPD_sections)
4172 CancelKind = CancelSections;
4173 else {
4174 assert(CancelRegion == OMPD_taskgroup);
4175 CancelKind = CancelTaskgroup;
4176 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004177 return CancelKind;
4178}
4179
4180void CGOpenMPRuntime::emitCancellationPointCall(
4181 CodeGenFunction &CGF, SourceLocation Loc,
4182 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004183 if (!CGF.HaveInsertPoint())
4184 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004185 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
4186 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004187 if (auto *OMPRegionInfo =
4188 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00004189 if (OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004190 llvm::Value *Args[] = {
4191 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
4192 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004193 // Ignore return result until untied tasks are supported.
4194 auto *Result = CGF.EmitRuntimeCall(
4195 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
4196 // if (__kmpc_cancellationpoint()) {
4197 // __kmpc_cancel_barrier();
4198 // exit from construct;
4199 // }
4200 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4201 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4202 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4203 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4204 CGF.EmitBlock(ExitBB);
4205 // __kmpc_cancel_barrier();
Alexey Bataev25e5b442015-09-15 12:52:43 +00004206 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004207 // exit from construct;
Alexey Bataev25e5b442015-09-15 12:52:43 +00004208 auto CancelDest =
4209 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004210 CGF.EmitBranchThroughCleanup(CancelDest);
4211 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4212 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004213 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00004214}
4215
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004216void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00004217 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004218 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004219 if (!CGF.HaveInsertPoint())
4220 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004221 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
4222 // kmp_int32 cncl_kind);
4223 if (auto *OMPRegionInfo =
4224 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004225 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
4226 PrePostActionTy &) {
4227 auto &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00004228 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004229 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00004230 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
4231 // Ignore return result until untied tasks are supported.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004232 auto *Result = CGF.EmitRuntimeCall(
4233 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00004234 // if (__kmpc_cancel()) {
4235 // __kmpc_cancel_barrier();
4236 // exit from construct;
4237 // }
4238 auto *ExitBB = CGF.createBasicBlock(".cancel.exit");
4239 auto *ContBB = CGF.createBasicBlock(".cancel.continue");
4240 auto *Cmp = CGF.Builder.CreateIsNotNull(Result);
4241 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
4242 CGF.EmitBlock(ExitBB);
4243 // __kmpc_cancel_barrier();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004244 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
Alexey Bataev87933c72015-09-18 08:07:34 +00004245 // exit from construct;
4246 auto CancelDest =
4247 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
4248 CGF.EmitBranchThroughCleanup(CancelDest);
4249 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
4250 };
4251 if (IfCond)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004252 emitOMPIfClause(CGF, IfCond, ThenGen,
4253 [](CodeGenFunction &, PrePostActionTy &) {});
4254 else {
4255 RegionCodeGenTy ThenRCG(ThenGen);
4256 ThenRCG(CGF);
4257 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00004258 }
4259}
Samuel Antaobed3c462015-10-02 16:14:20 +00004260
Samuel Antaoee8fb302016-01-06 13:42:12 +00004261/// \brief Obtain information that uniquely identifies a target entry. This
Samuel Antao2de62b02016-02-13 23:35:10 +00004262/// consists of the file and device IDs as well as line number associated with
4263/// the relevant entry source location.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004264static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
4265 unsigned &DeviceID, unsigned &FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004266 unsigned &LineNum) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004267
4268 auto &SM = C.getSourceManager();
4269
4270 // The loc should be always valid and have a file ID (the user cannot use
4271 // #pragma directives in macros)
4272
4273 assert(Loc.isValid() && "Source location is expected to be always valid.");
4274 assert(Loc.isFileID() && "Source location is expected to refer to a file.");
4275
4276 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
4277 assert(PLoc.isValid() && "Source location is expected to be always valid.");
4278
4279 llvm::sys::fs::UniqueID ID;
4280 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
4281 llvm_unreachable("Source file with target region no longer exists!");
4282
4283 DeviceID = ID.getDevice();
4284 FileID = ID.getFile();
4285 LineNum = PLoc.getLine();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004286}
4287
4288void CGOpenMPRuntime::emitTargetOutlinedFunction(
4289 const OMPExecutableDirective &D, StringRef ParentName,
4290 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004291 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004292 assert(!ParentName.empty() && "Invalid target region parent name!");
4293
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004294 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
4295 IsOffloadEntry, CodeGen);
4296}
4297
4298void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
4299 const OMPExecutableDirective &D, StringRef ParentName,
4300 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
4301 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004302 // Create a unique name for the entry function using the source location
4303 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004304 //
Samuel Antao2de62b02016-02-13 23:35:10 +00004305 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00004306 //
4307 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00004308 // mangled name of the function that encloses the target region and BB is the
4309 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004310
4311 unsigned DeviceID;
4312 unsigned FileID;
4313 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004314 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004315 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004316 SmallString<64> EntryFnName;
4317 {
4318 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00004319 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
4320 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004321 }
4322
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00004323 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4324
Samuel Antaobed3c462015-10-02 16:14:20 +00004325 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004326 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00004327 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004328
4329 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
4330
4331 // If this target outline function is not an offload entry, we don't need to
4332 // register it.
4333 if (!IsOffloadEntry)
4334 return;
4335
4336 // The target region ID is used by the runtime library to identify the current
4337 // target region, so it only has to be unique and not necessarily point to
4338 // anything. It could be the pointer to the outlined function that implements
4339 // the target region, but we aren't using that so that the compiler doesn't
4340 // need to keep that, and could therefore inline the host function if proven
4341 // worthwhile during optimization. In the other hand, if emitting code for the
4342 // device, the ID has to be the function address so that it can retrieved from
4343 // the offloading entry and launched by the runtime library. We also mark the
4344 // outlined function to have external linkage in case we are emitting code for
4345 // the device, because these functions will be entry points to the device.
4346
4347 if (CGM.getLangOpts().OpenMPIsDevice) {
4348 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
4349 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage);
4350 } else
4351 OutlinedFnID = new llvm::GlobalVariable(
4352 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
4353 llvm::GlobalValue::PrivateLinkage,
4354 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id");
4355
4356 // Register the information for the entry associated with this target region.
4357 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00004358 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID);
Samuel Antaobed3c462015-10-02 16:14:20 +00004359}
4360
Samuel Antaob68e2db2016-03-03 16:20:23 +00004361/// \brief Emit the num_teams clause of an enclosed teams directive at the
4362/// target region scope. If there is no teams directive associated with the
4363/// target directive, or if there is no num_teams clause associated with the
4364/// enclosed teams directive, return nullptr.
4365static llvm::Value *
4366emitNumTeamsClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4367 CodeGenFunction &CGF,
4368 const OMPExecutableDirective &D) {
4369
4370 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4371 "teams directive expected to be "
4372 "emitted only for the host!");
4373
4374 // FIXME: For the moment we do not support combined directives with target and
4375 // teams, so we do not expect to get any num_teams clause in the provided
4376 // directive. Once we support that, this assertion can be replaced by the
4377 // actual emission of the clause expression.
4378 assert(D.getSingleClause<OMPNumTeamsClause>() == nullptr &&
4379 "Not expecting clause in directive.");
4380
4381 // If the current target region has a teams region enclosed, we need to get
4382 // the number of teams to pass to the runtime function call. This is done
4383 // by generating the expression in a inlined region. This is required because
4384 // the expression is captured in the enclosing target environment when the
4385 // teams directive is not combined with target.
4386
4387 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4388
4389 // FIXME: Accommodate other combined directives with teams when they become
4390 // available.
4391 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) {
4392 if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) {
4393 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4394 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4395 llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams());
4396 return CGF.Builder.CreateIntCast(NumTeams, CGF.Int32Ty,
4397 /*IsSigned=*/true);
4398 }
4399
4400 // If we have an enclosed teams directive but no num_teams clause we use
4401 // the default value 0.
4402 return CGF.Builder.getInt32(0);
4403 }
4404
4405 // No teams associated with the directive.
4406 return nullptr;
4407}
4408
4409/// \brief Emit the thread_limit clause of an enclosed teams directive at the
4410/// target region scope. If there is no teams directive associated with the
4411/// target directive, or if there is no thread_limit clause associated with the
4412/// enclosed teams directive, return nullptr.
4413static llvm::Value *
4414emitThreadLimitClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime,
4415 CodeGenFunction &CGF,
4416 const OMPExecutableDirective &D) {
4417
4418 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the "
4419 "teams directive expected to be "
4420 "emitted only for the host!");
4421
4422 // FIXME: For the moment we do not support combined directives with target and
4423 // teams, so we do not expect to get any thread_limit clause in the provided
4424 // directive. Once we support that, this assertion can be replaced by the
4425 // actual emission of the clause expression.
4426 assert(D.getSingleClause<OMPThreadLimitClause>() == nullptr &&
4427 "Not expecting clause in directive.");
4428
4429 // If the current target region has a teams region enclosed, we need to get
4430 // the thread limit to pass to the runtime function call. This is done
4431 // by generating the expression in a inlined region. This is required because
4432 // the expression is captured in the enclosing target environment when the
4433 // teams directive is not combined with target.
4434
4435 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4436
4437 // FIXME: Accommodate other combined directives with teams when they become
4438 // available.
4439 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) {
4440 if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) {
4441 CGOpenMPInnerExprInfo CGInfo(CGF, CS);
4442 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
4443 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit());
4444 return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty,
4445 /*IsSigned=*/true);
4446 }
4447
4448 // If we have an enclosed teams directive but no thread_limit clause we use
4449 // the default value 0.
4450 return CGF.Builder.getInt32(0);
4451 }
4452
4453 // No teams associated with the directive.
4454 return nullptr;
4455}
4456
Samuel Antaobed3c462015-10-02 16:14:20 +00004457void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
4458 const OMPExecutableDirective &D,
4459 llvm::Value *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00004460 llvm::Value *OutlinedFnID,
Samuel Antaobed3c462015-10-02 16:14:20 +00004461 const Expr *IfCond, const Expr *Device,
4462 ArrayRef<llvm::Value *> CapturedVars) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00004463 if (!CGF.HaveInsertPoint())
4464 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00004465 /// \brief Values for bit flags used to specify the mapping type for
4466 /// offloading.
4467 enum OpenMPOffloadMappingFlags {
4468 /// \brief Allocate memory on the device and move data from host to device.
4469 OMP_MAP_TO = 0x01,
4470 /// \brief Allocate memory on the device and move data from device to host.
4471 OMP_MAP_FROM = 0x02,
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004472 /// \brief The element passed to the device is a pointer.
4473 OMP_MAP_PTR = 0x20,
4474 /// \brief Pass the element to the device by value.
4475 OMP_MAP_BYCOPY = 0x80,
Samuel Antaobed3c462015-10-02 16:14:20 +00004476 };
4477
4478 enum OpenMPOffloadingReservedDeviceIDs {
4479 /// \brief Device ID if the device was not defined, runtime should get it
4480 /// from environment variables in the spec.
4481 OMP_DEVICEID_UNDEF = -1,
4482 };
4483
Samuel Antaoee8fb302016-01-06 13:42:12 +00004484 assert(OutlinedFn && "Invalid outlined function!");
4485
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004486 auto &Ctx = CGF.getContext();
4487
Samuel Antaobed3c462015-10-02 16:14:20 +00004488 // Fill up the arrays with the all the captured variables.
4489 SmallVector<llvm::Value *, 16> BasePointers;
4490 SmallVector<llvm::Value *, 16> Pointers;
4491 SmallVector<llvm::Value *, 16> Sizes;
4492 SmallVector<unsigned, 16> MapTypes;
4493
4494 bool hasVLACaptures = false;
4495
4496 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
4497 auto RI = CS.getCapturedRecordDecl()->field_begin();
4498 // auto II = CS.capture_init_begin();
4499 auto CV = CapturedVars.begin();
4500 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
4501 CE = CS.capture_end();
4502 CI != CE; ++CI, ++RI, ++CV) {
4503 StringRef Name;
4504 QualType Ty;
4505 llvm::Value *BasePointer;
4506 llvm::Value *Pointer;
4507 llvm::Value *Size;
4508 unsigned MapType;
4509
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004510 // VLA sizes are passed to the outlined region by copy.
Samuel Antaobed3c462015-10-02 16:14:20 +00004511 if (CI->capturesVariableArrayType()) {
4512 BasePointer = Pointer = *CV;
Alexey Bataev1189bd02016-01-26 12:20:39 +00004513 Size = CGF.getTypeSize(RI->getType());
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004514 // Copy to the device as an argument. No need to retrieve it.
4515 MapType = OMP_MAP_BYCOPY;
Samuel Antaobed3c462015-10-02 16:14:20 +00004516 hasVLACaptures = true;
Samuel Antaobed3c462015-10-02 16:14:20 +00004517 } else if (CI->capturesThis()) {
4518 BasePointer = Pointer = *CV;
4519 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr());
Alexey Bataev1189bd02016-01-26 12:20:39 +00004520 Size = CGF.getTypeSize(PtrTy->getPointeeType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004521 // Default map type.
4522 MapType = OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004523 } else if (CI->capturesVariableByCopy()) {
4524 MapType = OMP_MAP_BYCOPY;
4525 if (!RI->getType()->isAnyPointerType()) {
4526 // If the field is not a pointer, we need to save the actual value and
4527 // load it as a void pointer.
4528 auto DstAddr = CGF.CreateMemTemp(
4529 Ctx.getUIntPtrType(),
4530 Twine(CI->getCapturedVar()->getName()) + ".casted");
4531 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
4532
4533 auto *SrcAddrVal = CGF.EmitScalarConversion(
4534 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
4535 Ctx.getPointerType(RI->getType()), SourceLocation());
4536 LValue SrcLV =
4537 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType());
4538
4539 // Store the value using the source type pointer.
4540 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV);
4541
4542 // Load the value using the destination type pointer.
4543 BasePointer = Pointer =
4544 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
4545 } else {
4546 MapType |= OMP_MAP_PTR;
4547 BasePointer = Pointer = *CV;
4548 }
Alexey Bataev1189bd02016-01-26 12:20:39 +00004549 Size = CGF.getTypeSize(RI->getType());
Samuel Antaobed3c462015-10-02 16:14:20 +00004550 } else {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004551 assert(CI->capturesVariable() && "Expected captured reference.");
Samuel Antaobed3c462015-10-02 16:14:20 +00004552 BasePointer = Pointer = *CV;
4553
4554 const ReferenceType *PtrTy =
4555 cast<ReferenceType>(RI->getType().getTypePtr());
4556 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00004557 Size = CGF.getTypeSize(ElementType);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004558 // The default map type for a scalar/complex type is 'to' because by
4559 // default the value doesn't have to be retrieved. For an aggregate type,
4560 // the default is 'tofrom'.
4561 MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
4562 : OMP_MAP_TO;
4563 if (ElementType->isAnyPointerType())
4564 MapType |= OMP_MAP_PTR;
Samuel Antaobed3c462015-10-02 16:14:20 +00004565 }
4566
4567 BasePointers.push_back(BasePointer);
4568 Pointers.push_back(Pointer);
4569 Sizes.push_back(Size);
4570 MapTypes.push_back(MapType);
4571 }
4572
4573 // Keep track on whether the host function has to be executed.
4574 auto OffloadErrorQType =
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004575 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004576 auto OffloadError = CGF.MakeAddrLValue(
4577 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
4578 OffloadErrorQType);
4579 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
4580 OffloadError);
4581
4582 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004583 auto &&ThenGen = [&Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes,
Alexey Bataevf539faa2016-03-28 12:58:34 +00004584 hasVLACaptures, Device, OutlinedFnID, OffloadError,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004585 OffloadErrorQType,
4586 &D](CodeGenFunction &CGF, PrePostActionTy &) {
4587 auto &RT = CGF.CGM.getOpenMPRuntime();
Samuel Antaobed3c462015-10-02 16:14:20 +00004588 unsigned PointerNumVal = BasePointers.size();
4589 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal);
4590 llvm::Value *BasePointersArray;
4591 llvm::Value *PointersArray;
4592 llvm::Value *SizesArray;
4593 llvm::Value *MapTypesArray;
4594
4595 if (PointerNumVal) {
4596 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004597 QualType PointerArrayType = Ctx.getConstantArrayType(
4598 Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004599 /*IndexTypeQuals=*/0);
4600
4601 BasePointersArray =
4602 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
4603 PointersArray =
4604 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
4605
4606 // If we don't have any VLA types, we can use a constant array for the map
4607 // sizes, otherwise we need to fill up the arrays as we do for the
4608 // pointers.
4609 if (hasVLACaptures) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004610 QualType SizeArrayType = Ctx.getConstantArrayType(
4611 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
Samuel Antaobed3c462015-10-02 16:14:20 +00004612 /*IndexTypeQuals=*/0);
4613 SizesArray =
4614 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
4615 } else {
4616 // We expect all the sizes to be constant, so we collect them to create
4617 // a constant array.
4618 SmallVector<llvm::Constant *, 16> ConstSizes;
4619 for (auto S : Sizes)
4620 ConstSizes.push_back(cast<llvm::Constant>(S));
4621
4622 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004623 llvm::ArrayType::get(CGF.CGM.SizeTy, ConstSizes.size()),
4624 ConstSizes);
Samuel Antaobed3c462015-10-02 16:14:20 +00004625 auto *SizesArrayGbl = new llvm::GlobalVariable(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004626 CGF.CGM.getModule(), SizesArrayInit->getType(),
Samuel Antaobed3c462015-10-02 16:14:20 +00004627 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4628 SizesArrayInit, ".offload_sizes");
4629 SizesArrayGbl->setUnnamedAddr(true);
4630 SizesArray = SizesArrayGbl;
4631 }
4632
4633 // The map types are always constant so we don't need to generate code to
4634 // fill arrays. Instead, we create an array constant.
4635 llvm::Constant *MapTypesArrayInit =
4636 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
4637 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004638 CGF.CGM.getModule(), MapTypesArrayInit->getType(),
Samuel Antaobed3c462015-10-02 16:14:20 +00004639 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
4640 MapTypesArrayInit, ".offload_maptypes");
4641 MapTypesArrayGbl->setUnnamedAddr(true);
4642 MapTypesArray = MapTypesArrayGbl;
4643
4644 for (unsigned i = 0; i < PointerNumVal; ++i) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004645 llvm::Value *BPVal = BasePointers[i];
4646 if (BPVal->getType()->isPointerTy())
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004647 BPVal = CGF.Builder.CreateBitCast(BPVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004648 else {
4649 assert(BPVal->getType()->isIntegerTy() &&
4650 "If not a pointer, the value type must be an integer.");
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004651 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004652 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004653 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004654 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal),
Samuel Antaobed3c462015-10-02 16:14:20 +00004655 BasePointersArray, 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004656 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4657 CGF.Builder.CreateStore(BPVal, BPAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004658
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004659 llvm::Value *PVal = Pointers[i];
4660 if (PVal->getType()->isPointerTy())
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004661 PVal = CGF.Builder.CreateBitCast(PVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004662 else {
4663 assert(PVal->getType()->isIntegerTy() &&
4664 "If not a pointer, the value type must be an integer.");
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004665 PVal = CGF.Builder.CreateIntToPtr(PVal, CGF.VoidPtrTy);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004666 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004667 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004668 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), PointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004669 0, i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004670 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
4671 CGF.Builder.CreateStore(PVal, PAddr);
Samuel Antaobed3c462015-10-02 16:14:20 +00004672
4673 if (hasVLACaptures) {
4674 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004675 llvm::ArrayType::get(CGF.SizeTy, PointerNumVal), SizesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004676 /*Idx0=*/0,
4677 /*Idx1=*/i);
Samuel Antao4af1b7b2015-12-02 17:44:43 +00004678 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
Samuel Antaobed3c462015-10-02 16:14:20 +00004679 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004680 Sizes[i], CGF.SizeTy, /*isSigned=*/true),
Samuel Antaobed3c462015-10-02 16:14:20 +00004681 SAddr);
4682 }
4683 }
4684
4685 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004686 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), BasePointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004687 /*Idx0=*/0, /*Idx1=*/0);
4688 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004689 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), PointersArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004690 /*Idx0=*/0,
4691 /*Idx1=*/0);
4692 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004693 llvm::ArrayType::get(CGF.SizeTy, PointerNumVal), SizesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004694 /*Idx0=*/0, /*Idx1=*/0);
4695 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004696 llvm::ArrayType::get(CGF.Int32Ty, PointerNumVal), MapTypesArray,
Samuel Antaobed3c462015-10-02 16:14:20 +00004697 /*Idx0=*/0,
4698 /*Idx1=*/0);
4699
4700 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004701 BasePointersArray = llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy);
4702 PointersArray = llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy);
4703 SizesArray = llvm::ConstantPointerNull::get(CGF.SizeTy->getPointerTo());
Samuel Antaobed3c462015-10-02 16:14:20 +00004704 MapTypesArray =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004705 llvm::ConstantPointerNull::get(CGF.Int32Ty->getPointerTo());
Samuel Antaobed3c462015-10-02 16:14:20 +00004706 }
4707
4708 // On top of the arrays that were filled up, the target offloading call
4709 // takes as arguments the device id as well as the host pointer. The host
4710 // pointer is used by the runtime library to identify the current target
4711 // region, so it only has to be unique and not necessarily point to
4712 // anything. It could be the pointer to the outlined function that
4713 // implements the target region, but we aren't using that so that the
4714 // compiler doesn't need to keep that, and could therefore inline the host
4715 // function if proven worthwhile during optimization.
4716
Samuel Antaoee8fb302016-01-06 13:42:12 +00004717 // From this point on, we need to have an ID of the target region defined.
4718 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00004719
4720 // Emit device ID if any.
4721 llvm::Value *DeviceID;
4722 if (Device)
4723 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004724 CGF.Int32Ty, /*isSigned=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004725 else
4726 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
4727
Samuel Antaob68e2db2016-03-03 16:20:23 +00004728 // Return value of the runtime offloading call.
4729 llvm::Value *Return;
4730
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004731 auto *NumTeams = emitNumTeamsClauseForTargetDirective(RT, CGF, D);
4732 auto *ThreadLimit = emitThreadLimitClauseForTargetDirective(RT, CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004733
4734 // If we have NumTeams defined this means that we have an enclosed teams
4735 // region. Therefore we also expect to have ThreadLimit defined. These two
4736 // values should be defined in the presence of a teams directive, regardless
4737 // of having any clauses associated. If the user is using teams but no
4738 // clauses, these two values will be the default that should be passed to
4739 // the runtime library - a 32-bit integer with the value zero.
4740 if (NumTeams) {
4741 assert(ThreadLimit && "Thread limit expression should be available along "
4742 "with number of teams.");
4743 llvm::Value *OffloadingArgs[] = {
4744 DeviceID, OutlinedFnID, PointerNum,
4745 BasePointersArray, PointersArray, SizesArray,
4746 MapTypesArray, NumTeams, ThreadLimit};
4747 Return = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004748 RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004749 } else {
4750 llvm::Value *OffloadingArgs[] = {
4751 DeviceID, OutlinedFnID, PointerNum, BasePointersArray,
4752 PointersArray, SizesArray, MapTypesArray};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004753 Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target),
Samuel Antaob68e2db2016-03-03 16:20:23 +00004754 OffloadingArgs);
4755 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004756
4757 CGF.EmitStoreOfScalar(Return, OffloadError);
4758 };
4759
Samuel Antaoee8fb302016-01-06 13:42:12 +00004760 // Notify that the host version must be executed.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004761 auto &&ElseGen = [OffloadError](CodeGenFunction &CGF, PrePostActionTy &) {
4762 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/-1u),
Samuel Antaoee8fb302016-01-06 13:42:12 +00004763 OffloadError);
4764 };
4765
4766 // If we have a target function ID it means that we need to support
4767 // offloading, otherwise, just execute on the host. We need to execute on host
4768 // regardless of the conditional in the if clause if, e.g., the user do not
4769 // specify target triples.
4770 if (OutlinedFnID) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004771 if (IfCond)
Samuel Antaoee8fb302016-01-06 13:42:12 +00004772 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004773 else {
4774 RegionCodeGenTy ThenRCG(ThenGen);
4775 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00004776 }
4777 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004778 RegionCodeGenTy ElseRCG(ElseGen);
4779 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00004780 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004781
4782 // Check the error code and execute the host version if required.
4783 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
4784 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
4785 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
4786 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
4787 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
4788
4789 CGF.EmitBlock(OffloadFailedBlock);
4790 CGF.Builder.CreateCall(OutlinedFn, BasePointers);
4791 CGF.EmitBranch(OffloadContBlock);
4792
4793 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00004794}
Samuel Antaoee8fb302016-01-06 13:42:12 +00004795
4796void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
4797 StringRef ParentName) {
4798 if (!S)
4799 return;
4800
4801 // If we find a OMP target directive, codegen the outline function and
4802 // register the result.
4803 // FIXME: Add other directives with target when they become supported.
4804 bool isTargetDirective = isa<OMPTargetDirective>(S);
4805
4806 if (isTargetDirective) {
4807 auto *E = cast<OMPExecutableDirective>(S);
4808 unsigned DeviceID;
4809 unsigned FileID;
4810 unsigned Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004811 getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00004812 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004813
4814 // Is this a target region that should not be emitted as an entry point? If
4815 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00004816 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
4817 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004818 return;
4819
4820 llvm::Function *Fn;
4821 llvm::Constant *Addr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004822 std::tie(Fn, Addr) =
4823 CodeGenFunction::EmitOMPTargetDirectiveOutlinedFunction(
4824 CGM, cast<OMPTargetDirective>(*E), ParentName,
4825 /*isOffloadEntry=*/true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004826 assert(Fn && Addr && "Target region emission failed.");
4827 return;
4828 }
4829
4830 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) {
4831 if (!E->getAssociatedStmt())
4832 return;
4833
4834 scanForTargetRegionsFunctions(
4835 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(),
4836 ParentName);
4837 return;
4838 }
4839
4840 // If this is a lambda function, look into its body.
4841 if (auto *L = dyn_cast<LambdaExpr>(S))
4842 S = L->getBody();
4843
4844 // Keep looking for target regions recursively.
4845 for (auto *II : S->children())
4846 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004847}
4848
4849bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
4850 auto &FD = *cast<FunctionDecl>(GD.getDecl());
4851
4852 // If emitting code for the host, we do not process FD here. Instead we do
4853 // the normal code generation.
4854 if (!CGM.getLangOpts().OpenMPIsDevice)
4855 return false;
4856
4857 // Try to detect target regions in the function.
4858 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
4859
4860 // We should not emit any function othen that the ones created during the
4861 // scanning. Therefore, we signal that this function is completely dealt
4862 // with.
4863 return true;
4864}
4865
4866bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
4867 if (!CGM.getLangOpts().OpenMPIsDevice)
4868 return false;
4869
4870 // Check if there are Ctors/Dtors in this declaration and look for target
4871 // regions in it. We use the complete variant to produce the kernel name
4872 // mangling.
4873 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
4874 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
4875 for (auto *Ctor : RD->ctors()) {
4876 StringRef ParentName =
4877 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
4878 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
4879 }
4880 auto *Dtor = RD->getDestructor();
4881 if (Dtor) {
4882 StringRef ParentName =
4883 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
4884 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
4885 }
4886 }
4887
4888 // If we are in target mode we do not emit any global (declare target is not
4889 // implemented yet). Therefore we signal that GD was processed in this case.
4890 return true;
4891}
4892
4893bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
4894 auto *VD = GD.getDecl();
4895 if (isa<FunctionDecl>(VD))
4896 return emitTargetFunctions(GD);
4897
4898 return emitTargetGlobalVariable(GD);
4899}
4900
4901llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
4902 // If we have offloading in the current module, we need to emit the entries
4903 // now and register the offloading descriptor.
4904 createOffloadEntriesAndInfoMetadata();
4905
4906 // Create and register the offloading binary descriptors. This is the main
4907 // entity that captures all the information about offloading in the current
4908 // compilation unit.
4909 return createOffloadingBinaryDescriptorRegistration();
4910}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004911
4912void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
4913 const OMPExecutableDirective &D,
4914 SourceLocation Loc,
4915 llvm::Value *OutlinedFn,
4916 ArrayRef<llvm::Value *> CapturedVars) {
4917 if (!CGF.HaveInsertPoint())
4918 return;
4919
4920 auto *RTLoc = emitUpdateLocation(CGF, Loc);
4921 CodeGenFunction::RunCleanupsScope Scope(CGF);
4922
4923 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
4924 llvm::Value *Args[] = {
4925 RTLoc,
4926 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
4927 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
4928 llvm::SmallVector<llvm::Value *, 16> RealArgs;
4929 RealArgs.append(std::begin(Args), std::end(Args));
4930 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
4931
4932 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
4933 CGF.EmitRuntimeCall(RTLFn, RealArgs);
4934}
4935
4936void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00004937 const Expr *NumTeams,
4938 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004939 SourceLocation Loc) {
4940 if (!CGF.HaveInsertPoint())
4941 return;
4942
4943 auto *RTLoc = emitUpdateLocation(CGF, Loc);
4944
Carlo Bertollic6872252016-04-04 15:55:02 +00004945 llvm::Value *NumTeamsVal =
4946 (NumTeams)
4947 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
4948 CGF.CGM.Int32Ty, /* isSigned = */ true)
4949 : CGF.Builder.getInt32(0);
4950
4951 llvm::Value *ThreadLimitVal =
4952 (ThreadLimit)
4953 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
4954 CGF.CGM.Int32Ty, /* isSigned = */ true)
4955 : CGF.Builder.getInt32(0);
4956
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004957 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00004958 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
4959 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004960 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
4961 PushNumTeamsArgs);
4962}