blob: 75971d853ab43c50ede489e3e967894d32a5ded3 [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Alexey Bataev9959db52014-05-06 10:08:46 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This provides a class for OpenMP runtime code generation.
10//
11//===----------------------------------------------------------------------===//
12
Samuel Antaoee8fb302016-01-06 13:42:12 +000013#include "CGCXXABI.h"
14#include "CGCleanup.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000015#include "CGOpenMPRuntime.h"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000016#include "CGRecordLayout.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000017#include "CodeGenFunction.h"
John McCall5ad74072017-03-02 20:04:19 +000018#include "clang/CodeGen/ConstantInitBuilder.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000019#include "clang/AST/Decl.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000020#include "clang/AST/StmtOpenMP.h"
Richard Smithbf5bcf22018-06-26 23:20:26 +000021#include "clang/Basic/BitmaskEnum.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000022#include "llvm/ADT/ArrayRef.h"
Teresa Johnsonffc4e242016-11-11 05:35:12 +000023#include "llvm/Bitcode/BitcodeReader.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000024#include "llvm/IR/DerivedTypes.h"
25#include "llvm/IR/GlobalValue.h"
26#include "llvm/IR/Value.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000027#include "llvm/Support/Format.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000028#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000029#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000030
31using namespace clang;
32using namespace CodeGen;
33
Benjamin Kramerc52193f2014-10-10 13:57:57 +000034namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000035/// Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000036class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
37public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000038 /// Kinds of OpenMP regions used in codegen.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000039 enum CGOpenMPRegionKind {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000040 /// Region with outlined function for standalone 'parallel'
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000041 /// directive.
42 ParallelOutlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000043 /// Region with outlined function for standalone 'task' directive.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000044 TaskOutlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000045 /// Region for constructs that do not require function outlining,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000046 /// like 'for', 'sections', 'atomic' etc. directives.
47 InlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000048 /// Region with outlined function for standalone 'target' directive.
Samuel Antaobed3c462015-10-02 16:14:20 +000049 TargetRegion,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000050 };
Alexey Bataev18095712014-10-10 12:19:54 +000051
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000052 CGOpenMPRegionInfo(const CapturedStmt &CS,
53 const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000054 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
55 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000056 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000057 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000058
59 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000060 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
61 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000062 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000063 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000064
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000065 /// Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000066 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000067 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000068
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000069 /// Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000070 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000071
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000072 /// Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000073 /// \return LValue for thread id variable. This LValue always has type int32*.
74 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000075
Alexey Bataev48591dd2016-04-20 04:01:36 +000076 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
77
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000078 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000079
Alexey Bataev81c7ea02015-07-03 09:56:58 +000080 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
81
Alexey Bataev25e5b442015-09-15 12:52:43 +000082 bool hasCancel() const { return HasCancel; }
83
Alexey Bataev18095712014-10-10 12:19:54 +000084 static bool classof(const CGCapturedStmtInfo *Info) {
85 return Info->getKind() == CR_OpenMP;
86 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000087
Alexey Bataev48591dd2016-04-20 04:01:36 +000088 ~CGOpenMPRegionInfo() override = default;
89
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000090protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000091 CGOpenMPRegionKind RegionKind;
Hans Wennborg45c74392016-01-12 20:54:36 +000092 RegionCodeGenTy CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000093 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +000094 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000095};
Alexey Bataev18095712014-10-10 12:19:54 +000096
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000097/// API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +000098class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000099public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000100 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000101 const RegionCodeGenTy &CodeGen,
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000102 OpenMPDirectiveKind Kind, bool HasCancel,
103 StringRef HelperName)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000104 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
105 HasCancel),
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000106 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000107 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
108 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000109
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000110 /// Get a variable or parameter for storing global thread id
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000111 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000112 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000113
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000114 /// Get the name of the capture helper.
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000115 StringRef getHelperName() const override { return HelperName; }
Alexey Bataev18095712014-10-10 12:19:54 +0000116
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000117 static bool classof(const CGCapturedStmtInfo *Info) {
118 return CGOpenMPRegionInfo::classof(Info) &&
119 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
120 ParallelOutlinedRegion;
121 }
122
Alexey Bataev18095712014-10-10 12:19:54 +0000123private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000124 /// A variable or parameter storing global thread id for OpenMP
Alexey Bataev18095712014-10-10 12:19:54 +0000125 /// constructs.
126 const VarDecl *ThreadIDVar;
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000127 StringRef HelperName;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000128};
129
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000130/// API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000131class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000132public:
Alexey Bataev48591dd2016-04-20 04:01:36 +0000133 class UntiedTaskActionTy final : public PrePostActionTy {
134 bool Untied;
135 const VarDecl *PartIDVar;
136 const RegionCodeGenTy UntiedCodeGen;
137 llvm::SwitchInst *UntiedSwitch = nullptr;
138
139 public:
140 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
141 const RegionCodeGenTy &UntiedCodeGen)
142 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
143 void Enter(CodeGenFunction &CGF) override {
144 if (Untied) {
145 // Emit task switching point.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000146 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev48591dd2016-04-20 04:01:36 +0000147 CGF.GetAddrOfLocalVar(PartIDVar),
148 PartIDVar->getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000149 llvm::Value *Res =
150 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation());
151 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done.");
Alexey Bataev48591dd2016-04-20 04:01:36 +0000152 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
153 CGF.EmitBlock(DoneBB);
154 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
155 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
156 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
157 CGF.Builder.GetInsertBlock());
158 emitUntiedSwitch(CGF);
159 }
160 }
161 void emitUntiedSwitch(CodeGenFunction &CGF) const {
162 if (Untied) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000163 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev48591dd2016-04-20 04:01:36 +0000164 CGF.GetAddrOfLocalVar(PartIDVar),
165 PartIDVar->getType()->castAs<PointerType>());
166 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
167 PartIdLVal);
168 UntiedCodeGen(CGF);
169 CodeGenFunction::JumpDest CurPoint =
170 CGF.getJumpDestInCurrentScope(".untied.next.");
171 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
172 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
173 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
174 CGF.Builder.GetInsertBlock());
175 CGF.EmitBranchThroughCleanup(CurPoint);
176 CGF.EmitBlock(CurPoint.getBlock());
177 }
178 }
179 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
180 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000181 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000182 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000183 const RegionCodeGenTy &CodeGen,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000184 OpenMPDirectiveKind Kind, bool HasCancel,
185 const UntiedTaskActionTy &Action)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000186 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev48591dd2016-04-20 04:01:36 +0000187 ThreadIDVar(ThreadIDVar), Action(Action) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000188 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
189 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000190
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000191 /// Get a variable or parameter for storing global thread id
Alexey Bataev62b63b12015-03-10 07:28:44 +0000192 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000193 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000194
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000195 /// Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000196 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000197
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000198 /// Get the name of the capture helper.
Alexey Bataev62b63b12015-03-10 07:28:44 +0000199 StringRef getHelperName() const override { return ".omp_outlined."; }
200
Alexey Bataev48591dd2016-04-20 04:01:36 +0000201 void emitUntiedSwitch(CodeGenFunction &CGF) override {
202 Action.emitUntiedSwitch(CGF);
203 }
204
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000205 static bool classof(const CGCapturedStmtInfo *Info) {
206 return CGOpenMPRegionInfo::classof(Info) &&
207 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
208 TaskOutlinedRegion;
209 }
210
Alexey Bataev62b63b12015-03-10 07:28:44 +0000211private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000212 /// A variable or parameter storing global thread id for OpenMP
Alexey Bataev62b63b12015-03-10 07:28:44 +0000213 /// constructs.
214 const VarDecl *ThreadIDVar;
Alexey Bataev48591dd2016-04-20 04:01:36 +0000215 /// Action for emitting code for untied tasks.
216 const UntiedTaskActionTy &Action;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000217};
218
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000219/// API for inlined captured statement code generation in OpenMP
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000220/// constructs.
221class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
222public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000223 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000224 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000225 OpenMPDirectiveKind Kind, bool HasCancel)
226 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
227 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000228 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000229
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000230 // Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000231 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000232 if (OuterRegionInfo)
233 return OuterRegionInfo->getContextValue();
234 llvm_unreachable("No context value for inlined OpenMP region");
235 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000236
Hans Wennborg7eb54642015-09-10 17:07:54 +0000237 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000238 if (OuterRegionInfo) {
239 OuterRegionInfo->setContextValue(V);
240 return;
241 }
242 llvm_unreachable("No context value for inlined OpenMP region");
243 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000244
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000245 /// Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000246 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000247 if (OuterRegionInfo)
248 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000249 // If there is no outer outlined region,no need to lookup in a list of
250 // captured variables, we can use the original one.
251 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000252 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000253
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000254 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000255 if (OuterRegionInfo)
256 return OuterRegionInfo->getThisFieldDecl();
257 return nullptr;
258 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000259
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000260 /// Get a variable or parameter for storing global thread id
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000261 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000262 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000263 if (OuterRegionInfo)
264 return OuterRegionInfo->getThreadIDVariable();
265 return nullptr;
266 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000267
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000268 /// Get an LValue for the current ThreadID variable.
Alexey Bataev311a9282017-10-12 13:51:32 +0000269 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override {
270 if (OuterRegionInfo)
271 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
272 llvm_unreachable("No LValue for inlined OpenMP construct");
273 }
274
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000275 /// Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000276 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000277 if (auto *OuterRegionInfo = getOldCSI())
278 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000279 llvm_unreachable("No helper name for inlined OpenMP construct");
280 }
281
Alexey Bataev48591dd2016-04-20 04:01:36 +0000282 void emitUntiedSwitch(CodeGenFunction &CGF) override {
283 if (OuterRegionInfo)
284 OuterRegionInfo->emitUntiedSwitch(CGF);
285 }
286
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000287 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
288
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000289 static bool classof(const CGCapturedStmtInfo *Info) {
290 return CGOpenMPRegionInfo::classof(Info) &&
291 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
292 }
293
Alexey Bataev48591dd2016-04-20 04:01:36 +0000294 ~CGOpenMPInlinedRegionInfo() override = default;
295
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000296private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000297 /// CodeGen info about outer OpenMP region.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000298 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
299 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000300};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000301
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000302/// API for captured statement code generation in OpenMP target
Samuel Antaobed3c462015-10-02 16:14:20 +0000303/// constructs. For this captures, implicit parameters are used instead of the
Samuel Antaoee8fb302016-01-06 13:42:12 +0000304/// captured fields. The name of the target region has to be unique in a given
305/// application so it is provided by the client, because only the client has
306/// the information to generate that.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000307class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
Samuel Antaobed3c462015-10-02 16:14:20 +0000308public:
309 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000310 const RegionCodeGenTy &CodeGen, StringRef HelperName)
Samuel Antaobed3c462015-10-02 16:14:20 +0000311 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000312 /*HasCancel=*/false),
313 HelperName(HelperName) {}
Samuel Antaobed3c462015-10-02 16:14:20 +0000314
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000315 /// This is unused for target regions because each starts executing
Samuel Antaobed3c462015-10-02 16:14:20 +0000316 /// with a single thread.
317 const VarDecl *getThreadIDVariable() const override { return nullptr; }
318
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000319 /// Get the name of the capture helper.
Samuel Antaoee8fb302016-01-06 13:42:12 +0000320 StringRef getHelperName() const override { return HelperName; }
Samuel Antaobed3c462015-10-02 16:14:20 +0000321
322 static bool classof(const CGCapturedStmtInfo *Info) {
323 return CGOpenMPRegionInfo::classof(Info) &&
324 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
325 }
Samuel Antaoee8fb302016-01-06 13:42:12 +0000326
327private:
328 StringRef HelperName;
Samuel Antaobed3c462015-10-02 16:14:20 +0000329};
330
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000331static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000332 llvm_unreachable("No codegen for expressions");
333}
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000334/// API for generation of expressions captured in a innermost OpenMP
Samuel Antaob68e2db2016-03-03 16:20:23 +0000335/// region.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000336class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000337public:
338 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
339 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
340 OMPD_unknown,
341 /*HasCancel=*/false),
342 PrivScope(CGF) {
343 // Make sure the globals captured in the provided statement are local by
344 // using the privatization logic. We assume the same variable is not
345 // captured more than once.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000346 for (const auto &C : CS.captures()) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000347 if (!C.capturesVariable() && !C.capturesVariableByCopy())
348 continue;
349
350 const VarDecl *VD = C.getCapturedVar();
351 if (VD->isLocalVarDeclOrParm())
352 continue;
353
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000354 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
Samuel Antaob68e2db2016-03-03 16:20:23 +0000355 /*RefersToEnclosingVariableOrCapture=*/false,
356 VD->getType().getNonReferenceType(), VK_LValue,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000357 C.getLocation());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000358 PrivScope.addPrivate(
359 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(); });
Samuel Antaob68e2db2016-03-03 16:20:23 +0000360 }
361 (void)PrivScope.Privatize();
362 }
363
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000364 /// Lookup the captured field decl for a variable.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000365 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000366 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
Samuel Antaob68e2db2016-03-03 16:20:23 +0000367 return FD;
368 return nullptr;
369 }
370
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000371 /// Emit the captured statement body.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000372 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
373 llvm_unreachable("No body for expressions");
374 }
375
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000376 /// Get a variable or parameter for storing global thread id
Samuel Antaob68e2db2016-03-03 16:20:23 +0000377 /// inside OpenMP construct.
378 const VarDecl *getThreadIDVariable() const override {
379 llvm_unreachable("No thread id for expressions");
380 }
381
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000382 /// Get the name of the capture helper.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000383 StringRef getHelperName() const override {
384 llvm_unreachable("No helper name for expressions");
385 }
386
387 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
388
389private:
390 /// Private scope to capture global variables.
391 CodeGenFunction::OMPPrivateScope PrivScope;
392};
393
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000394/// RAII for emitting code of OpenMP constructs.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000395class InlinedOpenMPRegionRAII {
396 CodeGenFunction &CGF;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000397 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
398 FieldDecl *LambdaThisCaptureField = nullptr;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000399 const CodeGen::CGBlockInfo *BlockInfo = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000400
401public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000402 /// Constructs region for combined constructs.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000403 /// \param CodeGen Code generation sequence for combined directives. Includes
404 /// a list of functions used for code generation of implicitly inlined
405 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000406 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000407 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000408 : CGF(CGF) {
409 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000410 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
411 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000412 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
413 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
414 CGF.LambdaThisCaptureField = nullptr;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000415 BlockInfo = CGF.BlockInfo;
416 CGF.BlockInfo = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000417 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000418
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000419 ~InlinedOpenMPRegionRAII() {
420 // Restore original CapturedStmtInfo only if we're done with code emission.
421 auto *OldCSI =
422 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
423 delete CGF.CapturedStmtInfo;
424 CGF.CapturedStmtInfo = OldCSI;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000425 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
426 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000427 CGF.BlockInfo = BlockInfo;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000428 }
429};
430
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000431/// Values for bit flags used in the ident_t to describe the fields.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000432/// All enumeric elements are named and described in accordance with the code
James Y Knight5d71fc52019-01-29 16:37:27 +0000433/// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev0f87dbe2017-08-14 17:56:13 +0000434enum OpenMPLocationFlags : unsigned {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000435 /// Use trampoline for internal microtask.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000436 OMP_IDENT_IMD = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000437 /// Use c-style ident structure.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000438 OMP_IDENT_KMPC = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000439 /// Atomic reduction option for kmpc_reduce.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000440 OMP_ATOMIC_REDUCE = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000441 /// Explicit 'barrier' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000442 OMP_IDENT_BARRIER_EXPL = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000443 /// Implicit barrier in code.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000444 OMP_IDENT_BARRIER_IMPL = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000445 /// Implicit barrier in 'for' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000446 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000447 /// Implicit barrier in 'sections' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000448 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000449 /// Implicit barrier in 'single' directive.
Alexey Bataev0f87dbe2017-08-14 17:56:13 +0000450 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
451 /// Call of __kmp_for_static_init for static loop.
452 OMP_IDENT_WORK_LOOP = 0x200,
453 /// Call of __kmp_for_static_init for sections.
454 OMP_IDENT_WORK_SECTIONS = 0x400,
455 /// Call of __kmp_for_static_init for distribute.
456 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
457 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)
Alexey Bataev50b3c952016-02-19 10:38:26 +0000458};
459
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000460namespace {
461LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
462/// Values for bit flags for marking which requires clauses have been used.
463enum OpenMPOffloadingRequiresDirFlags : int64_t {
464 /// flag undefined.
465 OMP_REQ_UNDEFINED = 0x000,
466 /// no requires clause present.
467 OMP_REQ_NONE = 0x001,
468 /// reverse_offload clause.
469 OMP_REQ_REVERSE_OFFLOAD = 0x002,
470 /// unified_address clause.
471 OMP_REQ_UNIFIED_ADDRESS = 0x004,
472 /// unified_shared_memory clause.
473 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
474 /// dynamic_allocators clause.
475 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
476 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)
477};
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +0000478
479enum OpenMPOffloadingReservedDeviceIDs {
480 /// Device ID if the device was not defined, runtime should get it
481 /// from environment variables in the spec.
482 OMP_DEVICEID_UNDEF = -1,
483};
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000484} // anonymous namespace
485
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000486/// Describes ident structure that describes a source location.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000487/// All descriptions are taken from
James Y Knight5d71fc52019-01-29 16:37:27 +0000488/// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev50b3c952016-02-19 10:38:26 +0000489/// Original structure:
490/// typedef struct ident {
491/// kmp_int32 reserved_1; /**< might be used in Fortran;
492/// see above */
493/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
494/// KMP_IDENT_KMPC identifies this union
495/// member */
496/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
497/// see above */
498///#if USE_ITT_BUILD
499/// /* but currently used for storing
500/// region-specific ITT */
501/// /* contextual information. */
502///#endif /* USE_ITT_BUILD */
503/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
504/// C++ */
505/// char const *psource; /**< String describing the source location.
506/// The string is composed of semi-colon separated
507// fields which describe the source file,
508/// the function and a pair of line numbers that
509/// delimit the construct.
510/// */
511/// } ident_t;
512enum IdentFieldIndex {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000513 /// might be used in Fortran
Alexey Bataev50b3c952016-02-19 10:38:26 +0000514 IdentField_Reserved_1,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000515 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000516 IdentField_Flags,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000517 /// Not really used in Fortran any more
Alexey Bataev50b3c952016-02-19 10:38:26 +0000518 IdentField_Reserved_2,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000519 /// Source[4] in Fortran, do not use for C++
Alexey Bataev50b3c952016-02-19 10:38:26 +0000520 IdentField_Reserved_3,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000521 /// String describing the source location. The string is composed of
Alexey Bataev50b3c952016-02-19 10:38:26 +0000522 /// semi-colon separated fields which describe the source file, the function
523 /// and a pair of line numbers that delimit the construct.
524 IdentField_PSource
525};
526
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000527/// Schedule types for 'omp for' loops (these enumerators are taken from
Alexey Bataev50b3c952016-02-19 10:38:26 +0000528/// the enum sched_type in kmp.h).
529enum OpenMPSchedType {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000530 /// Lower bound for default (unordered) versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000531 OMP_sch_lower = 32,
532 OMP_sch_static_chunked = 33,
533 OMP_sch_static = 34,
534 OMP_sch_dynamic_chunked = 35,
535 OMP_sch_guided_chunked = 36,
536 OMP_sch_runtime = 37,
537 OMP_sch_auto = 38,
Alexey Bataev6cff6242016-05-30 13:05:14 +0000538 /// static with chunk adjustment (e.g., simd)
Samuel Antao4c8035b2016-12-12 18:00:20 +0000539 OMP_sch_static_balanced_chunked = 45,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000540 /// Lower bound for 'ordered' versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000541 OMP_ord_lower = 64,
542 OMP_ord_static_chunked = 65,
543 OMP_ord_static = 66,
544 OMP_ord_dynamic_chunked = 67,
545 OMP_ord_guided_chunked = 68,
546 OMP_ord_runtime = 69,
547 OMP_ord_auto = 70,
548 OMP_sch_default = OMP_sch_static,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000549 /// dist_schedule types
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000550 OMP_dist_sch_static_chunked = 91,
551 OMP_dist_sch_static = 92,
Alexey Bataev9ebd7422016-05-10 09:57:36 +0000552 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
553 /// Set if the monotonic schedule modifier was present.
554 OMP_sch_modifier_monotonic = (1 << 29),
555 /// Set if the nonmonotonic schedule modifier was present.
556 OMP_sch_modifier_nonmonotonic = (1 << 30),
Alexey Bataev50b3c952016-02-19 10:38:26 +0000557};
558
559enum OpenMPRTLFunction {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000560 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000561 /// kmpc_micro microtask, ...);
562 OMPRTL__kmpc_fork_call,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000563 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000564 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
565 OMPRTL__kmpc_threadprivate_cached,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000566 /// Call to void __kmpc_threadprivate_register( ident_t *,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000567 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
568 OMPRTL__kmpc_threadprivate_register,
569 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
570 OMPRTL__kmpc_global_thread_num,
571 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
572 // kmp_critical_name *crit);
573 OMPRTL__kmpc_critical,
574 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
575 // global_tid, kmp_critical_name *crit, uintptr_t hint);
576 OMPRTL__kmpc_critical_with_hint,
577 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
578 // kmp_critical_name *crit);
579 OMPRTL__kmpc_end_critical,
580 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
581 // global_tid);
582 OMPRTL__kmpc_cancel_barrier,
583 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
584 OMPRTL__kmpc_barrier,
585 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
586 OMPRTL__kmpc_for_static_fini,
587 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
588 // global_tid);
589 OMPRTL__kmpc_serialized_parallel,
590 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
591 // global_tid);
592 OMPRTL__kmpc_end_serialized_parallel,
593 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
594 // kmp_int32 num_threads);
595 OMPRTL__kmpc_push_num_threads,
596 // Call to void __kmpc_flush(ident_t *loc);
597 OMPRTL__kmpc_flush,
598 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
599 OMPRTL__kmpc_master,
600 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
601 OMPRTL__kmpc_end_master,
602 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
603 // int end_part);
604 OMPRTL__kmpc_omp_taskyield,
605 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
606 OMPRTL__kmpc_single,
607 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
608 OMPRTL__kmpc_end_single,
609 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
610 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
611 // kmp_routine_entry_t *task_entry);
612 OMPRTL__kmpc_omp_task_alloc,
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +0000613 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *,
614 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t,
615 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry,
616 // kmp_int64 device_id);
617 OMPRTL__kmpc_omp_target_task_alloc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000618 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
619 // new_task);
620 OMPRTL__kmpc_omp_task,
621 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
622 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
623 // kmp_int32 didit);
624 OMPRTL__kmpc_copyprivate,
625 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
626 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
627 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
628 OMPRTL__kmpc_reduce,
629 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
630 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
631 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
632 // *lck);
633 OMPRTL__kmpc_reduce_nowait,
634 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
635 // kmp_critical_name *lck);
636 OMPRTL__kmpc_end_reduce,
637 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
638 // kmp_critical_name *lck);
639 OMPRTL__kmpc_end_reduce_nowait,
640 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
641 // kmp_task_t * new_task);
642 OMPRTL__kmpc_omp_task_begin_if0,
643 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
644 // kmp_task_t * new_task);
645 OMPRTL__kmpc_omp_task_complete_if0,
646 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
647 OMPRTL__kmpc_ordered,
648 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
649 OMPRTL__kmpc_end_ordered,
650 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
651 // global_tid);
652 OMPRTL__kmpc_omp_taskwait,
653 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
654 OMPRTL__kmpc_taskgroup,
655 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
656 OMPRTL__kmpc_end_taskgroup,
657 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
658 // int proc_bind);
659 OMPRTL__kmpc_push_proc_bind,
660 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
661 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
662 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
663 OMPRTL__kmpc_omp_task_with_deps,
664 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
665 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
666 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
667 OMPRTL__kmpc_omp_wait_deps,
668 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
669 // global_tid, kmp_int32 cncl_kind);
670 OMPRTL__kmpc_cancellationpoint,
671 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
672 // kmp_int32 cncl_kind);
673 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000674 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
675 // kmp_int32 num_teams, kmp_int32 thread_limit);
676 OMPRTL__kmpc_push_num_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000677 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
678 // microtask, ...);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000679 OMPRTL__kmpc_fork_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000680 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
681 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
682 // sched, kmp_uint64 grainsize, void *task_dup);
683 OMPRTL__kmpc_taskloop,
Alexey Bataev8b427062016-05-25 12:36:08 +0000684 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
685 // num_dims, struct kmp_dim *dims);
686 OMPRTL__kmpc_doacross_init,
687 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
688 OMPRTL__kmpc_doacross_fini,
689 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
690 // *vec);
691 OMPRTL__kmpc_doacross_post,
692 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
693 // *vec);
694 OMPRTL__kmpc_doacross_wait,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000695 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void
696 // *data);
697 OMPRTL__kmpc_task_reduction_init,
698 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
699 // *d);
700 OMPRTL__kmpc_task_reduction_get_th_data,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000701 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000702 OMPRTL__kmpc_alloc,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000703 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000704 OMPRTL__kmpc_free,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000705
706 //
707 // Offloading related calls
708 //
Alexey Bataev7bb33532019-01-07 21:30:43 +0000709 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
710 // size);
711 OMPRTL__kmpc_push_target_tripcount,
George Rokos63bc9d62017-11-21 18:25:12 +0000712 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000713 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev50b3c952016-02-19 10:38:26 +0000714 // *arg_types);
715 OMPRTL__tgt_target,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000716 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000717 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000718 // *arg_types);
719 OMPRTL__tgt_target_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000720 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000721 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
George Rokos63bc9d62017-11-21 18:25:12 +0000722 // *arg_types, int32_t num_teams, int32_t thread_limit);
Samuel Antaob68e2db2016-03-03 16:20:23 +0000723 OMPRTL__tgt_target_teams,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000724 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +0000725 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000726 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
727 OMPRTL__tgt_target_teams_nowait,
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000728 // Call to void __tgt_register_requires(int64_t flags);
729 OMPRTL__tgt_register_requires,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000730 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
731 OMPRTL__tgt_register_lib,
732 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
733 OMPRTL__tgt_unregister_lib,
George Rokos63bc9d62017-11-21 18:25:12 +0000734 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000735 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
Samuel Antaodf158d52016-04-27 22:58:19 +0000736 OMPRTL__tgt_target_data_begin,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000737 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000738 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000739 // *arg_types);
740 OMPRTL__tgt_target_data_begin_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000741 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
742 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
Samuel Antaodf158d52016-04-27 22:58:19 +0000743 OMPRTL__tgt_target_data_end,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000744 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000745 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000746 // *arg_types);
747 OMPRTL__tgt_target_data_end_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000748 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000749 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
Samuel Antao8d2d7302016-05-26 18:30:22 +0000750 OMPRTL__tgt_target_data_update,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000751 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000752 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000753 // *arg_types);
754 OMPRTL__tgt_target_data_update_nowait,
Michael Krused47b9432019-08-05 18:43:21 +0000755 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
756 OMPRTL__tgt_mapper_num_components,
757 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void
758 // *base, void *begin, int64_t size, int64_t type);
759 OMPRTL__tgt_push_mapper_component,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000760};
761
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000762/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
763/// region.
764class CleanupTy final : public EHScopeStack::Cleanup {
765 PrePostActionTy *Action;
766
767public:
768 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
769 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
770 if (!CGF.HaveInsertPoint())
771 return;
772 Action->Exit(CGF);
773 }
774};
775
Hans Wennborg7eb54642015-09-10 17:07:54 +0000776} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000777
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000778void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
779 CodeGenFunction::RunCleanupsScope Scope(CGF);
780 if (PrePostAction) {
781 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
782 Callback(CodeGen, CGF, *PrePostAction);
783 } else {
784 PrePostActionTy Action;
785 Callback(CodeGen, CGF, Action);
786 }
787}
788
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000789/// Check if the combiner is a call to UDR combiner and if it is so return the
790/// UDR decl used for reduction.
791static const OMPDeclareReductionDecl *
792getReductionInit(const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000793 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
794 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
795 if (const auto *DRE =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000796 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000797 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000798 return DRD;
799 return nullptr;
800}
801
802static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
803 const OMPDeclareReductionDecl *DRD,
804 const Expr *InitOp,
805 Address Private, Address Original,
806 QualType Ty) {
807 if (DRD->getInitializer()) {
808 std::pair<llvm::Function *, llvm::Function *> Reduction =
809 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000810 const auto *CE = cast<CallExpr>(InitOp);
811 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000812 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
813 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000814 const auto *LHSDRE =
815 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
816 const auto *RHSDRE =
817 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000818 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
819 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000820 [=]() { return Private; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000821 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000822 [=]() { return Original; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000823 (void)PrivateScope.Privatize();
824 RValue Func = RValue::get(Reduction.second);
825 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
826 CGF.EmitIgnoredExpr(InitOp);
827 } else {
828 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
Alexey Bataev18fa2322018-05-02 14:20:50 +0000829 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000830 auto *GV = new llvm::GlobalVariable(
831 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
Alexey Bataev18fa2322018-05-02 14:20:50 +0000832 llvm::GlobalValue::PrivateLinkage, Init, Name);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000833 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
834 RValue InitRVal;
835 switch (CGF.getEvaluationKind(Ty)) {
836 case TEK_Scalar:
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000837 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000838 break;
839 case TEK_Complex:
840 InitRVal =
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000841 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000842 break;
843 case TEK_Aggregate:
844 InitRVal = RValue::getAggregate(LV.getAddress());
845 break;
846 }
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000847 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000848 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
849 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
850 /*IsInitializer=*/false);
851 }
852}
853
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000854/// Emit initialization of arrays of complex types.
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000855/// \param DestAddr Address of the array.
856/// \param Type Type of array.
857/// \param Init Initial expression of array.
858/// \param SrcAddr Address of the original array.
859static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
Alexey Bataeva7b19152017-10-12 20:03:39 +0000860 QualType Type, bool EmitDeclareReductionInit,
861 const Expr *Init,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000862 const OMPDeclareReductionDecl *DRD,
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000863 Address SrcAddr = Address::invalid()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000864 // Perform element-by-element initialization.
865 QualType ElementTy;
866
867 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000868 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
869 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000870 DestAddr =
871 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
872 if (DRD)
873 SrcAddr =
874 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
875
876 llvm::Value *SrcBegin = nullptr;
877 if (DRD)
878 SrcBegin = SrcAddr.getPointer();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000879 llvm::Value *DestBegin = DestAddr.getPointer();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000880 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000881 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000882 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000883 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
884 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
885 llvm::Value *IsEmpty =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000886 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
887 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
888
889 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000890 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000891 CGF.EmitBlock(BodyBB);
892
893 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
894
895 llvm::PHINode *SrcElementPHI = nullptr;
896 Address SrcElementCurrent = Address::invalid();
897 if (DRD) {
898 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
899 "omp.arraycpy.srcElementPast");
900 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
901 SrcElementCurrent =
902 Address(SrcElementPHI,
903 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
904 }
905 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
906 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
907 DestElementPHI->addIncoming(DestBegin, EntryBB);
908 Address DestElementCurrent =
909 Address(DestElementPHI,
910 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
911
912 // Emit copy.
913 {
914 CodeGenFunction::RunCleanupsScope InitScope(CGF);
Alexey Bataeva7b19152017-10-12 20:03:39 +0000915 if (EmitDeclareReductionInit) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000916 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
917 SrcElementCurrent, ElementTy);
918 } else
919 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
920 /*IsInitializer=*/false);
921 }
922
923 if (DRD) {
924 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000925 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000926 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
927 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
928 }
929
930 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000931 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000932 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
933 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000934 llvm::Value *Done =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000935 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
936 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
937 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
938
939 // Done.
940 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
941}
942
943LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000944 return CGF.EmitOMPSharedLValue(E);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000945}
946
947LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
948 const Expr *E) {
949 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
950 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
951 return LValue();
952}
953
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000954void ReductionCodeGen::emitAggregateInitialization(
955 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
956 const OMPDeclareReductionDecl *DRD) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000957 // Emit VarDecl with copy init for arrays.
958 // Get the address of the original variable captured in current
959 // captured region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000960 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000961 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva7b19152017-10-12 20:03:39 +0000962 bool EmitDeclareReductionInit =
963 DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000964 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),
Alexey Bataeva7b19152017-10-12 20:03:39 +0000965 EmitDeclareReductionInit,
966 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
967 : PrivateVD->getInit(),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000968 DRD, SharedLVal.getAddress());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000969}
970
971ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
972 ArrayRef<const Expr *> Privates,
973 ArrayRef<const Expr *> ReductionOps) {
974 ClausesData.reserve(Shareds.size());
975 SharedAddresses.reserve(Shareds.size());
976 Sizes.reserve(Shareds.size());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000977 BaseDecls.reserve(Shareds.size());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000978 auto IPriv = Privates.begin();
979 auto IRed = ReductionOps.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000980 for (const Expr *Ref : Shareds) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000981 ClausesData.emplace_back(Ref, *IPriv, *IRed);
982 std::advance(IPriv, 1);
983 std::advance(IRed, 1);
984 }
985}
986
987void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) {
988 assert(SharedAddresses.size() == N &&
989 "Number of generated lvalues must be exactly N.");
Jonas Hahnfeld4525c822017-10-23 19:01:35 +0000990 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
991 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
992 SharedAddresses.emplace_back(First, Second);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000993}
994
995void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000996 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000997 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
998 QualType PrivateType = PrivateVD->getType();
999 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001000 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001001 Sizes.emplace_back(
1002 CGF.getTypeSize(
1003 SharedAddresses[N].first.getType().getNonReferenceType()),
1004 nullptr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001005 return;
1006 }
1007 llvm::Value *Size;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001008 llvm::Value *SizeInChars;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001009 auto *ElemType =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001010 cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType())
1011 ->getElementType();
1012 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001013 if (AsArraySection) {
1014 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(),
1015 SharedAddresses[N].first.getPointer());
1016 Size = CGF.Builder.CreateNUWAdd(
1017 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001018 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001019 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001020 SizeInChars = CGF.getTypeSize(
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001021 SharedAddresses[N].first.getType().getNonReferenceType());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001022 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001023 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001024 Sizes.emplace_back(SizeInChars, Size);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001025 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1026 CGF,
1027 cast<OpaqueValueExpr>(
1028 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1029 RValue::get(Size));
1030 CGF.EmitVariablyModifiedType(PrivateType);
1031}
1032
1033void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
1034 llvm::Value *Size) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001035 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001036 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1037 QualType PrivateType = PrivateVD->getType();
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001038 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001039 assert(!Size && !Sizes[N].second &&
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001040 "Size should be nullptr for non-variably modified reduction "
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001041 "items.");
1042 return;
1043 }
1044 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1045 CGF,
1046 cast<OpaqueValueExpr>(
1047 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1048 RValue::get(Size));
1049 CGF.EmitVariablyModifiedType(PrivateType);
1050}
1051
1052void ReductionCodeGen::emitInitialization(
1053 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
1054 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
1055 assert(SharedAddresses.size() > N && "No variable was generated");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001056 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001057 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001058 const OMPDeclareReductionDecl *DRD =
1059 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001060 QualType PrivateType = PrivateVD->getType();
1061 PrivateAddr = CGF.Builder.CreateElementBitCast(
1062 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1063 QualType SharedType = SharedAddresses[N].first.getType();
1064 SharedLVal = CGF.MakeAddrLValue(
1065 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(),
1066 CGF.ConvertTypeForMem(SharedType)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001067 SharedType, SharedAddresses[N].first.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001068 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType));
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001069 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001070 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001071 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
1072 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
1073 PrivateAddr, SharedLVal.getAddress(),
1074 SharedLVal.getType());
1075 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
1076 !CGF.isTrivialInitializer(PrivateVD->getInit())) {
1077 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,
1078 PrivateVD->getType().getQualifiers(),
1079 /*IsInitializer=*/false);
1080 }
1081}
1082
1083bool ReductionCodeGen::needCleanups(unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001084 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001085 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1086 QualType PrivateType = PrivateVD->getType();
1087 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1088 return DTorKind != QualType::DK_none;
1089}
1090
1091void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
1092 Address PrivateAddr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001093 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001094 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1095 QualType PrivateType = PrivateVD->getType();
1096 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1097 if (needCleanups(N)) {
1098 PrivateAddr = CGF.Builder.CreateElementBitCast(
1099 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1100 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);
1101 }
1102}
1103
1104static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1105 LValue BaseLV) {
1106 BaseTy = BaseTy.getNonReferenceType();
1107 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1108 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001109 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001110 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001111 } else {
Ivan A. Kosarev9f9d1572017-10-30 11:49:31 +00001112 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy);
1113 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001114 }
1115 BaseTy = BaseTy->getPointeeType();
1116 }
1117 return CGF.MakeAddrLValue(
1118 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(),
1119 CGF.ConvertTypeForMem(ElTy)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001120 BaseLV.getType(), BaseLV.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001121 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001122}
1123
1124static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1125 llvm::Type *BaseLVType, CharUnits BaseLVAlignment,
1126 llvm::Value *Addr) {
1127 Address Tmp = Address::invalid();
1128 Address TopTmp = Address::invalid();
1129 Address MostTopTmp = Address::invalid();
1130 BaseTy = BaseTy.getNonReferenceType();
1131 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1132 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
1133 Tmp = CGF.CreateMemTemp(BaseTy);
1134 if (TopTmp.isValid())
1135 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
1136 else
1137 MostTopTmp = Tmp;
1138 TopTmp = Tmp;
1139 BaseTy = BaseTy->getPointeeType();
1140 }
1141 llvm::Type *Ty = BaseLVType;
1142 if (Tmp.isValid())
1143 Ty = Tmp.getElementType();
1144 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);
1145 if (Tmp.isValid()) {
1146 CGF.Builder.CreateStore(Addr, Tmp);
1147 return MostTopTmp;
1148 }
1149 return Address(Addr, BaseLVAlignment);
1150}
1151
Alexey Bataev1c44e152018-03-06 18:59:43 +00001152static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001153 const VarDecl *OrigVD = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001154 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
1155 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
1156 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001157 Base = TempOASE->getBase()->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001158 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001159 Base = TempASE->getBase()->IgnoreParenImpCasts();
1160 DE = cast<DeclRefExpr>(Base);
1161 OrigVD = cast<VarDecl>(DE->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001162 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
1163 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
1164 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001165 Base = TempASE->getBase()->IgnoreParenImpCasts();
1166 DE = cast<DeclRefExpr>(Base);
1167 OrigVD = cast<VarDecl>(DE->getDecl());
1168 }
Alexey Bataev1c44e152018-03-06 18:59:43 +00001169 return OrigVD;
1170}
1171
1172Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
1173 Address PrivateAddr) {
1174 const DeclRefExpr *DE;
1175 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001176 BaseDecls.emplace_back(OrigVD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001177 LValue OriginalBaseLValue = CGF.EmitLValue(DE);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001178 LValue BaseLValue =
1179 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
1180 OriginalBaseLValue);
1181 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
1182 BaseLValue.getPointer(), SharedAddresses[N].first.getPointer());
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001183 llvm::Value *PrivatePointer =
1184 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1185 PrivateAddr.getPointer(),
1186 SharedAddresses[N].first.getAddress().getType());
1187 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001188 return castToBase(CGF, OrigVD->getType(),
1189 SharedAddresses[N].first.getType(),
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001190 OriginalBaseLValue.getAddress().getType(),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001191 OriginalBaseLValue.getAlignment(), Ptr);
1192 }
1193 BaseDecls.emplace_back(
1194 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
1195 return PrivateAddr;
1196}
1197
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001198bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001199 const OMPDeclareReductionDecl *DRD =
1200 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001201 return DRD && DRD->getInitializer();
1202}
1203
Alexey Bataev18095712014-10-10 12:19:54 +00001204LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +00001205 return CGF.EmitLoadOfPointerLValue(
1206 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1207 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +00001208}
1209
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001210void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001211 if (!CGF.HaveInsertPoint())
1212 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001213 // 1.2.2 OpenMP Language Terminology
1214 // Structured block - An executable statement with a single entry at the
1215 // top and a single exit at the bottom.
1216 // The point of exit cannot be a branch out of the structured block.
1217 // longjmp() and throw() must not violate the entry/exit criteria.
1218 CGF.EHStack.pushTerminate();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001219 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001220 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001221}
1222
Alexey Bataev62b63b12015-03-10 07:28:44 +00001223LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1224 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001225 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1226 getThreadIDVariable()->getType(),
Ivan A. Kosarev5f8c0ca2017-10-10 09:39:32 +00001227 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001228}
1229
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001230static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1231 QualType FieldTy) {
1232 auto *Field = FieldDecl::Create(
1233 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1234 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1235 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1236 Field->setAccess(AS_public);
1237 DC->addDecl(Field);
1238 return Field;
1239}
1240
Alexey Bataev18fa2322018-05-02 14:20:50 +00001241CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
1242 StringRef Separator)
1243 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
1244 OffloadEntriesInfoManager(CGM) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001245 ASTContext &C = CGM.getContext();
1246 RecordDecl *RD = C.buildImplicitRecord("ident_t");
1247 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1248 RD->startDefinition();
1249 // reserved_1
1250 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1251 // flags
1252 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1253 // reserved_2
1254 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1255 // reserved_3
1256 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1257 // psource
1258 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1259 RD->completeDefinition();
1260 IdentQTy = C.getRecordType(RD);
1261 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001262 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +00001263
1264 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +00001265}
1266
Alexey Bataev91797552015-03-18 04:13:55 +00001267void CGOpenMPRuntime::clear() {
1268 InternalVars.clear();
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00001269 // Clean non-target variable declarations possibly used only in debug info.
1270 for (const auto &Data : EmittedNonTargetVariables) {
1271 if (!Data.getValue().pointsToAliveValue())
1272 continue;
1273 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1274 if (!GV)
1275 continue;
1276 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1277 continue;
1278 GV->eraseFromParent();
1279 }
Alexey Bataev91797552015-03-18 04:13:55 +00001280}
1281
Alexey Bataev18fa2322018-05-02 14:20:50 +00001282std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1283 SmallString<128> Buffer;
1284 llvm::raw_svector_ostream OS(Buffer);
1285 StringRef Sep = FirstSeparator;
1286 for (StringRef Part : Parts) {
1287 OS << Sep << Part;
1288 Sep = Separator;
1289 }
1290 return OS.str();
1291}
1292
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001293static llvm::Function *
1294emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1295 const Expr *CombinerInitializer, const VarDecl *In,
1296 const VarDecl *Out, bool IsCombiner) {
1297 // void .omp_combiner.(Ty *in, Ty *out);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001298 ASTContext &C = CGM.getContext();
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001299 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1300 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001301 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001302 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001303 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001304 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001305 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001306 Args.push_back(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001307 const CGFunctionInfo &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00001308 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001309 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00001310 std::string Name = CGM.getOpenMPRuntime().getName(
1311 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1312 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1313 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00001314 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00001315 if (CGM.getLangOpts().Optimize) {
1316 Fn->removeFnAttr(llvm::Attribute::NoInline);
1317 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1318 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1319 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001320 CodeGenFunction CGF(CGM);
1321 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1322 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
Alexey Bataev7cae94e2018-01-04 19:45:16 +00001323 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1324 Out->getLocation());
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001325 CodeGenFunction::OMPPrivateScope Scope(CGF);
1326 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001327 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001328 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
1329 .getAddress();
1330 });
1331 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001332 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001333 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
1334 .getAddress();
1335 });
1336 (void)Scope.Privatize();
Alexey Bataev070f43a2017-09-06 14:49:58 +00001337 if (!IsCombiner && Out->hasInit() &&
1338 !CGF.isTrivialInitializer(Out->getInit())) {
1339 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1340 Out->getType().getQualifiers(),
1341 /*IsInitializer=*/true);
1342 }
1343 if (CombinerInitializer)
1344 CGF.EmitIgnoredExpr(CombinerInitializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001345 Scope.ForceCleanup();
1346 CGF.FinishFunction();
1347 return Fn;
1348}
1349
1350void CGOpenMPRuntime::emitUserDefinedReduction(
1351 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1352 if (UDRMap.count(D) > 0)
1353 return;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001354 llvm::Function *Combiner = emitCombinerOrInitializer(
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001355 CGM, D->getType(), D->getCombiner(),
1356 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1357 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001358 /*IsCombiner=*/true);
1359 llvm::Function *Initializer = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001360 if (const Expr *Init = D->getInitializer()) {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001361 Initializer = emitCombinerOrInitializer(
Alexey Bataev070f43a2017-09-06 14:49:58 +00001362 CGM, D->getType(),
1363 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1364 : nullptr,
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001365 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1366 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001367 /*IsCombiner=*/false);
1368 }
Alexey Bataev43a919f2018-04-13 17:48:43 +00001369 UDRMap.try_emplace(D, Combiner, Initializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001370 if (CGF) {
1371 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1372 Decls.second.push_back(D);
1373 }
1374}
1375
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001376std::pair<llvm::Function *, llvm::Function *>
1377CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1378 auto I = UDRMap.find(D);
1379 if (I != UDRMap.end())
1380 return I->second;
1381 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1382 return UDRMap.lookup(D);
1383}
1384
James Y Knight9871db02019-02-05 16:42:33 +00001385static llvm::Function *emitParallelOrTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001386 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1387 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1388 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001389 assert(ThreadIDVar->getType()->isPointerType() &&
1390 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +00001391 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001392 bool HasCancel = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001393 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001394 HasCancel = OPD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001395 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001396 HasCancel = OPSD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001397 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001398 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001399 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
Alexey Bataev2139ed62017-11-16 18:20:21 +00001400 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001401 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001402 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001403 else if (const auto *OPFD =
1404 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001405 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001406 else if (const auto *OPFD =
Alexey Bataev10a54312017-11-27 16:54:08 +00001407 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1408 HasCancel = OPFD->hasCancel();
Alexey Bataev25e5b442015-09-15 12:52:43 +00001409 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001410 HasCancel, OutlinedHelperName);
Alexey Bataevd157d472015-06-24 03:35:38 +00001411 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001412 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +00001413}
1414
James Y Knight9871db02019-02-05 16:42:33 +00001415llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001416 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1417 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1418 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1419 return emitParallelOrTeamsOutlinedFunction(
1420 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1421}
1422
James Y Knight9871db02019-02-05 16:42:33 +00001423llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001424 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1425 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1426 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1427 return emitParallelOrTeamsOutlinedFunction(
1428 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1429}
1430
James Y Knight9871db02019-02-05 16:42:33 +00001431llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001432 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +00001433 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1434 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1435 bool Tied, unsigned &NumberOfParts) {
1436 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1437 PrePostActionTy &) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001438 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1439 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
Alexey Bataev48591dd2016-04-20 04:01:36 +00001440 llvm::Value *TaskArgs[] = {
1441 UpLoc, ThreadID,
1442 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1443 TaskTVar->getType()->castAs<PointerType>())
1444 .getPointer()};
1445 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
1446 };
1447 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1448 UntiedCodeGen);
1449 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001450 assert(!ThreadIDVar->getType()->isPointerType() &&
1451 "thread id variable must be of type kmp_int32 for tasks");
Alexey Bataev475a7442018-01-12 19:39:11 +00001452 const OpenMPDirectiveKind Region =
1453 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1454 : OMPD_task;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001455 const CapturedStmt *CS = D.getCapturedStmt(Region);
1456 const auto *TD = dyn_cast<OMPTaskDirective>(&D);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001457 CodeGenFunction CGF(CGM, true);
Alexey Bataev7292c292016-04-25 12:22:29 +00001458 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1459 InnermostKind,
1460 TD ? TD->hasCancel() : false, Action);
Alexey Bataevd157d472015-06-24 03:35:38 +00001461 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
James Y Knight9871db02019-02-05 16:42:33 +00001462 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
Alexey Bataev48591dd2016-04-20 04:01:36 +00001463 if (!Tied)
1464 NumberOfParts = Action.getNumberOfParts();
1465 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001466}
1467
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001468static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1469 const RecordDecl *RD, const CGRecordLayout &RL,
1470 ArrayRef<llvm::Constant *> Data) {
1471 llvm::StructType *StructTy = RL.getLLVMType();
1472 unsigned PrevIdx = 0;
1473 ConstantInitBuilder CIBuilder(CGM);
1474 auto DI = Data.begin();
1475 for (const FieldDecl *FD : RD->fields()) {
1476 unsigned Idx = RL.getLLVMFieldNo(FD);
1477 // Fill the alignment.
1478 for (unsigned I = PrevIdx; I < Idx; ++I)
1479 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1480 PrevIdx = Idx + 1;
1481 Fields.add(*DI);
1482 ++DI;
1483 }
1484}
1485
1486template <class... As>
1487static llvm::GlobalVariable *
Mike Ricee1ca7b62018-08-29 15:45:11 +00001488createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1489 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1490 As &&... Args) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001491 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1492 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1493 ConstantInitBuilder CIBuilder(CGM);
1494 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1495 buildStructValue(Fields, CGM, RD, RL, Data);
1496 return Fields.finishAndCreateGlobal(
Mike Ricee1ca7b62018-08-29 15:45:11 +00001497 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1498 std::forward<As>(Args)...);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001499}
1500
1501template <typename T>
Benjamin Kramer651d0bf2018-05-15 21:26:47 +00001502static void
1503createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1504 ArrayRef<llvm::Constant *> Data,
1505 T &Parent) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001506 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1507 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1508 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1509 buildStructValue(Fields, CGM, RD, RL, Data);
1510 Fields.finishAndAddTo(Parent);
1511}
1512
Alexey Bataev50b3c952016-02-19 10:38:26 +00001513Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001514 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
Alexey Bataevceeaa482018-11-21 21:04:34 +00001515 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1516 FlagsTy FlagsKey(Flags, Reserved2Flags);
1517 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey);
Alexey Bataev9959db52014-05-06 10:08:46 +00001518 if (!Entry) {
1519 if (!DefaultOpenMPPSource) {
1520 // Initialize default location for psource field of ident_t structure of
1521 // all ident_t objects. Format is ";file;function;line;column;;".
1522 // Taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00001523 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp
Alexey Bataev9959db52014-05-06 10:08:46 +00001524 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +00001525 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001526 DefaultOpenMPPSource =
1527 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
1528 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001529
Alexey Bataevceeaa482018-11-21 21:04:34 +00001530 llvm::Constant *Data[] = {
1531 llvm::ConstantInt::getNullValue(CGM.Int32Ty),
1532 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
1533 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags),
1534 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource};
Mike Ricee1ca7b62018-08-29 15:45:11 +00001535 llvm::GlobalValue *DefaultOpenMPLocation =
Alexey Bataevceeaa482018-11-21 21:04:34 +00001536 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "",
Mike Ricee1ca7b62018-08-29 15:45:11 +00001537 llvm::GlobalValue::PrivateLinkage);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001538 DefaultOpenMPLocation->setUnnamedAddr(
1539 llvm::GlobalValue::UnnamedAddr::Global);
John McCall6c9f1fdb2016-11-19 08:17:24 +00001540
Alexey Bataevceeaa482018-11-21 21:04:34 +00001541 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +00001542 }
John McCall7f416cc2015-09-08 08:05:57 +00001543 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +00001544}
1545
Alexey Bataevfd006c42018-10-05 15:08:53 +00001546void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1547 bool AtCurrentPoint) {
1548 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1549 assert(!Elem.second.ServiceInsertPt && "Insert point is set already.");
1550
1551 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1552 if (AtCurrentPoint) {
1553 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1554 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1555 } else {
1556 Elem.second.ServiceInsertPt =
1557 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1558 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1559 }
1560}
1561
1562void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1563 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1564 if (Elem.second.ServiceInsertPt) {
1565 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1566 Elem.second.ServiceInsertPt = nullptr;
1567 Ptr->eraseFromParent();
1568 }
1569}
1570
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001571llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1572 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +00001573 unsigned Flags) {
1574 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +00001575 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +00001576 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +00001577 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +00001578 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001579
1580 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1581
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001582 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
John McCall7f416cc2015-09-08 08:05:57 +00001583 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001584 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1585 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001586 LocValue = Address(I->second.DebugLoc, Align);
John McCall7f416cc2015-09-08 08:05:57 +00001587
Alexander Musmanc6388682014-12-15 07:07:06 +00001588 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
1589 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +00001590 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +00001591 // Generate "ident_t .kmpc_loc.addr;"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001592 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +00001593 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +00001594 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001595 LocValue = AI;
1596
Alexey Bataevfd006c42018-10-05 15:08:53 +00001597 if (!Elem.second.ServiceInsertPt)
1598 setLocThreadIdInsertPt(CGF);
Alexey Bataev9959db52014-05-06 10:08:46 +00001599 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001600 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001601 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001602 CGF.getTypeSize(IdentQTy));
Alexey Bataev9959db52014-05-06 10:08:46 +00001603 }
1604
1605 // char **psource = &.kmpc_loc_<flags>.addr.psource;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001606 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy);
1607 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin();
1608 LValue PSource =
1609 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource));
Alexey Bataev9959db52014-05-06 10:08:46 +00001610
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001611 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
Alexey Bataevf002aca2014-05-30 05:48:40 +00001612 if (OMPDebugLoc == nullptr) {
1613 SmallString<128> Buffer2;
1614 llvm::raw_svector_ostream OS2(Buffer2);
1615 // Build debug location
1616 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1617 OS2 << ";" << PLoc.getFilename() << ";";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001618 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
Alexey Bataevf002aca2014-05-30 05:48:40 +00001619 OS2 << FD->getQualifiedNameAsString();
Alexey Bataevf002aca2014-05-30 05:48:40 +00001620 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1621 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
1622 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +00001623 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001624 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001625 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource);
Alexey Bataevf002aca2014-05-30 05:48:40 +00001626
John McCall7f416cc2015-09-08 08:05:57 +00001627 // Our callers always pass this to a runtime function, so for
1628 // convenience, go ahead and return a naked pointer.
1629 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001630}
1631
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001632llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1633 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001634 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1635
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001636 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +00001637 // Check whether we've already cached a load of the thread id in this
1638 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001639 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +00001640 if (I != OpenMPLocThreadIDMap.end()) {
1641 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +00001642 if (ThreadID != nullptr)
1643 return ThreadID;
1644 }
Alexey Bataevaee18552017-08-16 14:01:00 +00001645 // If exceptions are enabled, do not use parameter to avoid possible crash.
Alexey Bataev5d2c9a42017-11-02 18:55:05 +00001646 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1647 !CGF.getLangOpts().CXXExceptions ||
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001648 CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
Alexey Bataevaee18552017-08-16 14:01:00 +00001649 if (auto *OMPRegionInfo =
1650 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1651 if (OMPRegionInfo->getThreadIDVariable()) {
1652 // Check if this an outlined function with thread id passed as argument.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001653 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev1e491372018-01-23 18:44:14 +00001654 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
Alexey Bataevaee18552017-08-16 14:01:00 +00001655 // If value loaded in entry block, cache it and use it everywhere in
1656 // function.
1657 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
1658 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1659 Elem.second.ThreadID = ThreadID;
1660 }
1661 return ThreadID;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001662 }
Alexey Bataevd6c57552014-07-25 07:55:17 +00001663 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001664 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001665
1666 // This is not an outlined function region - need to call __kmpc_int32
1667 // kmpc_global_thread_num(ident_t *loc).
1668 // Generate thread id value and cache this value for use across the
1669 // function.
Alexey Bataevfd006c42018-10-05 15:08:53 +00001670 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1671 if (!Elem.second.ServiceInsertPt)
1672 setLocThreadIdInsertPt(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001673 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001674 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001675 llvm::CallInst *Call = CGF.Builder.CreateCall(
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001676 createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1677 emitUpdateLocation(CGF, Loc));
1678 Call->setCallingConv(CGF.getRuntimeCC());
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001679 Elem.second.ThreadID = Call;
1680 return Call;
Alexey Bataev9959db52014-05-06 10:08:46 +00001681}
1682
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001683void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001684 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataevfd006c42018-10-05 15:08:53 +00001685 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1686 clearLocThreadIdInsertPt(CGF);
Alexey Bataev03b340a2014-10-21 03:16:40 +00001687 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001688 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001689 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001690 for(auto *D : FunctionUDRMap[CGF.CurFn])
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001691 UDRMap.erase(D);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001692 FunctionUDRMap.erase(CGF.CurFn);
1693 }
Michael Krused47b9432019-08-05 18:43:21 +00001694 auto I = FunctionUDMMap.find(CGF.CurFn);
1695 if (I != FunctionUDMMap.end()) {
1696 for(auto *D : I->second)
1697 UDMMap.erase(D);
1698 FunctionUDMMap.erase(I);
1699 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001700}
1701
1702llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001703 return IdentTy->getPointerTo();
Alexey Bataev9959db52014-05-06 10:08:46 +00001704}
1705
1706llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001707 if (!Kmpc_MicroTy) {
1708 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1709 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1710 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1711 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1712 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001713 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1714}
1715
James Y Knight9871db02019-02-05 16:42:33 +00001716llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
1717 llvm::FunctionCallee RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001718 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001719 case OMPRTL__kmpc_fork_call: {
1720 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1721 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001722 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1723 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001724 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001725 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001726 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
James Y Knight9871db02019-02-05 16:42:33 +00001727 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00001728 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
1729 llvm::LLVMContext &Ctx = F->getContext();
1730 llvm::MDBuilder MDB(Ctx);
1731 // Annotate the callback behavior of the __kmpc_fork_call:
1732 // - The callback callee is argument number 2 (microtask).
1733 // - The first two arguments of the callback callee are unknown (-1).
1734 // - All variadic arguments to the __kmpc_fork_call are passed to the
1735 // callback callee.
1736 F->addMetadata(
1737 llvm::LLVMContext::MD_callback,
1738 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
1739 2, {-1, -1},
1740 /* VarArgsArePassed */ true)}));
1741 }
1742 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001743 break;
1744 }
1745 case OMPRTL__kmpc_global_thread_num: {
1746 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001747 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001748 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001749 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001750 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1751 break;
1752 }
Alexey Bataev97720002014-11-11 04:05:39 +00001753 case OMPRTL__kmpc_threadprivate_cached: {
1754 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1755 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1756 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1757 CGM.VoidPtrTy, CGM.SizeTy,
1758 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001759 auto *FnTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001760 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1761 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1762 break;
1763 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001764 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001765 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1766 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001767 llvm::Type *TypeParams[] = {
1768 getIdentTyPointerTy(), CGM.Int32Ty,
1769 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001770 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001771 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1772 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1773 break;
1774 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001775 case OMPRTL__kmpc_critical_with_hint: {
1776 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1777 // kmp_critical_name *crit, uintptr_t hint);
1778 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1779 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1780 CGM.IntPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001781 auto *FnTy =
Alexey Bataevfc57d162015-12-15 10:55:09 +00001782 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1783 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1784 break;
1785 }
Alexey Bataev97720002014-11-11 04:05:39 +00001786 case OMPRTL__kmpc_threadprivate_register: {
1787 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1788 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1789 // typedef void *(*kmpc_ctor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001790 auto *KmpcCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001791 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1792 /*isVarArg*/ false)->getPointerTo();
1793 // typedef void *(*kmpc_cctor)(void *, void *);
1794 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001795 auto *KmpcCopyCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001796 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001797 /*isVarArg*/ false)
1798 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00001799 // typedef void (*kmpc_dtor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001800 auto *KmpcDtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001801 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1802 ->getPointerTo();
1803 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1804 KmpcCopyCtorTy, KmpcDtorTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001805 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
Alexey Bataev97720002014-11-11 04:05:39 +00001806 /*isVarArg*/ false);
1807 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1808 break;
1809 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001810 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001811 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1812 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001813 llvm::Type *TypeParams[] = {
1814 getIdentTyPointerTy(), CGM.Int32Ty,
1815 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001816 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001817 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1818 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1819 break;
1820 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001821 case OMPRTL__kmpc_cancel_barrier: {
1822 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1823 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001824 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001825 auto *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001826 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1827 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001828 break;
1829 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001830 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001831 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001832 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001833 auto *FnTy =
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001834 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1835 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1836 break;
1837 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001838 case OMPRTL__kmpc_for_static_fini: {
1839 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1840 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001841 auto *FnTy =
Alexander Musmanc6388682014-12-15 07:07:06 +00001842 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1843 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1844 break;
1845 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001846 case OMPRTL__kmpc_push_num_threads: {
1847 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1848 // kmp_int32 num_threads)
1849 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1850 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001851 auto *FnTy =
Alexey Bataevb2059782014-10-13 08:23:51 +00001852 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1853 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1854 break;
1855 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001856 case OMPRTL__kmpc_serialized_parallel: {
1857 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1858 // global_tid);
1859 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001860 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001861 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1862 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1863 break;
1864 }
1865 case OMPRTL__kmpc_end_serialized_parallel: {
1866 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1867 // global_tid);
1868 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001869 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001870 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1871 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1872 break;
1873 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001874 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001875 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001876 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001877 auto *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001878 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001879 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1880 break;
1881 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001882 case OMPRTL__kmpc_master: {
1883 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1884 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001885 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001886 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1887 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1888 break;
1889 }
1890 case OMPRTL__kmpc_end_master: {
1891 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1892 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001893 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001894 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1895 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1896 break;
1897 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001898 case OMPRTL__kmpc_omp_taskyield: {
1899 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1900 // int end_part);
1901 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001902 auto *FnTy =
Alexey Bataev9f797f32015-02-05 05:57:51 +00001903 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1904 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1905 break;
1906 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001907 case OMPRTL__kmpc_single: {
1908 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1909 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001910 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001911 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1912 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1913 break;
1914 }
1915 case OMPRTL__kmpc_end_single: {
1916 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1917 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001918 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001919 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1920 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1921 break;
1922 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001923 case OMPRTL__kmpc_omp_task_alloc: {
1924 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1925 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1926 // kmp_routine_entry_t *task_entry);
1927 assert(KmpRoutineEntryPtrTy != nullptr &&
1928 "Type kmp_routine_entry_t must be created.");
1929 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1930 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1931 // Return void * and then cast to particular kmp_task_t type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001932 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001933 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1934 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1935 break;
1936 }
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00001937 case OMPRTL__kmpc_omp_target_task_alloc: {
1938 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid,
1939 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1940 // kmp_routine_entry_t *task_entry, kmp_int64 device_id);
1941 assert(KmpRoutineEntryPtrTy != nullptr &&
1942 "Type kmp_routine_entry_t must be created.");
1943 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1944 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy,
1945 CGM.Int64Ty};
1946 // Return void * and then cast to particular kmp_task_t type.
1947 auto *FnTy =
1948 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1949 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc");
1950 break;
1951 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001952 case OMPRTL__kmpc_omp_task: {
1953 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1954 // *new_task);
1955 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1956 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001957 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001958 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1959 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
1960 break;
1961 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001962 case OMPRTL__kmpc_copyprivate: {
1963 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00001964 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001965 // kmp_int32 didit);
1966 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1967 auto *CpyFnTy =
1968 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001969 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001970 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
1971 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001972 auto *FnTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00001973 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1974 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
1975 break;
1976 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001977 case OMPRTL__kmpc_reduce: {
1978 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
1979 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
1980 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
1981 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1982 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1983 /*isVarArg=*/false);
1984 llvm::Type *TypeParams[] = {
1985 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1986 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1987 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001988 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001989 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1990 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
1991 break;
1992 }
1993 case OMPRTL__kmpc_reduce_nowait: {
1994 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
1995 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
1996 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
1997 // *lck);
1998 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1999 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2000 /*isVarArg=*/false);
2001 llvm::Type *TypeParams[] = {
2002 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2003 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2004 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002005 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002006 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2007 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
2008 break;
2009 }
2010 case OMPRTL__kmpc_end_reduce: {
2011 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
2012 // kmp_critical_name *lck);
2013 llvm::Type *TypeParams[] = {
2014 getIdentTyPointerTy(), CGM.Int32Ty,
2015 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002016 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002017 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2018 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
2019 break;
2020 }
2021 case OMPRTL__kmpc_end_reduce_nowait: {
2022 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
2023 // kmp_critical_name *lck);
2024 llvm::Type *TypeParams[] = {
2025 getIdentTyPointerTy(), CGM.Int32Ty,
2026 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002027 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002028 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2029 RTLFn =
2030 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
2031 break;
2032 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002033 case OMPRTL__kmpc_omp_task_begin_if0: {
2034 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2035 // *new_task);
2036 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2037 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002038 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002039 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2040 RTLFn =
2041 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
2042 break;
2043 }
2044 case OMPRTL__kmpc_omp_task_complete_if0: {
2045 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2046 // *new_task);
2047 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2048 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002049 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002050 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2051 RTLFn = CGM.CreateRuntimeFunction(FnTy,
2052 /*Name=*/"__kmpc_omp_task_complete_if0");
2053 break;
2054 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002055 case OMPRTL__kmpc_ordered: {
2056 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
2057 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002058 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002059 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2060 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
2061 break;
2062 }
2063 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002064 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002065 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002066 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002067 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2068 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
2069 break;
2070 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002071 case OMPRTL__kmpc_omp_taskwait: {
2072 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
2073 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002074 auto *FnTy =
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002075 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2076 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
2077 break;
2078 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002079 case OMPRTL__kmpc_taskgroup: {
2080 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
2081 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002082 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002083 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2084 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
2085 break;
2086 }
2087 case OMPRTL__kmpc_end_taskgroup: {
2088 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
2089 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002090 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002091 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2092 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
2093 break;
2094 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00002095 case OMPRTL__kmpc_push_proc_bind: {
2096 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2097 // int proc_bind)
2098 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002099 auto *FnTy =
Alexey Bataev7f210c62015-06-18 13:40:03 +00002100 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2101 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
2102 break;
2103 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002104 case OMPRTL__kmpc_omp_task_with_deps: {
2105 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2106 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2107 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
2108 llvm::Type *TypeParams[] = {
2109 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
2110 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002111 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002112 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2113 RTLFn =
2114 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
2115 break;
2116 }
2117 case OMPRTL__kmpc_omp_wait_deps: {
2118 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2119 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
2120 // kmp_depend_info_t *noalias_dep_list);
2121 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2122 CGM.Int32Ty, CGM.VoidPtrTy,
2123 CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002124 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002125 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2126 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
2127 break;
2128 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002129 case OMPRTL__kmpc_cancellationpoint: {
2130 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2131 // global_tid, kmp_int32 cncl_kind)
2132 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002133 auto *FnTy =
Alexey Bataev0f34da12015-07-02 04:17:07 +00002134 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2135 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
2136 break;
2137 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002138 case OMPRTL__kmpc_cancel: {
2139 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2140 // kmp_int32 cncl_kind)
2141 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002142 auto *FnTy =
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002143 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2144 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
2145 break;
2146 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002147 case OMPRTL__kmpc_push_num_teams: {
2148 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
2149 // kmp_int32 num_teams, kmp_int32 num_threads)
2150 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2151 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002152 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002153 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2154 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
2155 break;
2156 }
2157 case OMPRTL__kmpc_fork_teams: {
2158 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
2159 // microtask, ...);
2160 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2161 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002162 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002163 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
2164 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
James Y Knight9871db02019-02-05 16:42:33 +00002165 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00002166 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
2167 llvm::LLVMContext &Ctx = F->getContext();
2168 llvm::MDBuilder MDB(Ctx);
2169 // Annotate the callback behavior of the __kmpc_fork_teams:
2170 // - The callback callee is argument number 2 (microtask).
2171 // - The first two arguments of the callback callee are unknown (-1).
2172 // - All variadic arguments to the __kmpc_fork_teams are passed to the
2173 // callback callee.
2174 F->addMetadata(
2175 llvm::LLVMContext::MD_callback,
2176 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
2177 2, {-1, -1},
2178 /* VarArgsArePassed */ true)}));
2179 }
2180 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002181 break;
2182 }
Alexey Bataev7292c292016-04-25 12:22:29 +00002183 case OMPRTL__kmpc_taskloop: {
2184 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
2185 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
2186 // sched, kmp_uint64 grainsize, void *task_dup);
2187 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2188 CGM.IntTy,
2189 CGM.VoidPtrTy,
2190 CGM.IntTy,
2191 CGM.Int64Ty->getPointerTo(),
2192 CGM.Int64Ty->getPointerTo(),
2193 CGM.Int64Ty,
2194 CGM.IntTy,
2195 CGM.IntTy,
2196 CGM.Int64Ty,
2197 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002198 auto *FnTy =
Alexey Bataev7292c292016-04-25 12:22:29 +00002199 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2200 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
2201 break;
2202 }
Alexey Bataev8b427062016-05-25 12:36:08 +00002203 case OMPRTL__kmpc_doacross_init: {
2204 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
2205 // num_dims, struct kmp_dim *dims);
2206 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2207 CGM.Int32Ty,
2208 CGM.Int32Ty,
2209 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002210 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002211 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2212 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
2213 break;
2214 }
2215 case OMPRTL__kmpc_doacross_fini: {
2216 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
2217 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002218 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002219 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2220 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
2221 break;
2222 }
2223 case OMPRTL__kmpc_doacross_post: {
2224 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
2225 // *vec);
2226 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2227 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002228 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002229 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2230 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
2231 break;
2232 }
2233 case OMPRTL__kmpc_doacross_wait: {
2234 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
2235 // *vec);
2236 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2237 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002238 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002239 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2240 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
2241 break;
2242 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002243 case OMPRTL__kmpc_task_reduction_init: {
2244 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
2245 // *data);
2246 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002247 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002248 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2249 RTLFn =
2250 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
2251 break;
2252 }
2253 case OMPRTL__kmpc_task_reduction_get_th_data: {
2254 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
2255 // *d);
2256 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002257 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002258 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2259 RTLFn = CGM.CreateRuntimeFunction(
2260 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
2261 break;
2262 }
Alexey Bataev4f680db2019-03-19 16:41:16 +00002263 case OMPRTL__kmpc_alloc: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002264 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t
2265 // al); omp_allocator_handle_t type is void *.
2266 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002267 auto *FnTy =
2268 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2269 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc");
2270 break;
2271 }
2272 case OMPRTL__kmpc_free: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002273 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t
2274 // al); omp_allocator_handle_t type is void *.
2275 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002276 auto *FnTy =
2277 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2278 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free");
2279 break;
2280 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00002281 case OMPRTL__kmpc_push_target_tripcount: {
2282 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
2283 // size);
2284 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
2285 llvm::FunctionType *FnTy =
2286 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2287 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
2288 break;
2289 }
Samuel Antaobed3c462015-10-02 16:14:20 +00002290 case OMPRTL__tgt_target: {
George Rokos63bc9d62017-11-21 18:25:12 +00002291 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002292 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Samuel Antaobed3c462015-10-02 16:14:20 +00002293 // *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002294 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaobed3c462015-10-02 16:14:20 +00002295 CGM.VoidPtrTy,
2296 CGM.Int32Ty,
2297 CGM.VoidPtrPtrTy,
2298 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002299 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002300 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002301 auto *FnTy =
Samuel Antaobed3c462015-10-02 16:14:20 +00002302 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2303 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
2304 break;
2305 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002306 case OMPRTL__tgt_target_nowait: {
2307 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002308 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002309 // int64_t *arg_types);
2310 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2311 CGM.VoidPtrTy,
2312 CGM.Int32Ty,
2313 CGM.VoidPtrPtrTy,
2314 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002315 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002316 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002317 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002318 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2319 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
2320 break;
2321 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00002322 case OMPRTL__tgt_target_teams: {
George Rokos63bc9d62017-11-21 18:25:12 +00002323 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002324 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
George Rokos63bc9d62017-11-21 18:25:12 +00002325 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2326 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaob68e2db2016-03-03 16:20:23 +00002327 CGM.VoidPtrTy,
2328 CGM.Int32Ty,
2329 CGM.VoidPtrPtrTy,
2330 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002331 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002332 CGM.Int64Ty->getPointerTo(),
Samuel Antaob68e2db2016-03-03 16:20:23 +00002333 CGM.Int32Ty,
2334 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002335 auto *FnTy =
Samuel Antaob68e2db2016-03-03 16:20:23 +00002336 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2337 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
2338 break;
2339 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002340 case OMPRTL__tgt_target_teams_nowait: {
2341 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +00002342 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002343 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2344 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2345 CGM.VoidPtrTy,
2346 CGM.Int32Ty,
2347 CGM.VoidPtrPtrTy,
2348 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002349 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002350 CGM.Int64Ty->getPointerTo(),
2351 CGM.Int32Ty,
2352 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002353 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002354 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2355 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
2356 break;
2357 }
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00002358 case OMPRTL__tgt_register_requires: {
2359 // Build void __tgt_register_requires(int64_t flags);
2360 llvm::Type *TypeParams[] = {CGM.Int64Ty};
2361 auto *FnTy =
2362 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2363 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires");
2364 break;
2365 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00002366 case OMPRTL__tgt_register_lib: {
2367 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
2368 QualType ParamTy =
2369 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2370 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002371 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002372 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2373 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
2374 break;
2375 }
2376 case OMPRTL__tgt_unregister_lib: {
2377 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
2378 QualType ParamTy =
2379 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2380 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002381 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002382 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2383 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
2384 break;
2385 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002386 case OMPRTL__tgt_target_data_begin: {
George Rokos63bc9d62017-11-21 18:25:12 +00002387 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002388 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002389 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002390 CGM.Int32Ty,
2391 CGM.VoidPtrPtrTy,
2392 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002393 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002394 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002395 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002396 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2397 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
2398 break;
2399 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002400 case OMPRTL__tgt_target_data_begin_nowait: {
2401 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002402 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002403 // *arg_types);
2404 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2405 CGM.Int32Ty,
2406 CGM.VoidPtrPtrTy,
2407 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002408 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002409 CGM.Int64Ty->getPointerTo()};
2410 auto *FnTy =
2411 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2412 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
2413 break;
2414 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002415 case OMPRTL__tgt_target_data_end: {
George Rokos63bc9d62017-11-21 18:25:12 +00002416 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002417 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002418 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002419 CGM.Int32Ty,
2420 CGM.VoidPtrPtrTy,
2421 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002422 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002423 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002424 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002425 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2426 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
2427 break;
2428 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002429 case OMPRTL__tgt_target_data_end_nowait: {
2430 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002431 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002432 // *arg_types);
2433 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2434 CGM.Int32Ty,
2435 CGM.VoidPtrPtrTy,
2436 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002437 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002438 CGM.Int64Ty->getPointerTo()};
2439 auto *FnTy =
2440 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2441 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
2442 break;
2443 }
Samuel Antao8d2d7302016-05-26 18:30:22 +00002444 case OMPRTL__tgt_target_data_update: {
George Rokos63bc9d62017-11-21 18:25:12 +00002445 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002446 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002447 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antao8d2d7302016-05-26 18:30:22 +00002448 CGM.Int32Ty,
2449 CGM.VoidPtrPtrTy,
2450 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002451 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002452 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002453 auto *FnTy =
Samuel Antao8d2d7302016-05-26 18:30:22 +00002454 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2455 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
2456 break;
2457 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002458 case OMPRTL__tgt_target_data_update_nowait: {
2459 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002460 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002461 // *arg_types);
2462 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2463 CGM.Int32Ty,
2464 CGM.VoidPtrPtrTy,
2465 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002466 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002467 CGM.Int64Ty->getPointerTo()};
2468 auto *FnTy =
2469 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2470 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
2471 break;
2472 }
Michael Krused47b9432019-08-05 18:43:21 +00002473 case OMPRTL__tgt_mapper_num_components: {
2474 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
2475 llvm::Type *TypeParams[] = {CGM.VoidPtrTy};
2476 auto *FnTy =
2477 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false);
2478 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components");
2479 break;
2480 }
2481 case OMPRTL__tgt_push_mapper_component: {
2482 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void
2483 // *base, void *begin, int64_t size, int64_t type);
2484 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy,
2485 CGM.Int64Ty, CGM.Int64Ty};
2486 auto *FnTy =
2487 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2488 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component");
2489 break;
2490 }
Alexey Bataev9959db52014-05-06 10:08:46 +00002491 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00002492 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00002493 return RTLFn;
2494}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002495
James Y Knight9871db02019-02-05 16:42:33 +00002496llvm::FunctionCallee
2497CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman21212e42015-03-13 10:38:23 +00002498 assert((IVSize == 32 || IVSize == 64) &&
2499 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002500 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
2501 : "__kmpc_for_static_init_4u")
2502 : (IVSigned ? "__kmpc_for_static_init_8"
2503 : "__kmpc_for_static_init_8u");
2504 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2505 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman21212e42015-03-13 10:38:23 +00002506 llvm::Type *TypeParams[] = {
2507 getIdentTyPointerTy(), // loc
2508 CGM.Int32Ty, // tid
2509 CGM.Int32Ty, // schedtype
2510 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2511 PtrTy, // p_lower
2512 PtrTy, // p_upper
2513 PtrTy, // p_stride
2514 ITy, // incr
2515 ITy // chunk
2516 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002517 auto *FnTy =
Alexander Musman21212e42015-03-13 10:38:23 +00002518 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2519 return CGM.CreateRuntimeFunction(FnTy, Name);
2520}
2521
James Y Knight9871db02019-02-05 16:42:33 +00002522llvm::FunctionCallee
2523CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002524 assert((IVSize == 32 || IVSize == 64) &&
2525 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002526 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002527 IVSize == 32
2528 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
2529 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002530 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
Alexander Musman92bdaab2015-03-12 13:37:50 +00002531 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
2532 CGM.Int32Ty, // tid
2533 CGM.Int32Ty, // schedtype
2534 ITy, // lower
2535 ITy, // upper
2536 ITy, // stride
2537 ITy // chunk
2538 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002539 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002540 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2541 return CGM.CreateRuntimeFunction(FnTy, Name);
2542}
2543
James Y Knight9871db02019-02-05 16:42:33 +00002544llvm::FunctionCallee
2545CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002546 assert((IVSize == 32 || IVSize == 64) &&
2547 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002548 StringRef Name =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002549 IVSize == 32
2550 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
2551 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
2552 llvm::Type *TypeParams[] = {
2553 getIdentTyPointerTy(), // loc
2554 CGM.Int32Ty, // tid
2555 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002556 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002557 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2558 return CGM.CreateRuntimeFunction(FnTy, Name);
2559}
2560
James Y Knight9871db02019-02-05 16:42:33 +00002561llvm::FunctionCallee
2562CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002563 assert((IVSize == 32 || IVSize == 64) &&
2564 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002565 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002566 IVSize == 32
2567 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
2568 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002569 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2570 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002571 llvm::Type *TypeParams[] = {
2572 getIdentTyPointerTy(), // loc
2573 CGM.Int32Ty, // tid
2574 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2575 PtrTy, // p_lower
2576 PtrTy, // p_upper
2577 PtrTy // p_stride
2578 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002579 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002580 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2581 return CGM.CreateRuntimeFunction(FnTy, Name);
2582}
2583
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002584/// Obtain information that uniquely identifies a target entry. This
2585/// consists of the file and device IDs as well as line number associated with
2586/// the relevant entry source location.
2587static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
2588 unsigned &DeviceID, unsigned &FileID,
2589 unsigned &LineNum) {
2590 SourceManager &SM = C.getSourceManager();
2591
2592 // The loc should be always valid and have a file ID (the user cannot use
2593 // #pragma directives in macros)
2594
2595 assert(Loc.isValid() && "Source location is expected to be always valid.");
2596
2597 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
2598 assert(PLoc.isValid() && "Source location is expected to be always valid.");
2599
2600 llvm::sys::fs::UniqueID ID;
2601 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
2602 SM.getDiagnostics().Report(diag::err_cannot_open_file)
2603 << PLoc.getFilename() << EC.message();
2604
2605 DeviceID = ID.getDevice();
2606 FileID = ID.getFile();
2607 LineNum = PLoc.getLine();
2608}
2609
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002610Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00002611 if (CGM.getLangOpts().OpenMPSimd)
2612 return Address::invalid();
Alexey Bataev92327c52018-03-26 16:40:55 +00002613 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002614 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002615 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
2616 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2617 HasRequiresUnifiedSharedMemory))) {
Alexey Bataev92327c52018-03-26 16:40:55 +00002618 SmallString<64> PtrName;
2619 {
2620 llvm::raw_svector_ostream OS(PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002621 OS << CGM.getMangledName(GlobalDecl(VD));
2622 if (!VD->isExternallyVisible()) {
2623 unsigned DeviceID, FileID, Line;
2624 getTargetEntryUniqueInfo(CGM.getContext(),
2625 VD->getCanonicalDecl()->getBeginLoc(),
2626 DeviceID, FileID, Line);
2627 OS << llvm::format("_%x", FileID);
2628 }
2629 OS << "_decl_tgt_ref_ptr";
Alexey Bataev92327c52018-03-26 16:40:55 +00002630 }
2631 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
2632 if (!Ptr) {
2633 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
2634 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
2635 PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002636
2637 auto *GV = cast<llvm::GlobalVariable>(Ptr);
2638 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
2639
2640 if (!CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev03f270c2018-03-30 18:31:07 +00002641 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
Alexey Bataev03f270c2018-03-30 18:31:07 +00002642 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
Alexey Bataev92327c52018-03-26 16:40:55 +00002643 }
2644 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
2645 }
2646 return Address::invalid();
2647}
2648
Alexey Bataev97720002014-11-11 04:05:39 +00002649llvm::Constant *
2650CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002651 assert(!CGM.getLangOpts().OpenMPUseTLS ||
2652 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00002653 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev18fa2322018-05-02 14:20:50 +00002654 std::string Suffix = getName({"cache", ""});
2655 return getOrCreateInternalVariable(
2656 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
Alexey Bataev97720002014-11-11 04:05:39 +00002657}
2658
John McCall7f416cc2015-09-08 08:05:57 +00002659Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
2660 const VarDecl *VD,
2661 Address VDAddr,
2662 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002663 if (CGM.getLangOpts().OpenMPUseTLS &&
2664 CGM.getContext().getTargetInfo().isTLSSupported())
2665 return VDAddr;
2666
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002667 llvm::Type *VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002668 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002669 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
2670 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00002671 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
2672 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00002673 return Address(CGF.EmitRuntimeCall(
2674 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2675 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00002676}
2677
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002678void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00002679 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00002680 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
2681 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
2682 // library.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002683 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002684 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00002685 OMPLoc);
2686 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
2687 // to register constructor/destructor for variable.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002688 llvm::Value *Args[] = {
2689 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
2690 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00002691 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002692 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00002693}
2694
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002695llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00002696 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00002697 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002698 if (CGM.getLangOpts().OpenMPUseTLS &&
2699 CGM.getContext().getTargetInfo().isTLSSupported())
2700 return nullptr;
2701
Alexey Bataev97720002014-11-11 04:05:39 +00002702 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002703 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
Alexey Bataev97720002014-11-11 04:05:39 +00002704 QualType ASTTy = VD->getType();
2705
2706 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002707 const Expr *Init = VD->getAnyInitializer();
Alexey Bataev97720002014-11-11 04:05:39 +00002708 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2709 // Generate function that re-emits the declaration's initializer into the
2710 // threadprivate copy of the variable VD
2711 CodeGenFunction CtorCGF(CGM);
2712 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002713 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2714 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002715 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002716 Args.push_back(&Dst);
2717
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002718 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002719 CGM.getContext().VoidPtrTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002720 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002721 std::string Name = getName({"__kmpc_global_ctor_", ""});
2722 llvm::Function *Fn =
2723 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002724 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002725 Args, Loc, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002726 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002727 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002728 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00002729 Address Arg = Address(ArgVal, VDAddr.getAlignment());
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002730 Arg = CtorCGF.Builder.CreateElementBitCast(
2731 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00002732 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
2733 /*IsInitializer=*/true);
2734 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002735 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002736 CGM.getContext().VoidPtrTy, Dst.getLocation());
2737 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
2738 CtorCGF.FinishFunction();
2739 Ctor = Fn;
2740 }
2741 if (VD->getType().isDestructedType() != QualType::DK_none) {
2742 // Generate function that emits destructor call for the threadprivate copy
2743 // of the variable VD
2744 CodeGenFunction DtorCGF(CGM);
2745 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002746 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2747 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002748 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002749 Args.push_back(&Dst);
2750
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002751 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002752 CGM.getContext().VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002753 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002754 std::string Name = getName({"__kmpc_global_dtor_", ""});
2755 llvm::Function *Fn =
2756 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002757 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00002758 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002759 Loc, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002760 // Create a scope with an artificial location for the body of this function.
2761 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002762 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
Alexey Bataev97720002014-11-11 04:05:39 +00002763 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00002764 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
2765 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00002766 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2767 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2768 DtorCGF.FinishFunction();
2769 Dtor = Fn;
2770 }
2771 // Do not emit init function if it is not required.
2772 if (!Ctor && !Dtor)
2773 return nullptr;
2774
2775 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002776 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
2777 /*isVarArg=*/false)
2778 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002779 // Copying constructor for the threadprivate variable.
2780 // Must be NULL - reserved by runtime, but currently it requires that this
2781 // parameter is always NULL. Otherwise it fires assertion.
2782 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
2783 if (Ctor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002784 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
2785 /*isVarArg=*/false)
2786 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002787 Ctor = llvm::Constant::getNullValue(CtorTy);
2788 }
2789 if (Dtor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002790 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
2791 /*isVarArg=*/false)
2792 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002793 Dtor = llvm::Constant::getNullValue(DtorTy);
2794 }
2795 if (!CGF) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002796 auto *InitFunctionTy =
Alexey Bataev97720002014-11-11 04:05:39 +00002797 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002798 std::string Name = getName({"__omp_threadprivate_init_", ""});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002799 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Alexey Bataev18fa2322018-05-02 14:20:50 +00002800 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00002801 CodeGenFunction InitCGF(CGM);
2802 FunctionArgList ArgList;
2803 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
2804 CGM.getTypes().arrangeNullaryFunction(), ArgList,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002805 Loc, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002806 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002807 InitCGF.FinishFunction();
2808 return InitFunction;
2809 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002810 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002811 }
2812 return nullptr;
2813}
2814
Alexey Bataev34f8a702018-03-28 14:28:54 +00002815bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
2816 llvm::GlobalVariable *Addr,
2817 bool PerformInit) {
Alexey Bataev4db9dc62019-09-23 15:53:51 +00002818 if (CGM.getLangOpts().OMPTargetTriples.empty())
2819 return false;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002820 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002821 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002822 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
2823 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2824 HasRequiresUnifiedSharedMemory))
Alexey Bataevd01b7492018-08-15 19:45:12 +00002825 return CGM.getLangOpts().OpenMPIsDevice;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002826 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002827 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
Alexey Bataev34f8a702018-03-28 14:28:54 +00002828 return CGM.getLangOpts().OpenMPIsDevice;
2829
2830 QualType ASTTy = VD->getType();
2831
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002832 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002833 // Produce the unique prefix to identify the new target regions. We use
2834 // the source location of the variable declaration which we know to not
2835 // conflict with any target region.
2836 unsigned DeviceID;
2837 unsigned FileID;
2838 unsigned Line;
2839 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2840 SmallString<128> Buffer, Out;
2841 {
2842 llvm::raw_svector_ostream OS(Buffer);
2843 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2844 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2845 }
2846
2847 const Expr *Init = VD->getAnyInitializer();
2848 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2849 llvm::Constant *Ctor;
2850 llvm::Constant *ID;
2851 if (CGM.getLangOpts().OpenMPIsDevice) {
2852 // Generate function that re-emits the declaration's initializer into
2853 // the threadprivate copy of the variable VD
2854 CodeGenFunction CtorCGF(CGM);
2855
2856 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2857 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2858 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2859 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2860 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2861 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2862 FunctionArgList(), Loc, Loc);
2863 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2864 CtorCGF.EmitAnyExprToMem(Init,
2865 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2866 Init->getType().getQualifiers(),
2867 /*IsInitializer=*/true);
2868 CtorCGF.FinishFunction();
2869 Ctor = Fn;
2870 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002871 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002872 } else {
2873 Ctor = new llvm::GlobalVariable(
2874 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2875 llvm::GlobalValue::PrivateLinkage,
2876 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2877 ID = Ctor;
2878 }
2879
2880 // Register the information for the entry associated with the constructor.
2881 Out.clear();
2882 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2883 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002884 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002885 }
2886 if (VD->getType().isDestructedType() != QualType::DK_none) {
2887 llvm::Constant *Dtor;
2888 llvm::Constant *ID;
2889 if (CGM.getLangOpts().OpenMPIsDevice) {
2890 // Generate function that emits destructor call for the threadprivate
2891 // copy of the variable VD
2892 CodeGenFunction DtorCGF(CGM);
2893
2894 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2895 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2896 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2897 FTy, Twine(Buffer, "_dtor"), FI, Loc);
2898 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
2899 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2900 FunctionArgList(), Loc, Loc);
2901 // Create a scope with an artificial location for the body of this
2902 // function.
2903 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
2904 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
2905 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2906 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2907 DtorCGF.FinishFunction();
2908 Dtor = Fn;
2909 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002910 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002911 } else {
2912 Dtor = new llvm::GlobalVariable(
2913 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2914 llvm::GlobalValue::PrivateLinkage,
2915 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
2916 ID = Dtor;
2917 }
2918 // Register the information for the entry associated with the destructor.
2919 Out.clear();
2920 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2921 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002922 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002923 }
2924 return CGM.getLangOpts().OpenMPIsDevice;
2925}
2926
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002927Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2928 QualType VarType,
2929 StringRef Name) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00002930 std::string Suffix = getName({"artificial", ""});
2931 std::string CacheSuffix = getName({"cache", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002932 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002933 llvm::Value *GAddr =
2934 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002935 llvm::Value *Args[] = {
2936 emitUpdateLocation(CGF, SourceLocation()),
2937 getThreadID(CGF, SourceLocation()),
2938 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
2939 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002940 /*isSigned=*/false),
Alexey Bataev18fa2322018-05-02 14:20:50 +00002941 getOrCreateInternalVariable(
2942 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002943 return Address(
2944 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2945 CGF.EmitRuntimeCall(
2946 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2947 VarLVType->getPointerTo(/*AddrSpace=*/0)),
2948 CGM.getPointerAlign());
2949}
2950
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +00002951void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
2952 const RegionCodeGenTy &ThenGen,
2953 const RegionCodeGenTy &ElseGen) {
Alexey Bataev1d677132015-04-22 13:57:31 +00002954 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
2955
2956 // If the condition constant folds and can be elided, try to avoid emitting
2957 // the condition and the dead arm of the if/else.
2958 bool CondConstant;
2959 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002960 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00002961 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002962 else
Alexey Bataev1d677132015-04-22 13:57:31 +00002963 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00002964 return;
2965 }
2966
2967 // Otherwise, the condition did not fold, or we couldn't elide it. Just
2968 // emit the conditional branch.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002969 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
2970 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
2971 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
Alexey Bataev1d677132015-04-22 13:57:31 +00002972 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
2973
2974 // Emit the 'then' code.
2975 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002976 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00002977 CGF.EmitBranch(ContBlock);
2978 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002979 // There is no need to emit line number for unconditional branch.
2980 (void)ApplyDebugLocation::CreateEmpty(CGF);
2981 CGF.EmitBlock(ElseBlock);
2982 ElseGen(CGF);
2983 // There is no need to emit line number for unconditional branch.
2984 (void)ApplyDebugLocation::CreateEmpty(CGF);
2985 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00002986 // Emit the continuation block for code after the if.
2987 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002988}
2989
Alexey Bataev1d677132015-04-22 13:57:31 +00002990void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00002991 llvm::Function *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002992 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00002993 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002994 if (!CGF.HaveInsertPoint())
2995 return;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002996 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002997 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
2998 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00002999 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003000 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00003001 llvm::Value *Args[] = {
3002 RTLoc,
3003 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003004 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00003005 llvm::SmallVector<llvm::Value *, 16> RealArgs;
3006 RealArgs.append(std::begin(Args), std::end(Args));
3007 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
3008
James Y Knight9871db02019-02-05 16:42:33 +00003009 llvm::FunctionCallee RTLFn =
3010 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00003011 CGF.EmitRuntimeCall(RTLFn, RealArgs);
3012 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003013 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
3014 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003015 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
3016 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00003017 // Build calls:
3018 // __kmpc_serialized_parallel(&Loc, GTid);
3019 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003020 CGF.EmitRuntimeCall(
3021 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003022
Alexey Bataev1d677132015-04-22 13:57:31 +00003023 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003024 Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
3025 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00003026 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00003027 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
Alexey Bataev8521ff62018-07-25 20:03:01 +00003028 // ThreadId for serialized parallels is 0.
3029 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003030 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
3031 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev3c595a62017-08-14 15:01:03 +00003032 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003033
Alexey Bataev1d677132015-04-22 13:57:31 +00003034 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003035 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00003036 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003037 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
3038 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00003039 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003040 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003041 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003042 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003043 RegionCodeGenTy ThenRCG(ThenGen);
3044 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003045 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00003046}
3047
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00003048// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00003049// thread-ID variable (it is passed in a first argument of the outlined function
3050// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
3051// regular serial code region, get thread ID by calling kmp_int32
3052// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
3053// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00003054Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
3055 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003056 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003057 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003058 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00003059 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003060
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003061 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3062 QualType Int32Ty =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003063 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003064 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
Alexey Bataevd74d0602014-10-13 06:02:40 +00003065 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00003066 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00003067
3068 return ThreadIDTemp;
3069}
3070
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003071llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
3072 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003073 SmallString<256> Buffer;
3074 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00003075 Out << Name;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003076 StringRef RuntimeName = Out.str();
Alexey Bataev43a919f2018-04-13 17:48:43 +00003077 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
David Blaikie13156b62014-11-19 03:06:06 +00003078 if (Elem.second) {
3079 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00003080 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00003081 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00003082 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003083
David Blaikie13156b62014-11-19 03:06:06 +00003084 return Elem.second = new llvm::GlobalVariable(
3085 CGM.getModule(), Ty, /*IsConstant*/ false,
3086 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003087 Elem.first(), /*InsertBefore=*/nullptr,
3088 llvm::GlobalValue::NotThreadLocal, AddressSpace);
Alexey Bataev97720002014-11-11 04:05:39 +00003089}
3090
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003091llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00003092 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
3093 std::string Name = getName({Prefix, "var"});
3094 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003095}
3096
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003097namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003098/// Common pre(post)-action for different OpenMP constructs.
3099class CommonActionTy final : public PrePostActionTy {
James Y Knight9871db02019-02-05 16:42:33 +00003100 llvm::FunctionCallee EnterCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003101 ArrayRef<llvm::Value *> EnterArgs;
James Y Knight9871db02019-02-05 16:42:33 +00003102 llvm::FunctionCallee ExitCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003103 ArrayRef<llvm::Value *> ExitArgs;
3104 bool Conditional;
3105 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003106
3107public:
James Y Knight9871db02019-02-05 16:42:33 +00003108 CommonActionTy(llvm::FunctionCallee EnterCallee,
3109 ArrayRef<llvm::Value *> EnterArgs,
3110 llvm::FunctionCallee ExitCallee,
3111 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003112 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3113 ExitArgs(ExitArgs), Conditional(Conditional) {}
3114 void Enter(CodeGenFunction &CGF) override {
3115 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3116 if (Conditional) {
3117 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3118 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3119 ContBlock = CGF.createBasicBlock("omp_if.end");
3120 // Generate the branch (If-stmt)
3121 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3122 CGF.EmitBlock(ThenBlock);
3123 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00003124 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003125 void Done(CodeGenFunction &CGF) {
3126 // Emit the rest of blocks/branches
3127 CGF.EmitBranch(ContBlock);
3128 CGF.EmitBlock(ContBlock, true);
3129 }
3130 void Exit(CodeGenFunction &CGF) override {
3131 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00003132 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003133};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003134} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003135
3136void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3137 StringRef CriticalName,
3138 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00003139 SourceLocation Loc, const Expr *Hint) {
3140 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00003141 // CriticalOpGen();
3142 // __kmpc_end_critical(ident_t *, gtid, Lock);
3143 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00003144 if (!CGF.HaveInsertPoint())
3145 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00003146 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3147 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003148 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3149 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00003150 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003151 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3152 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3153 }
3154 CommonActionTy Action(
3155 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3156 : OMPRTL__kmpc_critical),
3157 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3158 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003159 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003160}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003161
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003162void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003163 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003164 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003165 if (!CGF.HaveInsertPoint())
3166 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00003167 // if(__kmpc_master(ident_t *, gtid)) {
3168 // MasterOpGen();
3169 // __kmpc_end_master(ident_t *, gtid);
3170 // }
3171 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003172 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003173 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3174 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3175 /*Conditional=*/true);
3176 MasterOpGen.setAction(Action);
3177 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3178 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00003179}
3180
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003181void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3182 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003183 if (!CGF.HaveInsertPoint())
3184 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00003185 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3186 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003187 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00003188 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003189 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003190 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3191 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00003192}
3193
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003194void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3195 const RegionCodeGenTy &TaskgroupOpGen,
3196 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003197 if (!CGF.HaveInsertPoint())
3198 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003199 // __kmpc_taskgroup(ident_t *, gtid);
3200 // TaskgroupOpGen();
3201 // __kmpc_end_taskgroup(ident_t *, gtid);
3202 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003203 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3204 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3205 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3206 Args);
3207 TaskgroupOpGen.setAction(Action);
3208 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003209}
3210
John McCall7f416cc2015-09-08 08:05:57 +00003211/// Given an array of pointers to variables, project the address of a
3212/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003213static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3214 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00003215 // Pull out the pointer to the variable.
James Y Knight751fe282019-02-09 22:22:28 +00003216 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
John McCall7f416cc2015-09-08 08:05:57 +00003217 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3218
3219 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003220 Addr = CGF.Builder.CreateElementBitCast(
3221 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00003222 return Addr;
3223}
3224
Alexey Bataeva63048e2015-03-23 06:18:07 +00003225static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00003226 CodeGenModule &CGM, llvm::Type *ArgsType,
3227 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003228 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3229 SourceLocation Loc) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003230 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003231 // void copy_func(void *LHSArg, void *RHSArg);
3232 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003233 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3234 ImplicitParamDecl::Other);
3235 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3236 ImplicitParamDecl::Other);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003237 Args.push_back(&LHSArg);
3238 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003239 const auto &CGFI =
3240 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003241 std::string Name =
3242 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3243 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3244 llvm::GlobalValue::InternalLinkage, Name,
3245 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00003246 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00003247 Fn->setDoesNotRecurse();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003248 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003249 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev420d45b2015-04-14 05:11:24 +00003250 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003251 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003252 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3253 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3254 ArgsType), CGF.getPointerAlign());
3255 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3256 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3257 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003258 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3259 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3260 // ...
3261 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00003262 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003263 const auto *DestVar =
3264 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003265 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3266
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003267 const auto *SrcVar =
3268 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003269 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3270
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003271 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003272 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00003273 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003274 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003275 CGF.FinishFunction();
3276 return Fn;
3277}
3278
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003279void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003280 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00003281 SourceLocation Loc,
3282 ArrayRef<const Expr *> CopyprivateVars,
3283 ArrayRef<const Expr *> SrcExprs,
3284 ArrayRef<const Expr *> DstExprs,
3285 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003286 if (!CGF.HaveInsertPoint())
3287 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003288 assert(CopyprivateVars.size() == SrcExprs.size() &&
3289 CopyprivateVars.size() == DstExprs.size() &&
3290 CopyprivateVars.size() == AssignmentOps.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003291 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003292 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003293 // if(__kmpc_single(ident_t *, gtid)) {
3294 // SingleOpGen();
3295 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003296 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003297 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003298 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3299 // <copy_func>, did_it);
3300
John McCall7f416cc2015-09-08 08:05:57 +00003301 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003302 if (!CopyprivateVars.empty()) {
3303 // int32 did_it = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003304 QualType KmpInt32Ty =
3305 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003306 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00003307 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003308 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003309 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003310 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003311 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3312 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3313 /*Conditional=*/true);
3314 SingleOpGen.setAction(Action);
3315 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3316 if (DidIt.isValid()) {
3317 // did_it = 1;
3318 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3319 }
3320 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003321 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3322 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00003323 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003324 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003325 QualType CopyprivateArrayTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003326 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
3327 /*IndexTypeQuals=*/0);
3328 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00003329 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003330 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3331 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +00003332 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
John McCall7f416cc2015-09-08 08:05:57 +00003333 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003334 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003335 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
3336 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003337 }
3338 // Build function that copies private values from single region to all other
3339 // threads in the corresponding parallel region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003340 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003341 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003342 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003343 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003344 Address CL =
3345 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3346 CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003347 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003348 llvm::Value *Args[] = {
3349 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3350 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00003351 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00003352 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00003353 CpyFn, // void (*) (void *, void *) <copy_func>
3354 DidItVal // i32 did_it
3355 };
3356 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3357 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003358}
3359
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003360void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3361 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00003362 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003363 if (!CGF.HaveInsertPoint())
3364 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003365 // __kmpc_ordered(ident_t *, gtid);
3366 // OrderedOpGen();
3367 // __kmpc_end_ordered(ident_t *, gtid);
3368 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00003369 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003370 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003371 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3372 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3373 Args);
3374 OrderedOpGen.setAction(Action);
3375 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3376 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003377 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00003378 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003379}
3380
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003381unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003382 unsigned Flags;
3383 if (Kind == OMPD_for)
3384 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3385 else if (Kind == OMPD_sections)
3386 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3387 else if (Kind == OMPD_single)
3388 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3389 else if (Kind == OMPD_barrier)
3390 Flags = OMP_IDENT_BARRIER_EXPL;
3391 else
3392 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003393 return Flags;
3394}
3395
Alexey Bataevf6a53d62019-03-18 18:40:00 +00003396void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3397 CodeGenFunction &CGF, const OMPLoopDirective &S,
3398 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3399 // Check if the loop directive is actually a doacross loop directive. In this
3400 // case choose static, 1 schedule.
3401 if (llvm::any_of(
3402 S.getClausesOfKind<OMPOrderedClause>(),
3403 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3404 ScheduleKind = OMPC_SCHEDULE_static;
3405 // Chunk size is 1 in this case.
3406 llvm::APInt ChunkSize(32, 1);
3407 ChunkExpr = IntegerLiteral::Create(
3408 CGF.getContext(), ChunkSize,
3409 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3410 SourceLocation());
3411 }
3412}
3413
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003414void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3415 OpenMPDirectiveKind Kind, bool EmitChecks,
3416 bool ForceSimpleCall) {
3417 if (!CGF.HaveInsertPoint())
3418 return;
3419 // Build call __kmpc_cancel_barrier(loc, thread_id);
3420 // Build call __kmpc_barrier(loc, thread_id);
3421 unsigned Flags = getDefaultFlagsForBarriers(Kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003422 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3423 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003424 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3425 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003426 if (auto *OMPRegionInfo =
3427 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003428 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003429 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003430 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003431 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003432 // if (__kmpc_cancel_barrier()) {
3433 // exit from construct;
3434 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003435 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3436 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3437 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003438 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3439 CGF.EmitBlock(ExitBB);
3440 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003441 CodeGenFunction::JumpDest CancelDestination =
Alexey Bataev25e5b442015-09-15 12:52:43 +00003442 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003443 CGF.EmitBranchThroughCleanup(CancelDestination);
3444 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3445 }
3446 return;
3447 }
3448 }
3449 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003450}
3451
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003452/// Map the OpenMP loop schedule to the runtime enumeration.
Alexander Musmanc6388682014-12-15 07:07:06 +00003453static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003454 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00003455 switch (ScheduleKind) {
3456 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003457 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3458 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00003459 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003460 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003461 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003462 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003463 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003464 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3465 case OMPC_SCHEDULE_auto:
3466 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00003467 case OMPC_SCHEDULE_unknown:
3468 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003469 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00003470 }
3471 llvm_unreachable("Unexpected runtime schedule");
3472}
3473
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003474/// Map the OpenMP distribute schedule to the runtime enumeration.
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003475static OpenMPSchedType
3476getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3477 // only static is allowed for dist_schedule
3478 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3479}
3480
Alexander Musmanc6388682014-12-15 07:07:06 +00003481bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3482 bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003483 OpenMPSchedType Schedule =
3484 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00003485 return Schedule == OMP_sch_static;
3486}
3487
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003488bool CGOpenMPRuntime::isStaticNonchunked(
3489 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003490 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003491 return Schedule == OMP_dist_sch_static;
3492}
3493
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003494bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3495 bool Chunked) const {
3496 OpenMPSchedType Schedule =
3497 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3498 return Schedule == OMP_sch_static_chunked;
3499}
3500
3501bool CGOpenMPRuntime::isStaticChunked(
3502 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3503 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3504 return Schedule == OMP_dist_sch_static_chunked;
3505}
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003506
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003507bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003508 OpenMPSchedType Schedule =
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003509 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003510 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
3511 return Schedule != OMP_sch_static;
3512}
3513
Alexey Bataev07a3b592019-08-23 19:52:05 +00003514static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003515 OpenMPScheduleClauseModifier M1,
3516 OpenMPScheduleClauseModifier M2) {
Alexey Bataev6cff6242016-05-30 13:05:14 +00003517 int Modifier = 0;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003518 switch (M1) {
3519 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003520 Modifier = OMP_sch_modifier_monotonic;
3521 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003522 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003523 Modifier = OMP_sch_modifier_nonmonotonic;
3524 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003525 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003526 if (Schedule == OMP_sch_static_chunked)
3527 Schedule = OMP_sch_static_balanced_chunked;
3528 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003529 case OMPC_SCHEDULE_MODIFIER_last:
3530 case OMPC_SCHEDULE_MODIFIER_unknown:
3531 break;
3532 }
3533 switch (M2) {
3534 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003535 Modifier = OMP_sch_modifier_monotonic;
3536 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003537 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003538 Modifier = OMP_sch_modifier_nonmonotonic;
3539 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003540 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003541 if (Schedule == OMP_sch_static_chunked)
3542 Schedule = OMP_sch_static_balanced_chunked;
3543 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003544 case OMPC_SCHEDULE_MODIFIER_last:
3545 case OMPC_SCHEDULE_MODIFIER_unknown:
3546 break;
3547 }
Alexey Bataev07a3b592019-08-23 19:52:05 +00003548 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
3549 // If the static schedule kind is specified or if the ordered clause is
3550 // specified, and if the nonmonotonic modifier is not specified, the effect is
3551 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
3552 // modifier is specified, the effect is as if the nonmonotonic modifier is
3553 // specified.
3554 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
3555 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
3556 Schedule == OMP_sch_static_balanced_chunked ||
3557 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static))
3558 Modifier = OMP_sch_modifier_nonmonotonic;
3559 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003560 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003561}
3562
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003563void CGOpenMPRuntime::emitForDispatchInit(
3564 CodeGenFunction &CGF, SourceLocation Loc,
3565 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3566 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003567 if (!CGF.HaveInsertPoint())
3568 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003569 OpenMPSchedType Schedule = getRuntimeSchedule(
3570 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003571 assert(Ordered ||
3572 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003573 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3574 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003575 // Call __kmpc_dispatch_init(
3576 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3577 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3578 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003579
John McCall7f416cc2015-09-08 08:05:57 +00003580 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003581 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3582 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003583 llvm::Value *Args[] = {
Alexey Bataev07a3b592019-08-23 19:52:05 +00003584 emitUpdateLocation(CGF, Loc),
3585 getThreadID(CGF, Loc),
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003586 CGF.Builder.getInt32(addMonoNonMonoModifier(
Alexey Bataev07a3b592019-08-23 19:52:05 +00003587 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
3588 DispatchValues.LB, // Lower
3589 DispatchValues.UB, // Upper
3590 CGF.Builder.getIntN(IVSize, 1), // Stride
3591 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003592 };
3593 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3594}
3595
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003596static void emitForStaticInitCall(
3597 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003598 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003599 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003600 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003601 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003602 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003603
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003604 assert(!Values.Ordered);
3605 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3606 Schedule == OMP_sch_static_balanced_chunked ||
3607 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3608 Schedule == OMP_dist_sch_static ||
3609 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003610
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003611 // Call __kmpc_for_static_init(
3612 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3613 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3614 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3615 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3616 llvm::Value *Chunk = Values.Chunk;
3617 if (Chunk == nullptr) {
3618 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3619 Schedule == OMP_dist_sch_static) &&
3620 "expected static non-chunked schedule");
3621 // If the Chunk was not specified in the clause - use default value 1.
3622 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3623 } else {
3624 assert((Schedule == OMP_sch_static_chunked ||
3625 Schedule == OMP_sch_static_balanced_chunked ||
3626 Schedule == OMP_ord_static_chunked ||
3627 Schedule == OMP_dist_sch_static_chunked) &&
3628 "expected static chunked schedule");
3629 }
3630 llvm::Value *Args[] = {
3631 UpdateLocation,
3632 ThreadId,
Alexey Bataev07a3b592019-08-23 19:52:05 +00003633 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003634 M2)), // Schedule type
3635 Values.IL.getPointer(), // &isLastIter
3636 Values.LB.getPointer(), // &LB
3637 Values.UB.getPointer(), // &UB
3638 Values.ST.getPointer(), // &Stride
3639 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3640 Chunk // Chunk
3641 };
3642 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003643}
3644
John McCall7f416cc2015-09-08 08:05:57 +00003645void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3646 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003647 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003648 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003649 const StaticRTInput &Values) {
3650 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3651 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3652 assert(isOpenMPWorksharingDirective(DKind) &&
3653 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003654 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003655 isOpenMPLoopDirective(DKind)
3656 ? OMP_IDENT_WORK_LOOP
3657 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003658 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003659 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003660 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003661 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003662 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003663}
John McCall7f416cc2015-09-08 08:05:57 +00003664
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003665void CGOpenMPRuntime::emitDistributeStaticInit(
3666 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003667 OpenMPDistScheduleClauseKind SchedKind,
3668 const CGOpenMPRuntime::StaticRTInput &Values) {
3669 OpenMPSchedType ScheduleNum =
3670 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003671 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003672 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003673 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003674 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003675 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003676 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3677 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003678 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003679}
3680
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003681void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003682 SourceLocation Loc,
3683 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003684 if (!CGF.HaveInsertPoint())
3685 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003686 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003687 llvm::Value *Args[] = {
3688 emitUpdateLocation(CGF, Loc,
3689 isOpenMPDistributeDirective(DKind)
3690 ? OMP_IDENT_WORK_DISTRIBUTE
3691 : isOpenMPLoopDirective(DKind)
3692 ? OMP_IDENT_WORK_LOOP
3693 : OMP_IDENT_WORK_SECTIONS),
3694 getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003695 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3696 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003697}
3698
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003699void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3700 SourceLocation Loc,
3701 unsigned IVSize,
3702 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003703 if (!CGF.HaveInsertPoint())
3704 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003705 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003706 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003707 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3708}
3709
Alexander Musman92bdaab2015-03-12 13:37:50 +00003710llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3711 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003712 bool IVSigned, Address IL,
3713 Address LB, Address UB,
3714 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003715 // Call __kmpc_dispatch_next(
3716 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3717 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3718 // kmp_int[32|64] *p_stride);
3719 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003720 emitUpdateLocation(CGF, Loc),
3721 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003722 IL.getPointer(), // &isLastIter
3723 LB.getPointer(), // &Lower
3724 UB.getPointer(), // &Upper
3725 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003726 };
3727 llvm::Value *Call =
3728 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3729 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003730 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003731 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003732}
3733
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003734void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3735 llvm::Value *NumThreads,
3736 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003737 if (!CGF.HaveInsertPoint())
3738 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003739 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3740 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003741 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003742 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003743 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3744 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003745}
3746
Alexey Bataev7f210c62015-06-18 13:40:03 +00003747void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3748 OpenMPProcBindClauseKind ProcBind,
3749 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003750 if (!CGF.HaveInsertPoint())
3751 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00003752 // Constants for proc bind value accepted by the runtime.
3753 enum ProcBindTy {
3754 ProcBindFalse = 0,
3755 ProcBindTrue,
3756 ProcBindMaster,
3757 ProcBindClose,
3758 ProcBindSpread,
3759 ProcBindIntel,
3760 ProcBindDefault
3761 } RuntimeProcBind;
3762 switch (ProcBind) {
3763 case OMPC_PROC_BIND_master:
3764 RuntimeProcBind = ProcBindMaster;
3765 break;
3766 case OMPC_PROC_BIND_close:
3767 RuntimeProcBind = ProcBindClose;
3768 break;
3769 case OMPC_PROC_BIND_spread:
3770 RuntimeProcBind = ProcBindSpread;
3771 break;
3772 case OMPC_PROC_BIND_unknown:
3773 llvm_unreachable("Unsupported proc_bind value.");
3774 }
3775 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3776 llvm::Value *Args[] = {
3777 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3778 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
3779 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3780}
3781
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003782void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3783 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003784 if (!CGF.HaveInsertPoint())
3785 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00003786 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003787 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3788 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003789}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003790
Alexey Bataev62b63b12015-03-10 07:28:44 +00003791namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003792/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003793enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003794 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003795 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003796 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003797 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003798 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003799 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003800 /// Function with call of destructors for private variables.
3801 Data1,
3802 /// Task priority.
3803 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003804 /// (Taskloops only) Lower bound.
3805 KmpTaskTLowerBound,
3806 /// (Taskloops only) Upper bound.
3807 KmpTaskTUpperBound,
3808 /// (Taskloops only) Stride.
3809 KmpTaskTStride,
3810 /// (Taskloops only) Is last iteration flag.
3811 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003812 /// (Taskloops only) Reduction data.
3813 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003814};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003815} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003816
Samuel Antaoee8fb302016-01-06 13:42:12 +00003817bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003818 return OffloadEntriesTargetRegion.empty() &&
3819 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003820}
3821
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003822/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003823void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3824 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3825 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003826 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003827 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3828 "only required for the device "
3829 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003830 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003831 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003832 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003833 ++OffloadingEntriesNum;
3834}
3835
3836void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3837 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3838 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003839 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003840 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003841 // If we are emitting code for a target, the entry is already initialized,
3842 // only has to be registered.
3843 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003844 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3845 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3846 DiagnosticsEngine::Error,
3847 "Unable to find target region on line '%0' in the device code.");
3848 CGM.getDiags().Report(DiagID) << LineNum;
3849 return;
3850 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003851 auto &Entry =
3852 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003853 assert(Entry.isValid() && "Entry not initialized!");
3854 Entry.setAddress(Addr);
3855 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003856 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003857 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003858 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003859 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003860 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003861 }
3862}
3863
3864bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003865 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3866 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003867 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3868 if (PerDevice == OffloadEntriesTargetRegion.end())
3869 return false;
3870 auto PerFile = PerDevice->second.find(FileID);
3871 if (PerFile == PerDevice->second.end())
3872 return false;
3873 auto PerParentName = PerFile->second.find(ParentName);
3874 if (PerParentName == PerFile->second.end())
3875 return false;
3876 auto PerLine = PerParentName->second.find(LineNum);
3877 if (PerLine == PerParentName->second.end())
3878 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003879 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003880 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003881 return false;
3882 return true;
3883}
3884
3885void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3886 const OffloadTargetRegionEntryInfoActTy &Action) {
3887 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003888 for (const auto &D : OffloadEntriesTargetRegion)
3889 for (const auto &F : D.second)
3890 for (const auto &P : F.second)
3891 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00003892 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003893}
3894
Alexey Bataev03f270c2018-03-30 18:31:07 +00003895void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3896 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3897 OMPTargetGlobalVarEntryKind Flags,
3898 unsigned Order) {
3899 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3900 "only required for the device "
3901 "code generation.");
3902 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3903 ++OffloadingEntriesNum;
3904}
Samuel Antaoee8fb302016-01-06 13:42:12 +00003905
Alexey Bataev03f270c2018-03-30 18:31:07 +00003906void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3907 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3908 CharUnits VarSize,
3909 OMPTargetGlobalVarEntryKind Flags,
3910 llvm::GlobalValue::LinkageTypes Linkage) {
3911 if (CGM.getLangOpts().OpenMPIsDevice) {
3912 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3913 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3914 "Entry not initialized!");
3915 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3916 "Resetting with the new address.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00003917 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3918 if (Entry.getVarSize().isZero()) {
3919 Entry.setVarSize(VarSize);
3920 Entry.setLinkage(Linkage);
3921 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003922 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003923 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003924 Entry.setVarSize(VarSize);
3925 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00003926 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003927 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00003928 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3929 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3930 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3931 "Entry not initialized!");
3932 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3933 "Resetting with the new address.");
3934 if (Entry.getVarSize().isZero()) {
3935 Entry.setVarSize(VarSize);
3936 Entry.setLinkage(Linkage);
3937 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003938 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003939 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003940 OffloadEntriesDeviceGlobalVar.try_emplace(
3941 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
3942 ++OffloadingEntriesNum;
3943 }
3944}
3945
3946void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3947 actOnDeviceGlobalVarEntriesInfo(
3948 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
3949 // Scan all target region entries and perform the provided action.
3950 for (const auto &E : OffloadEntriesDeviceGlobalVar)
3951 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00003952}
3953
3954llvm::Function *
3955CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003956 // If we don't have entries or if we are emitting code for the device, we
3957 // don't need to do anything.
3958 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
3959 return nullptr;
3960
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003961 llvm::Module &M = CGM.getModule();
3962 ASTContext &C = CGM.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003963
3964 // Get list of devices we care about
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003965 const std::vector<llvm::Triple> &Devices = CGM.getLangOpts().OMPTargetTriples;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003966
3967 // We should be creating an offloading descriptor only if there are devices
3968 // specified.
3969 assert(!Devices.empty() && "No OpenMP offloading devices??");
3970
3971 // Create the external variables that will point to the begin and end of the
3972 // host entries section. These will be defined by the linker.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003973 llvm::Type *OffloadEntryTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00003974 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003975 auto *HostEntriesBegin = new llvm::GlobalVariable(
Samuel Antaoee8fb302016-01-06 13:42:12 +00003976 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00003977 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Sergey Dmitriev4b343fd2019-09-27 20:00:51 +00003978 "__start_omp_offloading_entries");
3979 HostEntriesBegin->setVisibility(llvm::GlobalValue::HiddenVisibility);
3980 auto *HostEntriesEnd = new llvm::GlobalVariable(
3981 M, OffloadEntryTy, /*isConstant=*/true,
3982 llvm::GlobalValue::ExternalLinkage,
3983 /*Initializer=*/nullptr, "__stop_omp_offloading_entries");
3984 HostEntriesEnd->setVisibility(llvm::GlobalValue::HiddenVisibility);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003985
3986 // Create all device images
Samuel Antaoee8fb302016-01-06 13:42:12 +00003987 auto *DeviceImageTy = cast<llvm::StructType>(
3988 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
John McCall23c9dc62016-11-28 22:18:27 +00003989 ConstantInitBuilder DeviceImagesBuilder(CGM);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003990 ConstantArrayBuilder DeviceImagesEntries =
3991 DeviceImagesBuilder.beginArray(DeviceImageTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003992
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003993 for (const llvm::Triple &Device : Devices) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003994 StringRef T = Device.getTriple();
Alexey Bataev18fa2322018-05-02 14:20:50 +00003995 std::string BeginName = getName({"omp_offloading", "img_start", ""});
Samuel Antaoee8fb302016-01-06 13:42:12 +00003996 auto *ImgBegin = new llvm::GlobalVariable(
Alexey Bataev62a4cb02018-07-31 18:27:42 +00003997 M, CGM.Int8Ty, /*isConstant=*/true,
3998 llvm::GlobalValue::ExternalWeakLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00003999 /*Initializer=*/nullptr, Twine(BeginName).concat(T));
4000 std::string EndName = getName({"omp_offloading", "img_end", ""});
Samuel Antaoee8fb302016-01-06 13:42:12 +00004001 auto *ImgEnd = new llvm::GlobalVariable(
Alexey Bataev62a4cb02018-07-31 18:27:42 +00004002 M, CGM.Int8Ty, /*isConstant=*/true,
4003 llvm::GlobalValue::ExternalWeakLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004004 /*Initializer=*/nullptr, Twine(EndName).concat(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004005
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004006 llvm::Constant *Data[] = {ImgBegin, ImgEnd, HostEntriesBegin,
4007 HostEntriesEnd};
4008 createConstantGlobalStructAndAddToParent(CGM, getTgtDeviceImageQTy(), Data,
4009 DeviceImagesEntries);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004010 }
4011
4012 // Create device images global array.
Alexey Bataev18fa2322018-05-02 14:20:50 +00004013 std::string ImagesName = getName({"omp_offloading", "device_images"});
John McCall6c9f1fdb2016-11-19 08:17:24 +00004014 llvm::GlobalVariable *DeviceImages =
Alexey Bataev18fa2322018-05-02 14:20:50 +00004015 DeviceImagesEntries.finishAndCreateGlobal(ImagesName,
4016 CGM.getPointerAlign(),
4017 /*isConstant=*/true);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004018 DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004019
4020 // This is a Zero array to be used in the creation of the constant expressions
4021 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
4022 llvm::Constant::getNullValue(CGM.Int32Ty)};
4023
4024 // Create the target region descriptor.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004025 llvm::Constant *Data[] = {
4026 llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
4027 llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(),
4028 DeviceImages, Index),
4029 HostEntriesBegin, HostEntriesEnd};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004030 std::string Descriptor = getName({"omp_offloading", "descriptor"});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004031 llvm::GlobalVariable *Desc = createGlobalStruct(
4032 CGM, getTgtBinaryDescriptorQTy(), /*IsConstant=*/true, Data, Descriptor);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004033
4034 // Emit code to register or unregister the descriptor at execution
4035 // startup or closing, respectively.
4036
Alexey Bataev03f270c2018-03-30 18:31:07 +00004037 llvm::Function *UnRegFn;
4038 {
4039 FunctionArgList Args;
4040 ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other);
4041 Args.push_back(&DummyPtr);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004042
Alexey Bataev03f270c2018-03-30 18:31:07 +00004043 CodeGenFunction CGF(CGM);
4044 // Disable debug info for global (de-)initializer because they are not part
4045 // of some particular construct.
4046 CGF.disableDebugInfo();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004047 const auto &FI =
4048 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
4049 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004050 std::string UnregName = getName({"omp_offloading", "descriptor_unreg"});
4051 UnRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, UnregName, FI);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004052 CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args);
4053 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
4054 Desc);
4055 CGF.FinishFunction();
4056 }
4057 llvm::Function *RegFn;
4058 {
4059 CodeGenFunction CGF(CGM);
4060 // Disable debug info for global (de-)initializer because they are not part
4061 // of some particular construct.
4062 CGF.disableDebugInfo();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004063 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
Alexey Bataev03f270c2018-03-30 18:31:07 +00004064 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Sergey Dmitrievbde9cf92018-08-03 20:19:28 +00004065
4066 // Encode offload target triples into the registration function name. It
4067 // will serve as a comdat key for the registration/unregistration code for
4068 // this particular combination of offloading targets.
4069 SmallVector<StringRef, 4U> RegFnNameParts(Devices.size() + 2U);
4070 RegFnNameParts[0] = "omp_offloading";
4071 RegFnNameParts[1] = "descriptor_reg";
4072 llvm::transform(Devices, std::next(RegFnNameParts.begin(), 2),
4073 [](const llvm::Triple &T) -> const std::string& {
4074 return T.getTriple();
4075 });
4076 llvm::sort(std::next(RegFnNameParts.begin(), 2), RegFnNameParts.end());
4077 std::string Descriptor = getName(RegFnNameParts);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004078 RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004079 CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList());
4080 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc);
4081 // Create a variable to drive the registration and unregistration of the
4082 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
4083 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(),
4084 SourceLocation(), nullptr, C.CharTy,
4085 ImplicitParamDecl::Other);
4086 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
4087 CGF.FinishFunction();
4088 }
George Rokos29d0f002017-05-27 03:03:13 +00004089 if (CGM.supportsCOMDAT()) {
4090 // It is sufficient to call registration function only once, so create a
4091 // COMDAT group for registration/unregistration functions and associated
4092 // data. That would reduce startup time and code size. Registration
4093 // function serves as a COMDAT group key.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004094 llvm::Comdat *ComdatKey = M.getOrInsertComdat(RegFn->getName());
George Rokos29d0f002017-05-27 03:03:13 +00004095 RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage);
4096 RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
4097 RegFn->setComdat(ComdatKey);
4098 UnRegFn->setComdat(ComdatKey);
4099 DeviceImages->setComdat(ComdatKey);
4100 Desc->setComdat(ComdatKey);
4101 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004102 return RegFn;
4103}
4104
Alexey Bataev03f270c2018-03-30 18:31:07 +00004105void CGOpenMPRuntime::createOffloadEntry(
4106 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4107 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004108 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004109 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004110 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004111
4112 // Create constant string with the name.
4113 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4114
Alexey Bataev18fa2322018-05-02 14:20:50 +00004115 std::string StringName = getName({"omp_offloading", "entry_name"});
4116 auto *Str = new llvm::GlobalVariable(
4117 M, StrPtrInit->getType(), /*isConstant=*/true,
4118 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004119 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004120
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004121 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4122 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4123 llvm::ConstantInt::get(CGM.SizeTy, Size),
4124 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4125 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004126 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004127 llvm::GlobalVariable *Entry = createGlobalStruct(
4128 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4129 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004130
4131 // The entry has to be created in the section the linker expects it to be.
Sergey Dmitriev4b343fd2019-09-27 20:00:51 +00004132 Entry->setSection("omp_offloading_entries");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004133}
4134
4135void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4136 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004137 // can easily figure out what to emit. The produced metadata looks like
4138 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004139 //
4140 // !omp_offload.info = !{!1, ...}
4141 //
4142 // Right now we only generate metadata for function that contain target
4143 // regions.
4144
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00004145 // If we do not have entries, we don't need to do anything.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004146 if (OffloadEntriesInfoManager.empty())
4147 return;
4148
4149 llvm::Module &M = CGM.getModule();
4150 llvm::LLVMContext &C = M.getContext();
Alexey Bataev03f270c2018-03-30 18:31:07 +00004151 SmallVector<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004152 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004153 llvm::SmallVector<StringRef, 16> ParentFunctions(
4154 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004155
Simon Pilgrim2c518802017-03-30 14:13:19 +00004156 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004157 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004158 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004159 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004160 };
4161
Alexey Bataev03f270c2018-03-30 18:31:07 +00004162 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4163
4164 // Create the offloading info metadata node.
4165 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004166
4167 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004168 auto &&TargetRegionMetadataEmitter =
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004169 [&C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004170 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4171 unsigned Line,
4172 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4173 // Generate metadata for target regions. Each entry of this metadata
4174 // contains:
4175 // - Entry 0 -> Kind of this type of metadata (0).
4176 // - Entry 1 -> Device ID of the file where the entry was identified.
4177 // - Entry 2 -> File ID of the file where the entry was identified.
4178 // - Entry 3 -> Mangled name of the function where the entry was
4179 // identified.
4180 // - Entry 4 -> Line in the file where the entry was identified.
4181 // - Entry 5 -> Order the entry was created.
4182 // The first element of the metadata node is the kind.
4183 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4184 GetMDInt(FileID), GetMDString(ParentName),
4185 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004186
Alexey Bataev03f270c2018-03-30 18:31:07 +00004187 // Save this entry in the right position of the ordered entries array.
4188 OrderedEntries[E.getOrder()] = &E;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004189 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004190
Alexey Bataev03f270c2018-03-30 18:31:07 +00004191 // Add metadata to the named metadata node.
4192 MD->addOperand(llvm::MDNode::get(C, Ops));
4193 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004194
4195 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4196 TargetRegionMetadataEmitter);
4197
Alexey Bataev03f270c2018-03-30 18:31:07 +00004198 // Create function that emits metadata for each device global variable entry;
4199 auto &&DeviceGlobalVarMetadataEmitter =
4200 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4201 MD](StringRef MangledName,
4202 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4203 &E) {
4204 // Generate metadata for global variables. Each entry of this metadata
4205 // contains:
4206 // - Entry 0 -> Kind of this type of metadata (1).
4207 // - Entry 1 -> Mangled name of the variable.
4208 // - Entry 2 -> Declare target kind.
4209 // - Entry 3 -> Order the entry was created.
4210 // The first element of the metadata node is the kind.
4211 llvm::Metadata *Ops[] = {
4212 GetMDInt(E.getKind()), GetMDString(MangledName),
4213 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4214
4215 // Save this entry in the right position of the ordered entries array.
4216 OrderedEntries[E.getOrder()] = &E;
4217
4218 // Add metadata to the named metadata node.
4219 MD->addOperand(llvm::MDNode::get(C, Ops));
4220 };
4221
4222 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4223 DeviceGlobalVarMetadataEmitter);
4224
4225 for (const auto *E : OrderedEntries) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004226 assert(E && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004227 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004228 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
4229 E)) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004230 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004231 // Do not blame the entry if the parent funtion is not emitted.
4232 StringRef FnName = ParentFunctions[CE->getOrder()];
4233 if (!CGM.GetGlobalValue(FnName))
4234 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004235 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4236 DiagnosticsEngine::Error,
Alexey Bataev7f01d202018-07-16 18:12:18 +00004237 "Offloading entry for target region is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004238 "address or the ID is invalid.");
4239 CGM.getDiags().Report(DiagID);
4240 continue;
4241 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004242 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004243 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
4244 } else if (const auto *CE =
4245 dyn_cast<OffloadEntriesInfoManagerTy::
4246 OffloadEntryInfoDeviceGlobalVar>(E)) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004247 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4248 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4249 CE->getFlags());
4250 switch (Flags) {
4251 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00004252 if (CGM.getLangOpts().OpenMPIsDevice &&
4253 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4254 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004255 if (!CE->getAddress()) {
4256 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4257 DiagnosticsEngine::Error,
4258 "Offloading entry for declare target variable is incorrect: the "
4259 "address is invalid.");
4260 CGM.getDiags().Report(DiagID);
4261 continue;
4262 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004263 // The vaiable has no definition - no need to add the entry.
4264 if (CE->getVarSize().isZero())
4265 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004266 break;
4267 }
4268 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4269 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4270 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4271 "Declaret target link address is set.");
4272 if (CGM.getLangOpts().OpenMPIsDevice)
4273 continue;
4274 if (!CE->getAddress()) {
4275 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4276 DiagnosticsEngine::Error,
4277 "Offloading entry for declare target variable is incorrect: the "
4278 "address is invalid.");
4279 CGM.getDiags().Report(DiagID);
4280 continue;
4281 }
4282 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004283 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004284 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004285 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004286 CE->getLinkage());
4287 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004288 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004289 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004290 }
4291}
4292
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004293/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004294/// metadata.
4295void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4296 // If we are in target mode, load the metadata from the host IR. This code has
4297 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4298
4299 if (!CGM.getLangOpts().OpenMPIsDevice)
4300 return;
4301
4302 if (CGM.getLangOpts().OMPHostIRFile.empty())
4303 return;
4304
4305 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004306 if (auto EC = Buf.getError()) {
4307 CGM.getDiags().Report(diag::err_cannot_open_file)
4308 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004309 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004310 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004311
4312 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004313 auto ME = expectedToErrorOrAndEmitErrors(
4314 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004315
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004316 if (auto EC = ME.getError()) {
4317 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4318 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4319 CGM.getDiags().Report(DiagID)
4320 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004321 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004322 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004323
4324 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4325 if (!MD)
4326 return;
4327
George Burgess IV00f70bd2018-03-01 05:43:23 +00004328 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004329 auto &&GetMDInt = [MN](unsigned Idx) {
4330 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004331 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4332 };
4333
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004334 auto &&GetMDString = [MN](unsigned Idx) {
4335 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004336 return V->getString();
4337 };
4338
Alexey Bataev03f270c2018-03-30 18:31:07 +00004339 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004340 default:
4341 llvm_unreachable("Unexpected metadata!");
4342 break;
4343 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004344 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004345 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004346 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4347 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4348 /*Order=*/GetMDInt(5));
4349 break;
4350 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4351 OffloadingEntryInfoDeviceGlobalVar:
4352 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4353 /*MangledName=*/GetMDString(1),
4354 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4355 /*Flags=*/GetMDInt(2)),
4356 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004357 break;
4358 }
4359 }
4360}
4361
Alexey Bataev62b63b12015-03-10 07:28:44 +00004362void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4363 if (!KmpRoutineEntryPtrTy) {
4364 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004365 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004366 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4367 FunctionProtoType::ExtProtoInfo EPI;
4368 KmpRoutineEntryPtrQTy = C.getPointerType(
4369 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4370 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4371 }
4372}
4373
Samuel Antaoee8fb302016-01-06 13:42:12 +00004374QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004375 // Make sure the type of the entry is already created. This is the type we
4376 // have to create:
4377 // struct __tgt_offload_entry{
4378 // void *addr; // Pointer to the offload entry info.
4379 // // (function or global)
4380 // char *name; // Name of the function or global.
4381 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004382 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4383 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004384 // };
4385 if (TgtOffloadEntryQTy.isNull()) {
4386 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004387 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004388 RD->startDefinition();
4389 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4390 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4391 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004392 addFieldToRecordDecl(
4393 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4394 addFieldToRecordDecl(
4395 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004396 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004397 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004398 TgtOffloadEntryQTy = C.getRecordType(RD);
4399 }
4400 return TgtOffloadEntryQTy;
4401}
4402
4403QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
4404 // These are the types we need to build:
4405 // struct __tgt_device_image{
4406 // void *ImageStart; // Pointer to the target code start.
4407 // void *ImageEnd; // Pointer to the target code end.
4408 // // We also add the host entries to the device image, as it may be useful
4409 // // for the target runtime to have access to that information.
4410 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
4411 // // the entries.
4412 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4413 // // entries (non inclusive).
4414 // };
4415 if (TgtDeviceImageQTy.isNull()) {
4416 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004417 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004418 RD->startDefinition();
4419 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4420 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4421 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4422 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4423 RD->completeDefinition();
4424 TgtDeviceImageQTy = C.getRecordType(RD);
4425 }
4426 return TgtDeviceImageQTy;
4427}
4428
4429QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
4430 // struct __tgt_bin_desc{
4431 // int32_t NumDevices; // Number of devices supported.
4432 // __tgt_device_image *DeviceImages; // Arrays of device images
4433 // // (one per device).
4434 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
4435 // // entries.
4436 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4437 // // entries (non inclusive).
4438 // };
4439 if (TgtBinaryDescriptorQTy.isNull()) {
4440 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004441 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004442 RD->startDefinition();
4443 addFieldToRecordDecl(
4444 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4445 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
4446 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4447 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4448 RD->completeDefinition();
4449 TgtBinaryDescriptorQTy = C.getRecordType(RD);
4450 }
4451 return TgtBinaryDescriptorQTy;
4452}
4453
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004454namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004455struct PrivateHelpersTy {
4456 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4457 const VarDecl *PrivateElemInit)
4458 : Original(Original), PrivateCopy(PrivateCopy),
4459 PrivateElemInit(PrivateElemInit) {}
4460 const VarDecl *Original;
4461 const VarDecl *PrivateCopy;
4462 const VarDecl *PrivateElemInit;
4463};
4464typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004465} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004466
Alexey Bataev9e034042015-05-05 04:05:12 +00004467static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004468createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004469 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004470 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004471 // Build struct .kmp_privates_t. {
4472 // /* private vars */
4473 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004474 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004475 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004476 for (const auto &Pair : Privates) {
4477 const VarDecl *VD = Pair.second.Original;
4478 QualType Type = VD->getType().getNonReferenceType();
4479 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004480 if (VD->hasAttrs()) {
4481 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4482 E(VD->getAttrs().end());
4483 I != E; ++I)
4484 FD->addAttr(*I);
4485 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004486 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004487 RD->completeDefinition();
4488 return RD;
4489 }
4490 return nullptr;
4491}
4492
Alexey Bataev9e034042015-05-05 04:05:12 +00004493static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004494createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4495 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004496 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004497 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004498 // Build struct kmp_task_t {
4499 // void * shareds;
4500 // kmp_routine_entry_t routine;
4501 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004502 // kmp_cmplrdata_t data1;
4503 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004504 // For taskloops additional fields:
4505 // kmp_uint64 lb;
4506 // kmp_uint64 ub;
4507 // kmp_int64 st;
4508 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004509 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004510 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004511 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004512 UD->startDefinition();
4513 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4514 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4515 UD->completeDefinition();
4516 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004517 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004518 RD->startDefinition();
4519 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4520 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4521 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004522 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4523 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004524 if (isOpenMPTaskLoopDirective(Kind)) {
4525 QualType KmpUInt64Ty =
4526 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4527 QualType KmpInt64Ty =
4528 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4529 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4530 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4531 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4532 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004533 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004534 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004535 RD->completeDefinition();
4536 return RD;
4537}
4538
4539static RecordDecl *
4540createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004541 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004542 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004543 // Build struct kmp_task_t_with_privates {
4544 // kmp_task_t task_data;
4545 // .kmp_privates_t. privates;
4546 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004547 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004548 RD->startDefinition();
4549 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004550 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004551 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004552 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004553 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004554}
4555
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004556/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004557/// argument.
4558/// \code
4559/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004560/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004561/// For taskloops:
4562/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004563/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004564/// return 0;
4565/// }
4566/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004567static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004568emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004569 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4570 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004571 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004572 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004573 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004574 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004575 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004576 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4577 ImplicitParamDecl::Other);
4578 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4579 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4580 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004581 Args.push_back(&GtidArg);
4582 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004583 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004584 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004585 llvm::FunctionType *TaskEntryTy =
4586 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004587 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4588 auto *TaskEntry = llvm::Function::Create(
4589 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004590 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004591 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004592 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004593 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4594 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004595
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004596 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004597 // tt,
4598 // For taskloops:
4599 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4600 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004601 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004602 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004603 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4604 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4605 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004606 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004607 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004608 LValue Base =
4609 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004610 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004611 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004612 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
4613 llvm::Value *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004614
4615 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004616 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4617 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004618 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004619 CGF.ConvertTypeForMem(SharedsPtrTy));
4620
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004621 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4622 llvm::Value *PrivatesParam;
4623 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004624 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004625 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00004626 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004627 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004628 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004629 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004630
Alexey Bataev7292c292016-04-25 12:22:29 +00004631 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4632 TaskPrivatesMap,
4633 CGF.Builder
4634 .CreatePointerBitCastOrAddrSpaceCast(
4635 TDBase.getAddress(), CGF.VoidPtrTy)
4636 .getPointer()};
4637 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4638 std::end(CommonArgs));
4639 if (isOpenMPTaskLoopDirective(Kind)) {
4640 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004641 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4642 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004643 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004644 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4645 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004646 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004647 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4648 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004649 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004650 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4651 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004652 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004653 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4654 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004655 CallArgs.push_back(LBParam);
4656 CallArgs.push_back(UBParam);
4657 CallArgs.push_back(StParam);
4658 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004659 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004660 }
4661 CallArgs.push_back(SharedsParam);
4662
Alexey Bataev3c595a62017-08-14 15:01:03 +00004663 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4664 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004665 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4666 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004667 CGF.FinishFunction();
4668 return TaskEntry;
4669}
4670
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004671static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4672 SourceLocation Loc,
4673 QualType KmpInt32Ty,
4674 QualType KmpTaskTWithPrivatesPtrQTy,
4675 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004676 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004677 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004678 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4679 ImplicitParamDecl::Other);
4680 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4681 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4682 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004683 Args.push_back(&GtidArg);
4684 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004685 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004686 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004687 llvm::FunctionType *DestructorFnTy =
4688 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004689 std::string Name =
4690 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004691 auto *DestructorFn =
4692 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004693 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004694 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004695 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004696 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004697 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004698 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004699 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004700
Alexey Bataev31300ed2016-02-04 11:27:03 +00004701 LValue Base = CGF.EmitLoadOfPointerLValue(
4702 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4703 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004704 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004705 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4706 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004707 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004708 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004709 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004710 if (QualType::DestructionKind DtorKind =
4711 Field->getType().isDestructedType()) {
4712 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004713 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
4714 }
4715 }
4716 CGF.FinishFunction();
4717 return DestructorFn;
4718}
4719
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004720/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004721/// firstprivate variables.
4722/// \code
4723/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4724/// **noalias priv1,..., <tyn> **noalias privn) {
4725/// *priv1 = &.privates.priv1;
4726/// ...;
4727/// *privn = &.privates.privn;
4728/// }
4729/// \endcode
4730static llvm::Value *
4731emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004732 ArrayRef<const Expr *> PrivateVars,
4733 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004734 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004735 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004736 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004737 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004738 FunctionArgList Args;
4739 ImplicitParamDecl TaskPrivatesArg(
4740 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004741 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4742 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004743 Args.push_back(&TaskPrivatesArg);
4744 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4745 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004746 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004747 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004748 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4749 C.getPointerType(C.getPointerType(E->getType()))
4750 .withConst()
4751 .withRestrict(),
4752 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004753 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004754 PrivateVarsPos[VD] = Counter;
4755 ++Counter;
4756 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004757 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004758 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004759 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4760 C.getPointerType(C.getPointerType(E->getType()))
4761 .withConst()
4762 .withRestrict(),
4763 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004764 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004765 PrivateVarsPos[VD] = Counter;
4766 ++Counter;
4767 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004768 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004769 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004770 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4771 C.getPointerType(C.getPointerType(E->getType()))
4772 .withConst()
4773 .withRestrict(),
4774 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004775 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004776 PrivateVarsPos[VD] = Counter;
4777 ++Counter;
4778 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004779 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004780 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004781 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004782 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004783 std::string Name =
4784 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004785 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004786 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4787 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004788 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004789 TaskPrivatesMapFnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00004790 if (CGM.getLangOpts().Optimize) {
4791 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4792 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4793 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4794 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004795 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004796 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004797 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004798
4799 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004800 LValue Base = CGF.EmitLoadOfPointerLValue(
4801 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4802 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004803 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004804 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004805 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4806 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4807 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4808 LValue RefLVal =
4809 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4810 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev31300ed2016-02-04 11:27:03 +00004811 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00004812 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004813 ++Counter;
4814 }
4815 CGF.FinishFunction();
4816 return TaskPrivatesMap;
4817}
4818
Alexey Bataevf93095a2016-05-05 08:46:22 +00004819/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004820static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004821 const OMPExecutableDirective &D,
4822 Address KmpTaskSharedsPtr, LValue TDBase,
4823 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4824 QualType SharedsTy, QualType SharedsPtrTy,
4825 const OMPTaskDataTy &Data,
4826 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004827 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004828 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4829 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004830 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4831 ? OMPD_taskloop
4832 : OMPD_task;
4833 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4834 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004835 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004836 bool IsTargetTask =
4837 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4838 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4839 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4840 // PointersArray and SizesArray. The original variables for these arrays are
4841 // not captured and we get their addresses explicitly.
4842 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004843 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004844 SrcBase = CGF.MakeAddrLValue(
4845 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4846 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4847 SharedsTy);
4848 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004849 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004850 for (const PrivateDataTy &Pair : Privates) {
4851 const VarDecl *VD = Pair.second.PrivateCopy;
4852 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004853 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4854 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004855 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004856 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4857 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004858 // Check if the variable is the target-based BasePointersArray,
4859 // PointersArray or SizesArray.
4860 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004861 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004862 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004863 if (IsTargetTask && !SharedField) {
4864 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4865 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4866 cast<CapturedDecl>(OriginalVD->getDeclContext())
4867 ->getNumParams() == 0 &&
4868 isa<TranslationUnitDecl>(
4869 cast<CapturedDecl>(OriginalVD->getDeclContext())
4870 ->getDeclContext()) &&
4871 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004872 SharedRefLValue =
4873 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4874 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004875 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4876 SharedRefLValue = CGF.MakeAddrLValue(
4877 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
4878 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4879 SharedRefLValue.getTBAAInfo());
4880 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004881 if (Type->isArrayType()) {
4882 // Initialize firstprivate array.
4883 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4884 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004885 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004886 } else {
4887 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004888 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004889 CGF.EmitOMPAggregateAssign(
4890 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
4891 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4892 Address SrcElement) {
4893 // Clean up any temporaries needed by the initialization.
4894 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4895 InitScope.addPrivate(
4896 Elem, [SrcElement]() -> Address { return SrcElement; });
4897 (void)InitScope.Privatize();
4898 // Emit initialization for single element.
4899 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4900 CGF, &CapturesInfo);
4901 CGF.EmitAnyExprToMem(Init, DestElement,
4902 Init->getType().getQualifiers(),
4903 /*IsInitializer=*/false);
4904 });
4905 }
4906 } else {
4907 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4908 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
4909 return SharedRefLValue.getAddress();
4910 });
4911 (void)InitScope.Privatize();
4912 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4913 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4914 /*capturedByInit=*/false);
4915 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004916 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004917 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004918 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004919 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004920 ++FI;
4921 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004922}
4923
4924/// Check if duplication function is required for taskloops.
4925static bool checkInitIsRequired(CodeGenFunction &CGF,
4926 ArrayRef<PrivateDataTy> Privates) {
4927 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004928 for (const PrivateDataTy &Pair : Privates) {
4929 const VarDecl *VD = Pair.second.PrivateCopy;
4930 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004931 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4932 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004933 if (InitRequired)
4934 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004935 }
4936 return InitRequired;
4937}
4938
4939
4940/// Emit task_dup function (for initialization of
4941/// private/firstprivate/lastprivate vars and last_iter flag)
4942/// \code
4943/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4944/// lastpriv) {
4945/// // setup lastprivate flag
4946/// task_dst->last = lastpriv;
4947/// // could be constructor calls here...
4948/// }
4949/// \endcode
4950static llvm::Value *
4951emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4952 const OMPExecutableDirective &D,
4953 QualType KmpTaskTWithPrivatesPtrQTy,
4954 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4955 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4956 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4957 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004958 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004959 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004960 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4961 KmpTaskTWithPrivatesPtrQTy,
4962 ImplicitParamDecl::Other);
4963 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4964 KmpTaskTWithPrivatesPtrQTy,
4965 ImplicitParamDecl::Other);
4966 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4967 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004968 Args.push_back(&DstArg);
4969 Args.push_back(&SrcArg);
4970 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004971 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004972 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004973 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004974 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4975 auto *TaskDup = llvm::Function::Create(
4976 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004977 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004978 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004979 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004980 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4981 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004982
4983 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4984 CGF.GetAddrOfLocalVar(&DstArg),
4985 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4986 // task_dst->liter = lastpriv;
4987 if (WithLastIter) {
4988 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4989 LValue Base = CGF.EmitLValueForField(
4990 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4991 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4992 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4993 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4994 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4995 }
4996
4997 // Emit initial values for private copies (if any).
4998 assert(!Privates.empty());
4999 Address KmpTaskSharedsPtr = Address::invalid();
5000 if (!Data.FirstprivateVars.empty()) {
5001 LValue TDBase = CGF.EmitLoadOfPointerLValue(
5002 CGF.GetAddrOfLocalVar(&SrcArg),
5003 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
5004 LValue Base = CGF.EmitLValueForField(
5005 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
5006 KmpTaskSharedsPtr = Address(
5007 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
5008 Base, *std::next(KmpTaskTQTyRD->field_begin(),
5009 KmpTaskTShareds)),
5010 Loc),
5011 CGF.getNaturalTypeAlignment(SharedsTy));
5012 }
Alexey Bataev8a831592016-05-10 10:36:51 +00005013 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
5014 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005015 CGF.FinishFunction();
5016 return TaskDup;
5017}
5018
Alexey Bataev8a831592016-05-10 10:36:51 +00005019/// Checks if destructor function is required to be generated.
5020/// \return true if cleanups are required, false otherwise.
5021static bool
5022checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
5023 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005024 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
5025 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
5026 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005027 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
5028 if (NeedsCleanup)
5029 break;
5030 }
5031 return NeedsCleanup;
5032}
5033
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005034CGOpenMPRuntime::TaskResultTy
5035CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
5036 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005037 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005038 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005039 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00005040 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005041 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005042 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005043 for (const Expr *E : Data.PrivateVars) {
5044 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005045 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00005046 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00005047 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005048 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005049 ++I;
5050 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005051 I = Data.FirstprivateCopies.begin();
5052 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005053 for (const Expr *E : Data.FirstprivateVars) {
5054 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005055 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00005056 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00005057 PrivateHelpersTy(
5058 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005059 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00005060 ++I;
5061 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00005062 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00005063 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005064 for (const Expr *E : Data.LastprivateVars) {
5065 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005066 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00005067 C.getDeclAlign(VD),
5068 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005069 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00005070 ++I;
5071 }
Fangrui Song899d1392019-04-24 14:43:05 +00005072 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
5073 return L.first > R.first;
5074 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005075 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005076 // Build type kmp_routine_entry_t (if not built yet).
5077 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005078 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005079 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5080 if (SavedKmpTaskloopTQTy.isNull()) {
5081 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5082 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5083 }
5084 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00005085 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005086 assert((D.getDirectiveKind() == OMPD_task ||
5087 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
5088 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
5089 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005090 if (SavedKmpTaskTQTy.isNull()) {
5091 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5092 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5093 }
5094 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005095 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005096 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005097 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005098 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005099 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005100 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005101 QualType KmpTaskTWithPrivatesPtrQTy =
5102 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005103 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5104 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5105 KmpTaskTWithPrivatesTy->getPointerTo();
5106 llvm::Value *KmpTaskTWithPrivatesTySize =
5107 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005108 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5109
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005110 // Emit initial values for private copies (if any).
5111 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005112 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00005113 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005114 if (!Privates.empty()) {
5115 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005116 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5117 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5118 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005119 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5120 TaskPrivatesMap, TaskPrivatesMapTy);
5121 } else {
5122 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5123 cast<llvm::PointerType>(TaskPrivatesMapTy));
5124 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005125 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5126 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005127 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005128 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5129 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5130 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005131
5132 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5133 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5134 // kmp_routine_entry_t *task_entry);
5135 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005136 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005137 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005138 enum {
5139 TiedFlag = 0x1,
5140 FinalFlag = 0x2,
5141 DestructorsFlag = 0x8,
5142 PriorityFlag = 0x20
5143 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005144 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005145 bool NeedsCleanup = false;
5146 if (!Privates.empty()) {
5147 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5148 if (NeedsCleanup)
5149 Flags = Flags | DestructorsFlag;
5150 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005151 if (Data.Priority.getInt())
5152 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005153 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005154 Data.Final.getPointer()
5155 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005156 CGF.Builder.getInt32(FinalFlag),
5157 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005158 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005159 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005160 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005161 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5162 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5163 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5164 TaskEntry, KmpRoutineEntryPtrTy)};
5165 llvm::Value *NewTask;
5166 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5167 // Check if we have any device clause associated with the directive.
5168 const Expr *Device = nullptr;
5169 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5170 Device = C->getDevice();
5171 // Emit device ID if any otherwise use default value.
5172 llvm::Value *DeviceID;
5173 if (Device)
5174 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5175 CGF.Int64Ty, /*isSigned=*/true);
5176 else
5177 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5178 AllocArgs.push_back(DeviceID);
5179 NewTask = CGF.EmitRuntimeCall(
5180 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5181 } else {
5182 NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005183 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005184 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005185 llvm::Value *NewTaskNewTaskTTy =
5186 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5187 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005188 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5189 KmpTaskTWithPrivatesQTy);
5190 LValue TDBase =
5191 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005192 // Fill the data in the resulting kmp_task_t record.
5193 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005194 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005195 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005196 KmpTaskSharedsPtr =
5197 Address(CGF.EmitLoadOfScalar(
5198 CGF.EmitLValueForField(
5199 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5200 KmpTaskTShareds)),
5201 Loc),
5202 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005203 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5204 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005205 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005206 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005207 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005208 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005209 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005210 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5211 SharedsTy, SharedsPtrTy, Data, Privates,
5212 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005213 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5214 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5215 Result.TaskDupFn = emitTaskDupFunction(
5216 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5217 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5218 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005219 }
5220 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005221 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5222 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005223 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005224 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005225 const RecordDecl *KmpCmplrdataUD =
5226 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005227 if (NeedsCleanup) {
5228 llvm::Value *DestructorFn = emitDestructorsFunction(
5229 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5230 KmpTaskTWithPrivatesQTy);
5231 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5232 LValue DestructorsLV = CGF.EmitLValueForField(
5233 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5234 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5235 DestructorFn, KmpRoutineEntryPtrTy),
5236 DestructorsLV);
5237 }
5238 // Set priority.
5239 if (Data.Priority.getInt()) {
5240 LValue Data2LV = CGF.EmitLValueForField(
5241 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5242 LValue PriorityLV = CGF.EmitLValueForField(
5243 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5244 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5245 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005246 Result.NewTask = NewTask;
5247 Result.TaskEntry = TaskEntry;
5248 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5249 Result.TDBase = TDBase;
5250 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5251 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005252}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005253
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005254void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5255 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005256 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005257 QualType SharedsTy, Address Shareds,
5258 const Expr *IfCond,
5259 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005260 if (!CGF.HaveInsertPoint())
5261 return;
5262
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005263 TaskResultTy Result =
5264 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5265 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005266 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005267 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5268 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005269 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5270 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005271 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005272 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005273 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005274 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005275 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005276 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005277 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5278 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005279 QualType FlagsTy =
5280 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005281 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5282 if (KmpDependInfoTy.isNull()) {
5283 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5284 KmpDependInfoRD->startDefinition();
5285 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5286 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5287 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5288 KmpDependInfoRD->completeDefinition();
5289 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005290 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005291 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005292 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005293 // Define type kmp_depend_info[<Dependences.size()>];
5294 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005295 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005296 ArrayType::Normal, /*IndexTypeQuals=*/0);
5297 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005298 DependenciesArray =
5299 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005300 for (unsigned I = 0; I < NumDependencies; ++I) {
5301 const Expr *E = Data.Dependences[I].second;
5302 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005303 llvm::Value *Size;
5304 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005305 if (const auto *ASE =
5306 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005307 LValue UpAddrLVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005308 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005309 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00005310 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005311 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00005312 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005313 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5314 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005315 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005316 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005317 }
5318 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005319 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005320 KmpDependInfoTy);
5321 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005322 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005323 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005324 CGF.EmitStoreOfScalar(
5325 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
5326 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005327 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005328 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005329 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5330 CGF.EmitStoreOfScalar(Size, LenLVal);
5331 // deps[i].flags = <Dependences[i].first>;
5332 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005333 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005334 case OMPC_DEPEND_in:
5335 DepKind = DepIn;
5336 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005337 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005338 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005339 case OMPC_DEPEND_inout:
5340 DepKind = DepInOut;
5341 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005342 case OMPC_DEPEND_mutexinoutset:
5343 DepKind = DepMutexInOutSet;
5344 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005345 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005346 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005347 case OMPC_DEPEND_unknown:
5348 llvm_unreachable("Unknown task dependence type");
5349 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005350 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005351 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5352 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5353 FlagsLVal);
5354 }
John McCall7f416cc2015-09-08 08:05:57 +00005355 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005356 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005357 }
5358
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005359 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005360 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005361 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5362 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5363 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5364 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005365 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5366 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005367 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5368 llvm::Value *DepTaskArgs[7];
5369 if (NumDependencies) {
5370 DepTaskArgs[0] = UpLoc;
5371 DepTaskArgs[1] = ThreadID;
5372 DepTaskArgs[2] = NewTask;
5373 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5374 DepTaskArgs[4] = DependenciesArray.getPointer();
5375 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5376 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5377 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005378 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5379 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005380 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005381 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005382 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005383 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005384 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5385 }
John McCall7f416cc2015-09-08 08:05:57 +00005386 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005387 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005388 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005389 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005390 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005391 TaskArgs);
5392 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005393 // Check if parent region is untied and build return for untied task;
5394 if (auto *Region =
5395 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5396 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005397 };
John McCall7f416cc2015-09-08 08:05:57 +00005398
5399 llvm::Value *DepWaitTaskArgs[6];
5400 if (NumDependencies) {
5401 DepWaitTaskArgs[0] = UpLoc;
5402 DepWaitTaskArgs[1] = ThreadID;
5403 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5404 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5405 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5406 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5407 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005408 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005409 NumDependencies, &DepWaitTaskArgs,
5410 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005411 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005412 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5413 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5414 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5415 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5416 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005417 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005418 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005419 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005420 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005421 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5422 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005423 Action.Enter(CGF);
5424 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005425 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005426 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005427 };
5428
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005429 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5430 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005431 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5432 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005433 RegionCodeGenTy RCG(CodeGen);
5434 CommonActionTy Action(
5435 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5436 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5437 RCG.setAction(Action);
5438 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005439 };
John McCall7f416cc2015-09-08 08:05:57 +00005440
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005441 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00005442 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005443 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005444 RegionCodeGenTy ThenRCG(ThenCodeGen);
5445 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005446 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005447}
5448
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005449void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5450 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005451 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005452 QualType SharedsTy, Address Shareds,
5453 const Expr *IfCond,
5454 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005455 if (!CGF.HaveInsertPoint())
5456 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005457 TaskResultTy Result =
5458 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005459 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005460 // libcall.
5461 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5462 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5463 // sched, kmp_uint64 grainsize, void *task_dup);
5464 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5465 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5466 llvm::Value *IfVal;
5467 if (IfCond) {
5468 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5469 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005470 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005471 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005472 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005473
5474 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005475 Result.TDBase,
5476 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005477 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005478 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5479 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
5480 /*IsInitializer=*/true);
5481 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005482 Result.TDBase,
5483 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005484 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005485 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5486 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
5487 /*IsInitializer=*/true);
5488 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005489 Result.TDBase,
5490 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005491 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005492 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5493 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
5494 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005495 // Store reductions address.
5496 LValue RedLVal = CGF.EmitLValueForField(
5497 Result.TDBase,
5498 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005499 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005500 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005501 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005502 CGF.EmitNullInitialization(RedLVal.getAddress(),
5503 CGF.getContext().VoidPtrTy);
5504 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005505 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005506 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005507 UpLoc,
5508 ThreadID,
5509 Result.NewTask,
5510 IfVal,
5511 LBLVal.getPointer(),
5512 UBLVal.getPointer(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005513 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005514 llvm::ConstantInt::getSigned(
5515 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005516 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005517 CGF.IntTy, Data.Schedule.getPointer()
5518 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005519 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005520 Data.Schedule.getPointer()
5521 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005522 /*isSigned=*/false)
5523 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005524 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5525 Result.TaskDupFn, CGF.VoidPtrTy)
5526 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005527 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5528}
5529
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005530/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005531/// array sections) LHS op = RHS.
5532/// \param Type Type of array.
5533/// \param LHSVar Variable on the left side of the reduction operation
5534/// (references element of array in original variable).
5535/// \param RHSVar Variable on the right side of the reduction operation
5536/// (references element of array in original variable).
5537/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5538/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005539static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005540 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5541 const VarDecl *RHSVar,
5542 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5543 const Expr *, const Expr *)> &RedOpGen,
5544 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5545 const Expr *UpExpr = nullptr) {
5546 // Perform element-by-element initialization.
5547 QualType ElementTy;
5548 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5549 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5550
5551 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005552 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5553 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005554
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005555 llvm::Value *RHSBegin = RHSAddr.getPointer();
5556 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005557 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005558 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005559 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005560 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5561 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5562 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005563 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5564 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5565
5566 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005567 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005568 CGF.EmitBlock(BodyBB);
5569
5570 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5571
5572 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5573 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5574 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5575 Address RHSElementCurrent =
5576 Address(RHSElementPHI,
5577 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5578
5579 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5580 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5581 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5582 Address LHSElementCurrent =
5583 Address(LHSElementPHI,
5584 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5585
5586 // Emit copy.
5587 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005588 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5589 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005590 Scope.Privatize();
5591 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5592 Scope.ForceCleanup();
5593
5594 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005595 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005596 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005597 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005598 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5599 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005600 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005601 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5602 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5603 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5604 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5605
5606 // Done.
5607 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5608}
5609
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005610/// Emit reduction combiner. If the combiner is a simple expression emit it as
5611/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5612/// UDR combiner function.
5613static void emitReductionCombiner(CodeGenFunction &CGF,
5614 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005615 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5616 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5617 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005618 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005619 if (const auto *DRD =
5620 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005621 std::pair<llvm::Function *, llvm::Function *> Reduction =
5622 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5623 RValue Func = RValue::get(Reduction.first);
5624 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5625 CGF.EmitIgnoredExpr(ReductionOp);
5626 return;
5627 }
5628 CGF.EmitIgnoredExpr(ReductionOp);
5629}
5630
James Y Knight9871db02019-02-05 16:42:33 +00005631llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005632 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5633 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5634 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005635 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005636
5637 // void reduction_func(void *LHSArg, void *RHSArg);
5638 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005639 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5640 ImplicitParamDecl::Other);
5641 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5642 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005643 Args.push_back(&LHSArg);
5644 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005645 const auto &CGFI =
5646 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005647 std::string Name = getName({"omp", "reduction", "reduction_func"});
5648 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5649 llvm::GlobalValue::InternalLinkage, Name,
5650 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005651 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005652 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005653 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005654 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005655
5656 // Dst = (void*[n])(LHSArg);
5657 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005658 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5659 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5660 ArgsType), CGF.getPointerAlign());
5661 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5662 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5663 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005664
5665 // ...
5666 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5667 // ...
5668 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005669 auto IPriv = Privates.begin();
5670 unsigned Idx = 0;
5671 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005672 const auto *RHSVar =
5673 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5674 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005675 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005676 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005677 const auto *LHSVar =
5678 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5679 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005680 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005681 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005682 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005683 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005684 // Get array size and emit VLA type.
5685 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005686 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005687 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005688 const VariableArrayType *VLA =
5689 CGF.getContext().getAsVariableArrayType(PrivTy);
5690 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005691 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005692 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005693 CGF.EmitVariablyModifiedType(PrivTy);
5694 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005695 }
5696 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005697 IPriv = Privates.begin();
5698 auto ILHS = LHSExprs.begin();
5699 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005700 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005701 if ((*IPriv)->getType()->isArrayType()) {
5702 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005703 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5704 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005705 EmitOMPAggregateReduction(
5706 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5707 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5708 emitReductionCombiner(CGF, E);
5709 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005710 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005711 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005712 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005713 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005714 ++IPriv;
5715 ++ILHS;
5716 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005717 }
5718 Scope.ForceCleanup();
5719 CGF.FinishFunction();
5720 return Fn;
5721}
5722
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005723void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5724 const Expr *ReductionOp,
5725 const Expr *PrivateRef,
5726 const DeclRefExpr *LHS,
5727 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005728 if (PrivateRef->getType()->isArrayType()) {
5729 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005730 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5731 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005732 EmitOMPAggregateReduction(
5733 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5734 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5735 emitReductionCombiner(CGF, ReductionOp);
5736 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005737 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005738 // Emit reduction for array subscript or single variable.
5739 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005740 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005741}
5742
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005743void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005744 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005745 ArrayRef<const Expr *> LHSExprs,
5746 ArrayRef<const Expr *> RHSExprs,
5747 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005748 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005749 if (!CGF.HaveInsertPoint())
5750 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005751
5752 bool WithNowait = Options.WithNowait;
5753 bool SimpleReduction = Options.SimpleReduction;
5754
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005755 // Next code should be emitted for reduction:
5756 //
5757 // static kmp_critical_name lock = { 0 };
5758 //
5759 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5760 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5761 // ...
5762 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5763 // *(Type<n>-1*)rhs[<n>-1]);
5764 // }
5765 //
5766 // ...
5767 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5768 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5769 // RedList, reduce_func, &<lock>)) {
5770 // case 1:
5771 // ...
5772 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5773 // ...
5774 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5775 // break;
5776 // case 2:
5777 // ...
5778 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5779 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005780 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005781 // break;
5782 // default:;
5783 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005784 //
5785 // if SimpleReduction is true, only the next code is generated:
5786 // ...
5787 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5788 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005789
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005790 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005791
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005792 if (SimpleReduction) {
5793 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005794 auto IPriv = Privates.begin();
5795 auto ILHS = LHSExprs.begin();
5796 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005797 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005798 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5799 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005800 ++IPriv;
5801 ++ILHS;
5802 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005803 }
5804 return;
5805 }
5806
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005807 // 1. Build a list of reduction variables.
5808 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005809 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005810 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005811 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005812 // Reserve place for array size.
5813 ++Size;
5814 }
5815 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005816 QualType ReductionArrayTy =
5817 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
5818 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005819 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005820 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005821 auto IPriv = Privates.begin();
5822 unsigned Idx = 0;
5823 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005824 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005825 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005826 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00005827 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
5828 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005829 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005830 // Store array size.
5831 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005832 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005833 llvm::Value *Size = CGF.Builder.CreateIntCast(
5834 CGF.getVLASize(
5835 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005836 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005837 CGF.SizeTy, /*isSigned=*/false);
5838 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5839 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005840 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005841 }
5842
5843 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005844 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005845 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5846 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005847
5848 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005849 std::string Name = getName({"reduction"});
5850 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005851
5852 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5853 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005854 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5855 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5856 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5857 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005858 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005859 llvm::Value *Args[] = {
5860 IdentTLoc, // ident_t *<loc>
5861 ThreadId, // i32 <gtid>
5862 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5863 ReductionArrayTySize, // size_type sizeof(RedList)
5864 RL, // void *RedList
5865 ReductionFn, // void (*) (void *, void *) <reduce_func>
5866 Lock // kmp_critical_name *&<lock>
5867 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005868 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005869 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5870 : OMPRTL__kmpc_reduce),
5871 Args);
5872
5873 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005874 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5875 llvm::SwitchInst *SwInst =
5876 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005877
5878 // 6. Build case 1:
5879 // ...
5880 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5881 // ...
5882 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5883 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005884 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005885 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5886 CGF.EmitBlock(Case1BB);
5887
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005888 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5889 llvm::Value *EndArgs[] = {
5890 IdentTLoc, // ident_t *<loc>
5891 ThreadId, // i32 <gtid>
5892 Lock // kmp_critical_name *&<lock>
5893 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005894 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5895 CodeGenFunction &CGF, PrePostActionTy &Action) {
5896 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005897 auto IPriv = Privates.begin();
5898 auto ILHS = LHSExprs.begin();
5899 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005900 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005901 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5902 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005903 ++IPriv;
5904 ++ILHS;
5905 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005906 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005907 };
5908 RegionCodeGenTy RCG(CodeGen);
5909 CommonActionTy Action(
5910 nullptr, llvm::None,
5911 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5912 : OMPRTL__kmpc_end_reduce),
5913 EndArgs);
5914 RCG.setAction(Action);
5915 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005916
5917 CGF.EmitBranch(DefaultBB);
5918
5919 // 7. Build case 2:
5920 // ...
5921 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5922 // ...
5923 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005924 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005925 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5926 CGF.EmitBlock(Case2BB);
5927
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005928 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5929 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005930 auto ILHS = LHSExprs.begin();
5931 auto IRHS = RHSExprs.begin();
5932 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005933 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005934 const Expr *XExpr = nullptr;
5935 const Expr *EExpr = nullptr;
5936 const Expr *UpExpr = nullptr;
5937 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005938 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005939 if (BO->getOpcode() == BO_Assign) {
5940 XExpr = BO->getLHS();
5941 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005942 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005943 }
5944 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005945 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005946 if (RHSExpr) {
5947 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005948 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005949 RHSExpr->IgnoreParenImpCasts())) {
5950 // If this is a conditional operator, analyze its condition for
5951 // min/max reduction operator.
5952 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005953 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005954 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005955 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5956 EExpr = BORHS->getRHS();
5957 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005958 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005959 }
5960 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005961 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005962 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005963 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5964 const Expr *EExpr, const Expr *UpExpr) {
5965 LValue X = CGF.EmitLValue(XExpr);
5966 RValue E;
5967 if (EExpr)
5968 E = CGF.EmitAnyExpr(EExpr);
5969 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005970 X, E, BO, /*IsXLHSInRHSPart=*/true,
5971 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005972 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005973 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5974 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005975 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005976 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5977 CGF.emitOMPSimpleStore(
5978 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5979 VD->getType().getNonReferenceType(), Loc);
5980 return LHSTemp;
5981 });
5982 (void)PrivateScope.Privatize();
5983 return CGF.EmitAnyExpr(UpExpr);
5984 });
5985 };
5986 if ((*IPriv)->getType()->isArrayType()) {
5987 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005988 const auto *RHSVar =
5989 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005990 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5991 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005992 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005993 // Emit atomic reduction for array subscript or single variable.
5994 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005995 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005996 } else {
5997 // Emit as a critical region.
5998 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005999 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006000 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00006001 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006002 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00006003 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006004 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
6005 Action.Enter(CGF);
6006 emitReductionCombiner(CGF, E);
6007 },
6008 Loc);
6009 };
6010 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006011 const auto *LHSVar =
6012 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
6013 const auto *RHSVar =
6014 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006015 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
6016 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006017 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006018 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006019 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006020 }
Richard Trieucc3949d2016-02-18 22:34:54 +00006021 ++ILHS;
6022 ++IRHS;
6023 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00006024 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006025 };
6026 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
6027 if (!WithNowait) {
6028 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
6029 llvm::Value *EndArgs[] = {
6030 IdentTLoc, // ident_t *<loc>
6031 ThreadId, // i32 <gtid>
6032 Lock // kmp_critical_name *&<lock>
6033 };
6034 CommonActionTy Action(nullptr, llvm::None,
6035 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
6036 EndArgs);
6037 AtomicRCG.setAction(Action);
6038 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006039 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006040 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006041 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00006042
6043 CGF.EmitBranch(DefaultBB);
6044 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
6045}
6046
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006047/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00006048/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
6049static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
6050 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006051 SmallString<256> Buffer;
6052 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00006053 const clang::DeclRefExpr *DE;
6054 const VarDecl *D = ::getBaseDecl(Ref, DE);
6055 if (!D)
6056 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
6057 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00006058 std::string Name = CGM.getOpenMPRuntime().getName(
6059 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
6060 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006061 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006062 return Out.str();
6063}
6064
6065/// Emits reduction initializer function:
6066/// \code
6067/// void @.red_init(void* %arg) {
6068/// %0 = bitcast void* %arg to <type>*
6069/// store <type> <init>, <type>* %0
6070/// ret void
6071/// }
6072/// \endcode
6073static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6074 SourceLocation Loc,
6075 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006076 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006077 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006078 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6079 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006080 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006081 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006082 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006083 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006084 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006085 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006086 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006087 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006088 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006089 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006090 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006091 Address PrivateAddr = CGF.EmitLoadOfPointer(
6092 CGF.GetAddrOfLocalVar(&Param),
6093 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6094 llvm::Value *Size = nullptr;
6095 // If the size of the reduction item is non-constant, load it from global
6096 // threadprivate variable.
6097 if (RCG.getSizes(N).second) {
6098 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6099 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006100 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006101 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6102 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006103 }
6104 RCG.emitAggregateType(CGF, N, Size);
6105 LValue SharedLVal;
6106 // If initializer uses initializer from declare reduction construct, emit a
6107 // pointer to the address of the original reduction item (reuired by reduction
6108 // initializer)
6109 if (RCG.usesReductionInitializer(N)) {
6110 Address SharedAddr =
6111 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6112 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006113 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00006114 SharedAddr = CGF.EmitLoadOfPointer(
6115 SharedAddr,
6116 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006117 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6118 } else {
6119 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6120 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6121 CGM.getContext().VoidPtrTy);
6122 }
6123 // Emit the initializer:
6124 // %0 = bitcast void* %arg to <type>*
6125 // store <type> <init>, <type>* %0
6126 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6127 [](CodeGenFunction &) { return false; });
6128 CGF.FinishFunction();
6129 return Fn;
6130}
6131
6132/// Emits reduction combiner function:
6133/// \code
6134/// void @.red_comb(void* %arg0, void* %arg1) {
6135/// %lhs = bitcast void* %arg0 to <type>*
6136/// %rhs = bitcast void* %arg1 to <type>*
6137/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6138/// store <type> %2, <type>* %lhs
6139/// ret void
6140/// }
6141/// \endcode
6142static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6143 SourceLocation Loc,
6144 ReductionCodeGen &RCG, unsigned N,
6145 const Expr *ReductionOp,
6146 const Expr *LHS, const Expr *RHS,
6147 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006148 ASTContext &C = CGM.getContext();
6149 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6150 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006151 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006152 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6153 C.VoidPtrTy, ImplicitParamDecl::Other);
6154 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6155 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006156 Args.emplace_back(&ParamInOut);
6157 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006158 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006159 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006160 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006161 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006162 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006163 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006164 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006165 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006166 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006167 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006168 llvm::Value *Size = nullptr;
6169 // If the size of the reduction item is non-constant, load it from global
6170 // threadprivate variable.
6171 if (RCG.getSizes(N).second) {
6172 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6173 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006174 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006175 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6176 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006177 }
6178 RCG.emitAggregateType(CGF, N, Size);
6179 // Remap lhs and rhs variables to the addresses of the function arguments.
6180 // %lhs = bitcast void* %arg0 to <type>*
6181 // %rhs = bitcast void* %arg1 to <type>*
6182 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006183 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006184 // Pull out the pointer to the variable.
6185 Address PtrAddr = CGF.EmitLoadOfPointer(
6186 CGF.GetAddrOfLocalVar(&ParamInOut),
6187 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6188 return CGF.Builder.CreateElementBitCast(
6189 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6190 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006191 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006192 // Pull out the pointer to the variable.
6193 Address PtrAddr = CGF.EmitLoadOfPointer(
6194 CGF.GetAddrOfLocalVar(&ParamIn),
6195 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6196 return CGF.Builder.CreateElementBitCast(
6197 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6198 });
6199 PrivateScope.Privatize();
6200 // Emit the combiner body:
6201 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6202 // store <type> %2, <type>* %lhs
6203 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6204 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6205 cast<DeclRefExpr>(RHS));
6206 CGF.FinishFunction();
6207 return Fn;
6208}
6209
6210/// Emits reduction finalizer function:
6211/// \code
6212/// void @.red_fini(void* %arg) {
6213/// %0 = bitcast void* %arg to <type>*
6214/// <destroy>(<type>* %0)
6215/// ret void
6216/// }
6217/// \endcode
6218static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6219 SourceLocation Loc,
6220 ReductionCodeGen &RCG, unsigned N) {
6221 if (!RCG.needCleanups(N))
6222 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006223 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006224 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006225 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6226 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006227 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006228 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006229 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006230 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006231 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006232 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006233 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006234 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006235 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006236 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006237 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006238 Address PrivateAddr = CGF.EmitLoadOfPointer(
6239 CGF.GetAddrOfLocalVar(&Param),
6240 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6241 llvm::Value *Size = nullptr;
6242 // If the size of the reduction item is non-constant, load it from global
6243 // threadprivate variable.
6244 if (RCG.getSizes(N).second) {
6245 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6246 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006247 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006248 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6249 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006250 }
6251 RCG.emitAggregateType(CGF, N, Size);
6252 // Emit the finalizer body:
6253 // <destroy>(<type>* %0)
6254 RCG.emitCleanups(CGF, N, PrivateAddr);
6255 CGF.FinishFunction();
6256 return Fn;
6257}
6258
6259llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6260 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6261 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6262 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6263 return nullptr;
6264
6265 // Build typedef struct:
6266 // kmp_task_red_input {
6267 // void *reduce_shar; // shared reduction item
6268 // size_t reduce_size; // size of data item
6269 // void *reduce_init; // data initialization routine
6270 // void *reduce_fini; // data finalization routine
6271 // void *reduce_comb; // data combiner routine
6272 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6273 // } kmp_task_red_input_t;
6274 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006275 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006276 RD->startDefinition();
6277 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6278 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6279 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6280 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6281 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6282 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6283 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6284 RD->completeDefinition();
6285 QualType RDType = C.getRecordType(RD);
6286 unsigned Size = Data.ReductionVars.size();
6287 llvm::APInt ArraySize(/*numBits=*/64, Size);
6288 QualType ArrayRDType = C.getConstantArrayType(
6289 RDType, ArraySize, ArrayType::Normal, /*IndexTypeQuals=*/0);
6290 // kmp_task_red_input_t .rd_input.[Size];
6291 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6292 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6293 Data.ReductionOps);
6294 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6295 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6296 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6297 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6298 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6299 TaskRedInput.getPointer(), Idxs,
6300 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6301 ".rd_input.gep.");
6302 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6303 // ElemLVal.reduce_shar = &Shareds[Cnt];
6304 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6305 RCG.emitSharedLValue(CGF, Cnt);
6306 llvm::Value *CastedShared =
6307 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer());
6308 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6309 RCG.emitAggregateType(CGF, Cnt);
6310 llvm::Value *SizeValInChars;
6311 llvm::Value *SizeVal;
6312 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6313 // We use delayed creation/initialization for VLAs, array sections and
6314 // custom reduction initializations. It is required because runtime does not
6315 // provide the way to pass the sizes of VLAs/array sections to
6316 // initializer/combiner/finalizer functions and does not pass the pointer to
6317 // original reduction item to the initializer. Instead threadprivate global
6318 // variables are used to store these values and use them in the functions.
6319 bool DelayedCreation = !!SizeVal;
6320 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6321 /*isSigned=*/false);
6322 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6323 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6324 // ElemLVal.reduce_init = init;
6325 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6326 llvm::Value *InitAddr =
6327 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6328 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6329 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6330 // ElemLVal.reduce_fini = fini;
6331 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6332 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6333 llvm::Value *FiniAddr = Fini
6334 ? CGF.EmitCastToVoidPtr(Fini)
6335 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6336 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6337 // ElemLVal.reduce_comb = comb;
6338 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6339 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6340 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6341 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6342 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6343 // ElemLVal.flags = 0;
6344 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6345 if (DelayedCreation) {
6346 CGF.EmitStoreOfScalar(
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006347 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006348 FlagsLVal);
6349 } else
6350 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType());
6351 }
6352 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6353 // *data);
6354 llvm::Value *Args[] = {
6355 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6356 /*isSigned=*/true),
6357 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6358 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6359 CGM.VoidPtrTy)};
6360 return CGF.EmitRuntimeCall(
6361 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6362}
6363
6364void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6365 SourceLocation Loc,
6366 ReductionCodeGen &RCG,
6367 unsigned N) {
6368 auto Sizes = RCG.getSizes(N);
6369 // Emit threadprivate global variable if the type is non-constant
6370 // (Sizes.second = nullptr).
6371 if (Sizes.second) {
6372 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6373 /*isSigned=*/false);
6374 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6375 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006376 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006377 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6378 }
6379 // Store address of the original reduction item if custom initializer is used.
6380 if (RCG.usesReductionInitializer(N)) {
6381 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6382 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006383 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006384 CGF.Builder.CreateStore(
6385 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6386 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy),
6387 SharedAddr, /*IsVolatile=*/false);
6388 }
6389}
6390
6391Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6392 SourceLocation Loc,
6393 llvm::Value *ReductionsPtr,
6394 LValue SharedLVal) {
6395 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6396 // *d);
6397 llvm::Value *Args[] = {
6398 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6399 /*isSigned=*/true),
6400 ReductionsPtr,
6401 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(),
6402 CGM.VoidPtrTy)};
6403 return Address(
6404 CGF.EmitRuntimeCall(
6405 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6406 SharedLVal.getAlignment());
6407}
6408
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006409void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6410 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006411 if (!CGF.HaveInsertPoint())
6412 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006413 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6414 // global_tid);
6415 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6416 // Ignore return result until untied tasks are supported.
6417 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006418 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6419 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006420}
6421
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006422void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006423 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006424 const RegionCodeGenTy &CodeGen,
6425 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006426 if (!CGF.HaveInsertPoint())
6427 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006428 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006429 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006430}
6431
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006432namespace {
6433enum RTCancelKind {
6434 CancelNoreq = 0,
6435 CancelParallel = 1,
6436 CancelLoop = 2,
6437 CancelSections = 3,
6438 CancelTaskgroup = 4
6439};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006440} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006441
6442static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6443 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006444 if (CancelRegion == OMPD_parallel)
6445 CancelKind = CancelParallel;
6446 else if (CancelRegion == OMPD_for)
6447 CancelKind = CancelLoop;
6448 else if (CancelRegion == OMPD_sections)
6449 CancelKind = CancelSections;
6450 else {
6451 assert(CancelRegion == OMPD_taskgroup);
6452 CancelKind = CancelTaskgroup;
6453 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006454 return CancelKind;
6455}
6456
6457void CGOpenMPRuntime::emitCancellationPointCall(
6458 CodeGenFunction &CGF, SourceLocation Loc,
6459 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006460 if (!CGF.HaveInsertPoint())
6461 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006462 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6463 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006464 if (auto *OMPRegionInfo =
6465 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006466 // For 'cancellation point taskgroup', the task region info may not have a
6467 // cancel. This may instead happen in another adjacent task.
6468 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006469 llvm::Value *Args[] = {
6470 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6471 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006472 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006473 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006474 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6475 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006476 // exit from construct;
6477 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006478 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6479 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6480 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006481 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6482 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006483 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006484 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006485 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006486 CGF.EmitBranchThroughCleanup(CancelDest);
6487 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6488 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006489 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006490}
6491
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006492void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006493 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006494 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006495 if (!CGF.HaveInsertPoint())
6496 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006497 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6498 // kmp_int32 cncl_kind);
6499 if (auto *OMPRegionInfo =
6500 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006501 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6502 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006503 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006504 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006505 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006506 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6507 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006508 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006509 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006510 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006511 // exit from construct;
6512 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006513 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6514 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6515 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006516 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6517 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006518 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006519 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006520 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6521 CGF.EmitBranchThroughCleanup(CancelDest);
6522 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6523 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006524 if (IfCond) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006525 emitOMPIfClause(CGF, IfCond, ThenGen,
6526 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006527 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006528 RegionCodeGenTy ThenRCG(ThenGen);
6529 ThenRCG(CGF);
6530 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006531 }
6532}
Samuel Antaobed3c462015-10-02 16:14:20 +00006533
Samuel Antaoee8fb302016-01-06 13:42:12 +00006534void CGOpenMPRuntime::emitTargetOutlinedFunction(
6535 const OMPExecutableDirective &D, StringRef ParentName,
6536 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006537 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006538 assert(!ParentName.empty() && "Invalid target region parent name!");
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00006539 HasEmittedTargetRegion = true;
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006540 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6541 IsOffloadEntry, CodeGen);
6542}
6543
6544void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6545 const OMPExecutableDirective &D, StringRef ParentName,
6546 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6547 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006548 // Create a unique name for the entry function using the source location
6549 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006550 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006551 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006552 //
6553 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006554 // mangled name of the function that encloses the target region and BB is the
6555 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006556
6557 unsigned DeviceID;
6558 unsigned FileID;
6559 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006560 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006561 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006562 SmallString<64> EntryFnName;
6563 {
6564 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006565 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6566 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006567 }
6568
Alexey Bataev475a7442018-01-12 19:39:11 +00006569 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006570
Samuel Antaobed3c462015-10-02 16:14:20 +00006571 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006572 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006573 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006574
Samuel Antao6d004262016-06-16 18:39:34 +00006575 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006576
6577 // If this target outline function is not an offload entry, we don't need to
6578 // register it.
6579 if (!IsOffloadEntry)
6580 return;
6581
6582 // The target region ID is used by the runtime library to identify the current
6583 // target region, so it only has to be unique and not necessarily point to
6584 // anything. It could be the pointer to the outlined function that implements
6585 // the target region, but we aren't using that so that the compiler doesn't
6586 // need to keep that, and could therefore inline the host function if proven
6587 // worthwhile during optimization. In the other hand, if emitting code for the
6588 // device, the ID has to be the function address so that it can retrieved from
6589 // the offloading entry and launched by the runtime library. We also mark the
6590 // outlined function to have external linkage in case we are emitting code for
6591 // the device, because these functions will be entry points to the device.
6592
6593 if (CGM.getLangOpts().OpenMPIsDevice) {
6594 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006595 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006596 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006597 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006598 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006599 OutlinedFnID = new llvm::GlobalVariable(
6600 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006601 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006602 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006603 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006604
6605 // Register the information for the entry associated with this target region.
6606 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006607 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006608 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006609}
6610
Alexey Bataev5c427362019-04-10 19:11:33 +00006611/// Checks if the expression is constant or does not have non-trivial function
6612/// calls.
6613static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6614 // We can skip constant expressions.
6615 // We can skip expressions with trivial calls or simple expressions.
6616 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6617 !E->hasNonTrivialCall(Ctx)) &&
6618 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6619}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006620
Alexey Bataev5c427362019-04-10 19:11:33 +00006621const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6622 const Stmt *Body) {
6623 const Stmt *Child = Body->IgnoreContainers();
6624 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6625 Child = nullptr;
6626 for (const Stmt *S : C->body()) {
6627 if (const auto *E = dyn_cast<Expr>(S)) {
6628 if (isTrivial(Ctx, E))
6629 continue;
6630 }
6631 // Some of the statements can be ignored.
6632 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6633 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6634 continue;
6635 // Analyze declarations.
6636 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6637 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6638 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6639 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6640 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6641 isa<UsingDirectiveDecl>(D) ||
6642 isa<OMPDeclareReductionDecl>(D) ||
6643 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6644 return true;
6645 const auto *VD = dyn_cast<VarDecl>(D);
6646 if (!VD)
6647 return false;
6648 return VD->isConstexpr() ||
6649 ((VD->getType().isTrivialType(Ctx) ||
6650 VD->getType()->isReferenceType()) &&
6651 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6652 }))
6653 continue;
6654 }
6655 // Found multiple children - cannot get the one child only.
6656 if (Child)
6657 return nullptr;
6658 Child = S;
6659 }
6660 if (Child)
6661 Child = Child->IgnoreContainers();
6662 }
6663 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006664}
6665
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006666/// Emit the number of teams for a target directive. Inspect the num_teams
6667/// clause associated with a teams construct combined or closely nested
6668/// with the target directive.
6669///
6670/// Emit a team of size one for directives such as 'target parallel' that
6671/// have no associated teams construct.
6672///
6673/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006674static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006675emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006676 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006677 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6678 "Clauses associated with the teams directive expected to be emitted "
6679 "only for the host!");
6680 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6681 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6682 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006683 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006684 switch (DirectiveKind) {
6685 case OMPD_target: {
6686 const auto *CS = D.getInnermostCapturedStmt();
6687 const auto *Body =
6688 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6689 const Stmt *ChildStmt =
6690 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6691 if (const auto *NestedDir =
6692 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6693 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6694 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6695 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6696 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6697 const Expr *NumTeams =
6698 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6699 llvm::Value *NumTeamsVal =
6700 CGF.EmitScalarExpr(NumTeams,
6701 /*IgnoreResultAssign*/ true);
6702 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006703 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006704 }
6705 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006706 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006707 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6708 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6709 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006710 return Bld.getInt32(0);
6711 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006712 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006713 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006714 case OMPD_target_teams:
6715 case OMPD_target_teams_distribute:
6716 case OMPD_target_teams_distribute_simd:
6717 case OMPD_target_teams_distribute_parallel_for:
6718 case OMPD_target_teams_distribute_parallel_for_simd: {
6719 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6720 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6721 const Expr *NumTeams =
6722 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6723 llvm::Value *NumTeamsVal =
6724 CGF.EmitScalarExpr(NumTeams,
6725 /*IgnoreResultAssign*/ true);
6726 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006727 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006728 }
6729 return Bld.getInt32(0);
6730 }
6731 case OMPD_target_parallel:
6732 case OMPD_target_parallel_for:
6733 case OMPD_target_parallel_for_simd:
6734 case OMPD_target_simd:
6735 return Bld.getInt32(1);
6736 case OMPD_parallel:
6737 case OMPD_for:
6738 case OMPD_parallel_for:
6739 case OMPD_parallel_sections:
6740 case OMPD_for_simd:
6741 case OMPD_parallel_for_simd:
6742 case OMPD_cancel:
6743 case OMPD_cancellation_point:
6744 case OMPD_ordered:
6745 case OMPD_threadprivate:
6746 case OMPD_allocate:
6747 case OMPD_task:
6748 case OMPD_simd:
6749 case OMPD_sections:
6750 case OMPD_section:
6751 case OMPD_single:
6752 case OMPD_master:
6753 case OMPD_critical:
6754 case OMPD_taskyield:
6755 case OMPD_barrier:
6756 case OMPD_taskwait:
6757 case OMPD_taskgroup:
6758 case OMPD_atomic:
6759 case OMPD_flush:
6760 case OMPD_teams:
6761 case OMPD_target_data:
6762 case OMPD_target_exit_data:
6763 case OMPD_target_enter_data:
6764 case OMPD_distribute:
6765 case OMPD_distribute_simd:
6766 case OMPD_distribute_parallel_for:
6767 case OMPD_distribute_parallel_for_simd:
6768 case OMPD_teams_distribute:
6769 case OMPD_teams_distribute_simd:
6770 case OMPD_teams_distribute_parallel_for:
6771 case OMPD_teams_distribute_parallel_for_simd:
6772 case OMPD_target_update:
6773 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00006774 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00006775 case OMPD_declare_target:
6776 case OMPD_end_declare_target:
6777 case OMPD_declare_reduction:
6778 case OMPD_declare_mapper:
6779 case OMPD_taskloop:
6780 case OMPD_taskloop_simd:
6781 case OMPD_requires:
6782 case OMPD_unknown:
6783 break;
6784 }
6785 llvm_unreachable("Unexpected directive kind.");
6786}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006787
Alexey Bataev5c427362019-04-10 19:11:33 +00006788static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6789 llvm::Value *DefaultThreadLimitVal) {
6790 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6791 CGF.getContext(), CS->getCapturedStmt());
6792 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6793 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006794 llvm::Value *NumThreads = nullptr;
6795 llvm::Value *CondVal = nullptr;
6796 // Handle if clause. If if clause present, the number of threads is
6797 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6798 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6799 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6800 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6801 const OMPIfClause *IfClause = nullptr;
6802 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6803 if (C->getNameModifier() == OMPD_unknown ||
6804 C->getNameModifier() == OMPD_parallel) {
6805 IfClause = C;
6806 break;
6807 }
6808 }
6809 if (IfClause) {
6810 const Expr *Cond = IfClause->getCondition();
6811 bool Result;
6812 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6813 if (!Result)
6814 return CGF.Builder.getInt32(1);
6815 } else {
6816 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6817 if (const auto *PreInit =
6818 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6819 for (const auto *I : PreInit->decls()) {
6820 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6821 CGF.EmitVarDecl(cast<VarDecl>(*I));
6822 } else {
6823 CodeGenFunction::AutoVarEmission Emission =
6824 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6825 CGF.EmitAutoVarCleanups(Emission);
6826 }
6827 }
6828 }
6829 CondVal = CGF.EvaluateExprAsBool(Cond);
6830 }
6831 }
6832 }
6833 // Check the value of num_threads clause iff if clause was not specified
6834 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006835 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6836 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6837 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6838 const auto *NumThreadsClause =
6839 Dir->getSingleClause<OMPNumThreadsClause>();
6840 CodeGenFunction::LexicalScope Scope(
6841 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6842 if (const auto *PreInit =
6843 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6844 for (const auto *I : PreInit->decls()) {
6845 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6846 CGF.EmitVarDecl(cast<VarDecl>(*I));
6847 } else {
6848 CodeGenFunction::AutoVarEmission Emission =
6849 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6850 CGF.EmitAutoVarCleanups(Emission);
6851 }
6852 }
6853 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006854 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006855 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006856 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006857 if (DefaultThreadLimitVal)
6858 NumThreads = CGF.Builder.CreateSelect(
6859 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6860 DefaultThreadLimitVal, NumThreads);
6861 } else {
6862 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6863 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006864 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006865 // Process condition of the if clause.
6866 if (CondVal) {
6867 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6868 CGF.Builder.getInt32(1));
6869 }
6870 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006871 }
6872 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6873 return CGF.Builder.getInt32(1);
6874 return DefaultThreadLimitVal;
6875 }
6876 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6877 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006878}
6879
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006880/// Emit the number of threads for a target directive. Inspect the
6881/// thread_limit clause associated with a teams construct combined or closely
6882/// nested with the target directive.
6883///
6884/// Emit the num_threads clause for directives such as 'target parallel' that
6885/// have no associated teams construct.
6886///
6887/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006888static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006889emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006890 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006891 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6892 "Clauses associated with the teams directive expected to be emitted "
6893 "only for the host!");
6894 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6895 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6896 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006897 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006898 llvm::Value *ThreadLimitVal = nullptr;
6899 llvm::Value *NumThreadsVal = nullptr;
6900 switch (DirectiveKind) {
6901 case OMPD_target: {
6902 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6903 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6904 return NumThreads;
6905 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6906 CGF.getContext(), CS->getCapturedStmt());
6907 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6908 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6909 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6910 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6911 const auto *ThreadLimitClause =
6912 Dir->getSingleClause<OMPThreadLimitClause>();
6913 CodeGenFunction::LexicalScope Scope(
6914 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6915 if (const auto *PreInit =
6916 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6917 for (const auto *I : PreInit->decls()) {
6918 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6919 CGF.EmitVarDecl(cast<VarDecl>(*I));
6920 } else {
6921 CodeGenFunction::AutoVarEmission Emission =
6922 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6923 CGF.EmitAutoVarCleanups(Emission);
6924 }
6925 }
6926 }
6927 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6928 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6929 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006930 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006931 }
6932 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6933 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6934 CS = Dir->getInnermostCapturedStmt();
6935 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6936 CGF.getContext(), CS->getCapturedStmt());
6937 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6938 }
6939 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6940 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6941 CS = Dir->getInnermostCapturedStmt();
6942 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6943 return NumThreads;
6944 }
6945 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6946 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006947 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006948 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6949 }
6950 case OMPD_target_teams: {
6951 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6952 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6953 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6954 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6955 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6956 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006957 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006958 }
6959 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6960 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6961 return NumThreads;
6962 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6963 CGF.getContext(), CS->getCapturedStmt());
6964 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6965 if (Dir->getDirectiveKind() == OMPD_distribute) {
6966 CS = Dir->getInnermostCapturedStmt();
6967 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6968 return NumThreads;
6969 }
6970 }
6971 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6972 }
6973 case OMPD_target_teams_distribute:
6974 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6975 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6976 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6977 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6978 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6979 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006980 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006981 }
6982 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6983 case OMPD_target_parallel:
6984 case OMPD_target_parallel_for:
6985 case OMPD_target_parallel_for_simd:
6986 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006987 case OMPD_target_teams_distribute_parallel_for_simd: {
6988 llvm::Value *CondVal = nullptr;
6989 // Handle if clause. If if clause present, the number of threads is
6990 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6991 if (D.hasClausesOfKind<OMPIfClause>()) {
6992 const OMPIfClause *IfClause = nullptr;
6993 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6994 if (C->getNameModifier() == OMPD_unknown ||
6995 C->getNameModifier() == OMPD_parallel) {
6996 IfClause = C;
6997 break;
6998 }
6999 }
7000 if (IfClause) {
7001 const Expr *Cond = IfClause->getCondition();
7002 bool Result;
7003 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
7004 if (!Result)
7005 return Bld.getInt32(1);
7006 } else {
7007 CodeGenFunction::RunCleanupsScope Scope(CGF);
7008 CondVal = CGF.EvaluateExprAsBool(Cond);
7009 }
7010 }
7011 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007012 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
7013 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
7014 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
7015 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
7016 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
7017 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007018 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00007019 }
7020 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00007021 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00007022 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
7023 llvm::Value *NumThreads = CGF.EmitScalarExpr(
7024 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00007025 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007026 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00007027 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00007028 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00007029 ThreadLimitVal),
7030 NumThreadsVal, ThreadLimitVal)
7031 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00007032 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00007033 if (!ThreadLimitVal)
7034 ThreadLimitVal = Bld.getInt32(0);
7035 if (CondVal)
7036 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
7037 return ThreadLimitVal;
7038 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007039 case OMPD_target_teams_distribute_simd:
7040 case OMPD_target_simd:
7041 return Bld.getInt32(1);
7042 case OMPD_parallel:
7043 case OMPD_for:
7044 case OMPD_parallel_for:
7045 case OMPD_parallel_sections:
7046 case OMPD_for_simd:
7047 case OMPD_parallel_for_simd:
7048 case OMPD_cancel:
7049 case OMPD_cancellation_point:
7050 case OMPD_ordered:
7051 case OMPD_threadprivate:
7052 case OMPD_allocate:
7053 case OMPD_task:
7054 case OMPD_simd:
7055 case OMPD_sections:
7056 case OMPD_section:
7057 case OMPD_single:
7058 case OMPD_master:
7059 case OMPD_critical:
7060 case OMPD_taskyield:
7061 case OMPD_barrier:
7062 case OMPD_taskwait:
7063 case OMPD_taskgroup:
7064 case OMPD_atomic:
7065 case OMPD_flush:
7066 case OMPD_teams:
7067 case OMPD_target_data:
7068 case OMPD_target_exit_data:
7069 case OMPD_target_enter_data:
7070 case OMPD_distribute:
7071 case OMPD_distribute_simd:
7072 case OMPD_distribute_parallel_for:
7073 case OMPD_distribute_parallel_for_simd:
7074 case OMPD_teams_distribute:
7075 case OMPD_teams_distribute_simd:
7076 case OMPD_teams_distribute_parallel_for:
7077 case OMPD_teams_distribute_parallel_for_simd:
7078 case OMPD_target_update:
7079 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00007080 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00007081 case OMPD_declare_target:
7082 case OMPD_end_declare_target:
7083 case OMPD_declare_reduction:
7084 case OMPD_declare_mapper:
7085 case OMPD_taskloop:
7086 case OMPD_taskloop_simd:
7087 case OMPD_requires:
7088 case OMPD_unknown:
7089 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007090 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007091 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007092}
7093
Samuel Antao86ace552016-04-27 22:40:57 +00007094namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007095LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7096
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007097// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007098// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7099// It provides a convenient interface to obtain the information and generate
7100// code for that information.
7101class MappableExprsHandler {
7102public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007103 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007104 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007105 enum OpenMPOffloadMappingFlags : uint64_t {
7106 /// No flags
7107 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007108 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007109 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007110 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007111 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007112 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007113 /// if it was already mapped before.
7114 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007115 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007116 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007117 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007118 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007119 /// pointer and the pointee should be mapped.
7120 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007121 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007122 /// passed to the target kernel as an argument.
7123 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007124 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007125 /// in the current position for the data being mapped. Used when we have the
7126 /// use_device_ptr clause.
7127 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007128 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007129 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007130 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007131 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007132 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007133 /// Implicit map
7134 OMP_MAP_IMPLICIT = 0x200,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007135 /// Close is a hint to the runtime to allocate memory close to
7136 /// the target device.
7137 OMP_MAP_CLOSE = 0x400,
Alexey Bataevb3638132018-07-19 16:34:13 +00007138 /// The 16 MSBs of the flags indicate whether the entry is member of some
7139 /// struct/class.
7140 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7141 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007142 };
7143
Michael Krused47b9432019-08-05 18:43:21 +00007144 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7145 static unsigned getFlagMemberOffset() {
7146 unsigned Offset = 0;
7147 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7148 Remain = Remain >> 1)
7149 Offset++;
7150 return Offset;
7151 }
7152
Samuel Antaocc10b852016-07-28 14:23:26 +00007153 /// Class that associates information with a base pointer to be passed to the
7154 /// runtime library.
7155 class BasePointerInfo {
7156 /// The base pointer.
7157 llvm::Value *Ptr = nullptr;
7158 /// The base declaration that refers to this device pointer, or null if
7159 /// there is none.
7160 const ValueDecl *DevPtrDecl = nullptr;
7161
7162 public:
7163 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7164 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7165 llvm::Value *operator*() const { return Ptr; }
7166 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7167 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7168 };
7169
Alexey Bataevb3638132018-07-19 16:34:13 +00007170 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7171 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7172 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7173
7174 /// Map between a struct and the its lowest & highest elements which have been
7175 /// mapped.
7176 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7177 /// HE(FieldIndex, Pointer)}
7178 struct StructRangeInfoTy {
7179 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7180 0, Address::invalid()};
7181 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7182 0, Address::invalid()};
7183 Address Base = Address::invalid();
7184 };
Samuel Antao86ace552016-04-27 22:40:57 +00007185
7186private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007187 /// Kind that defines how a device pointer has to be returned.
7188 struct MapInfo {
7189 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7190 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007191 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007192 bool ReturnDevicePointer = false;
7193 bool IsImplicit = false;
7194
7195 MapInfo() = default;
7196 MapInfo(
7197 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007198 OpenMPMapClauseKind MapType,
7199 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007200 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007201 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007202 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7203 };
7204
7205 /// If use_device_ptr is used on a pointer which is a struct member and there
7206 /// is no map information about it, then emission of that entry is deferred
7207 /// until the whole struct has been processed.
7208 struct DeferredDevicePtrEntryTy {
7209 const Expr *IE = nullptr;
7210 const ValueDecl *VD = nullptr;
7211
7212 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7213 : IE(IE), VD(VD) {}
7214 };
7215
Michael Krused47b9432019-08-05 18:43:21 +00007216 /// The target directive from where the mappable clauses were extracted. It
7217 /// is either a executable directive or a user-defined mapper directive.
7218 llvm::PointerUnion<const OMPExecutableDirective *,
7219 const OMPDeclareMapperDecl *>
7220 CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007221
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007222 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007223 CodeGenFunction &CGF;
7224
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007225 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007226 /// bool data is set to true if the variable is implicitly marked as
7227 /// firstprivate, false otherwise.
7228 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007229
Samuel Antao6890b092016-07-28 14:25:09 +00007230 /// Map between device pointer declarations and their expression components.
7231 /// The key value for declarations in 'this' is null.
7232 llvm::DenseMap<
7233 const ValueDecl *,
7234 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7235 DevPointersMap;
7236
Samuel Antao86ace552016-04-27 22:40:57 +00007237 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007238 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007239
7240 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007241 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007242 ExprTy = RefTy->getPointeeType().getCanonicalType();
7243
7244 // Given that an array section is considered a built-in type, we need to
7245 // do the calculation based on the length of the section instead of relying
7246 // on CGF.getTypeSize(E->getType()).
7247 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7248 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7249 OAE->getBase()->IgnoreParenImpCasts())
7250 .getCanonicalType();
7251
7252 // If there is no length associated with the expression, that means we
7253 // are using the whole length of the base.
7254 if (!OAE->getLength() && OAE->getColonLoc().isValid())
7255 return CGF.getTypeSize(BaseTy);
7256
7257 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007258 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007259 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007260 } else {
7261 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007262 assert(ATy && "Expecting array type if not a pointer type.");
7263 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7264 }
7265
7266 // If we don't have a length at this point, that is because we have an
7267 // array section with a single element.
7268 if (!OAE->getLength())
7269 return ElemSize;
7270
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007271 llvm::Value *LengthVal = CGF.EmitScalarExpr(OAE->getLength());
Samuel Antao86ace552016-04-27 22:40:57 +00007272 LengthVal =
7273 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false);
7274 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7275 }
7276 return CGF.getTypeSize(ExprTy);
7277 }
7278
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007279 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007280 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007281 /// map as the first one of a series of maps that relate to the same map
7282 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007283 OpenMPOffloadMappingFlags getMapTypeBits(
7284 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7285 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007286 OpenMPOffloadMappingFlags Bits =
7287 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007288 switch (MapType) {
7289 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007290 case OMPC_MAP_release:
7291 // alloc and release is the default behavior in the runtime library, i.e.
7292 // if we don't pass any bits alloc/release that is what the runtime is
7293 // going to do. Therefore, we don't need to signal anything for these two
7294 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007295 break;
7296 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007297 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007298 break;
7299 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007300 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007301 break;
7302 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007303 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007304 break;
7305 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007306 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007307 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007308 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007309 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007310 }
7311 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007312 Bits |= OMP_MAP_PTR_AND_OBJ;
7313 if (AddIsTargetParamFlag)
7314 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007315 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7316 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007317 Bits |= OMP_MAP_ALWAYS;
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007318 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7319 != MapModifiers.end())
7320 Bits |= OMP_MAP_CLOSE;
Samuel Antao86ace552016-04-27 22:40:57 +00007321 return Bits;
7322 }
7323
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007324 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007325 /// final array section, is one whose length can't be proved to be one.
7326 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007327 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007328
7329 // It is not an array section and therefore not a unity-size one.
7330 if (!OASE)
7331 return false;
7332
7333 // An array section with no colon always refer to a single element.
7334 if (OASE->getColonLoc().isInvalid())
7335 return false;
7336
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007337 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007338
7339 // If we don't have a length we have to check if the array has size 1
7340 // for this dimension. Also, we should always expect a length if the
7341 // base type is pointer.
7342 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007343 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7344 OASE->getBase()->IgnoreParenImpCasts())
7345 .getCanonicalType();
7346 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007347 return ATy->getSize().getSExtValue() != 1;
7348 // If we don't have a constant dimension length, we have to consider
7349 // the current section as having any size, so it is not necessarily
7350 // unitary. If it happen to be unity size, that's user fault.
7351 return true;
7352 }
7353
7354 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007355 Expr::EvalResult Result;
7356 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007357 return true; // Can have more that size 1.
7358
Fangrui Song407659a2018-11-30 23:41:18 +00007359 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007360 return ConstLength.getSExtValue() != 1;
7361 }
7362
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007363 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007364 /// bits for the provided map type, map modifier, and expression components.
7365 /// \a IsFirstComponent should be set to true if the provided set of
7366 /// components is the first associated with a capture.
7367 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007368 OpenMPMapClauseKind MapType,
7369 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007370 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007371 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007372 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007373 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007374 bool IsImplicit,
7375 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7376 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007377 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007378 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007379 // base pointer, section pointer, size, flags
7380 // (to add to the ones that come from the map type and modifier).
7381 //
7382 // double d;
7383 // int i[100];
7384 // float *p;
7385 //
7386 // struct S1 {
7387 // int i;
7388 // float f[50];
7389 // }
7390 // struct S2 {
7391 // int i;
7392 // float f[50];
7393 // S1 s;
7394 // double *p;
7395 // struct S2 *ps;
7396 // }
7397 // S2 s;
7398 // S2 *ps;
7399 //
7400 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007401 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007402 //
7403 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007404 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007405 //
7406 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007407 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007408 //
7409 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007410 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007411 //
7412 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007413 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007414 //
7415 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007416 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007417 //
7418 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007419 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007420 //
7421 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007422 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007423 //
7424 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007425 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007426 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007427 // map(to: s.p[:22])
7428 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7429 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7430 // &(s.p), &(s.p[0]), 22*sizeof(double),
7431 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7432 // (*) alloc space for struct members, only this is a target parameter
7433 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7434 // optimizes this entry out, same in the examples below)
7435 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007436 //
7437 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007438 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007439 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007440 // map(from: s.ps->s.i)
7441 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7442 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7443 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007444 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007445 // map(to: s.ps->ps)
7446 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7447 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7448 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007449 //
7450 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007451 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7452 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7453 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7454 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007455 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007456 // map(to: s.ps->ps->s.f[:22])
7457 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7458 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7459 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7460 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007461 //
7462 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007463 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007464 //
7465 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007466 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007467 //
7468 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007469 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007470 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007471 // map(from: ps->p)
7472 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007473 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007474 // map(to: ps->p[:22])
7475 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7476 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7477 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007478 //
7479 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007480 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007481 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007482 // map(from: ps->ps->s.i)
7483 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7484 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7485 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007486 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007487 // map(from: ps->ps->ps)
7488 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7489 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7490 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007491 //
7492 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007493 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7494 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7495 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7496 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007497 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007498 // map(to: ps->ps->ps->s.f[:22])
7499 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7500 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7501 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7502 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7503 //
7504 // map(to: s.f[:22]) map(from: s.p[:33])
7505 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7506 // sizeof(double*) (**), TARGET_PARAM
7507 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7508 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7509 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7510 // (*) allocate contiguous space needed to fit all mapped members even if
7511 // we allocate space for members not mapped (in this example,
7512 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7513 // them as well because they fall between &s.f[0] and &s.p)
7514 //
7515 // map(from: s.f[:22]) map(to: ps->p[:33])
7516 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7517 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7518 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7519 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7520 // (*) the struct this entry pertains to is the 2nd element in the list of
7521 // arguments, hence MEMBER_OF(2)
7522 //
7523 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7524 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7525 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7526 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7527 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7528 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7529 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7530 // (*) the struct this entry pertains to is the 4th element in the list
7531 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007532
7533 // Track if the map information being generated is the first for a capture.
7534 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007535 // When the variable is on a declare target link or in a to clause with
7536 // unified memory, a reference is needed to hold the host/device address
7537 // of the variable.
7538 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007539
7540 // Scan the components from the base to the complete expression.
7541 auto CI = Components.rbegin();
7542 auto CE = Components.rend();
7543 auto I = CI;
7544
7545 // Track if the map information being generated is the first for a list of
7546 // components.
7547 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007548 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007549 const Expr *AssocExpr = I->getAssociatedExpression();
7550 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7551 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007552
Patrick Lystere13b1e32019-01-02 19:28:48 +00007553 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007554 // The base is the 'this' pointer. The content of the pointer is going
7555 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007556 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007557 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7558 (OASE &&
7559 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7560 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007561 } else {
7562 // The base is the reference to the variable.
7563 // BP = &Var.
Patrick Lystere13b1e32019-01-02 19:28:48 +00007564 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Alexey Bataev92327c52018-03-26 16:40:55 +00007565 if (const auto *VD =
7566 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7567 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007568 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7569 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7570 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7571 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7572 RequiresReference = true;
7573 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007574 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007575 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007576 }
Samuel Antao86ace552016-04-27 22:40:57 +00007577
7578 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007579 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007580 // reference. References are ignored for mapping purposes.
7581 QualType Ty =
7582 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7583 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007584 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007585
7586 // We do not need to generate individual map information for the
7587 // pointer, it can be associated with the combined storage.
7588 ++I;
7589 }
7590 }
7591
Alexey Bataevb3638132018-07-19 16:34:13 +00007592 // Track whether a component of the list should be marked as MEMBER_OF some
7593 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7594 // in a component list should be marked as MEMBER_OF, all subsequent entries
7595 // do not belong to the base struct. E.g.
7596 // struct S2 s;
7597 // s.ps->ps->ps->f[:]
7598 // (1) (2) (3) (4)
7599 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7600 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7601 // is the pointee of ps(2) which is not member of struct s, so it should not
7602 // be marked as such (it is still PTR_AND_OBJ).
7603 // The variable is initialized to false so that PTR_AND_OBJ entries which
7604 // are not struct members are not considered (e.g. array of pointers to
7605 // data).
7606 bool ShouldBeMemberOf = false;
7607
7608 // Variable keeping track of whether or not we have encountered a component
7609 // in the component list which is a member expression. Useful when we have a
7610 // pointer or a final array section, in which case it is the previous
7611 // component in the list which tells us whether we have a member expression.
7612 // E.g. X.f[:]
7613 // While processing the final array section "[:]" it is "f" which tells us
7614 // whether we are dealing with a member of a declared struct.
7615 const MemberExpr *EncounteredME = nullptr;
7616
Samuel Antao86ace552016-04-27 22:40:57 +00007617 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007618 // If the current component is member of a struct (parent struct) mark it.
7619 if (!EncounteredME) {
7620 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7621 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7622 // as MEMBER_OF the parent struct.
7623 if (EncounteredME)
7624 ShouldBeMemberOf = true;
7625 }
7626
Samuel Antao86ace552016-04-27 22:40:57 +00007627 auto Next = std::next(I);
7628
7629 // We need to generate the addresses and sizes if this is the last
7630 // component, if the component is a pointer or if it is an array section
7631 // whose length can't be proved to be one. If this is a pointer, it
7632 // becomes the base address for the following components.
7633
7634 // A final array section, is one whose length can't be proved to be one.
7635 bool IsFinalArraySection =
7636 isFinalArraySectionExpression(I->getAssociatedExpression());
7637
7638 // Get information on whether the element is a pointer. Have to do a
7639 // special treatment for array sections given that they are built-in
7640 // types.
7641 const auto *OASE =
7642 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7643 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007644 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7645 .getCanonicalType()
7646 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007647 I->getAssociatedExpression()->getType()->isAnyPointerType();
7648
7649 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007650 // If this is not the last component, we expect the pointer to be
7651 // associated with an array expression or member expression.
7652 assert((Next == CE ||
7653 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7654 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7655 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7656 "Unexpected expression");
7657
Alexey Bataevb3638132018-07-19 16:34:13 +00007658 Address LB =
7659 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007660
Alexey Bataevb3638132018-07-19 16:34:13 +00007661 // If this component is a pointer inside the base struct then we don't
7662 // need to create any entry for it - it will be combined with the object
7663 // it is pointing to into a single PTR_AND_OBJ entry.
7664 bool IsMemberPointer =
7665 IsPointer && EncounteredME &&
7666 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7667 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007668 if (!OverlappedElements.empty()) {
7669 // Handle base element with the info for overlapped elements.
7670 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7671 assert(Next == CE &&
7672 "Expected last element for the overlapped elements.");
7673 assert(!IsPointer &&
7674 "Unexpected base element with the pointer type.");
7675 // Mark the whole struct as the struct that requires allocation on the
7676 // device.
7677 PartialStruct.LowestElem = {0, LB};
7678 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7679 I->getAssociatedExpression()->getType());
7680 Address HB = CGF.Builder.CreateConstGEP(
7681 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7682 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007683 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007684 PartialStruct.HighestElem = {
7685 std::numeric_limits<decltype(
7686 PartialStruct.HighestElem.first)>::max(),
7687 HB};
7688 PartialStruct.Base = BP;
7689 // Emit data for non-overlapped data.
7690 OpenMPOffloadMappingFlags Flags =
7691 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007692 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007693 /*AddPtrFlag=*/false,
7694 /*AddIsTargetParamFlag=*/false);
7695 LB = BP;
7696 llvm::Value *Size = nullptr;
7697 // Do bitcopy of all non-overlapped structure elements.
7698 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7699 Component : OverlappedElements) {
7700 Address ComponentLB = Address::invalid();
7701 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7702 Component) {
7703 if (MC.getAssociatedDeclaration()) {
7704 ComponentLB =
7705 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7706 .getAddress();
7707 Size = CGF.Builder.CreatePtrDiff(
7708 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7709 CGF.EmitCastToVoidPtr(LB.getPointer()));
7710 break;
7711 }
7712 }
7713 BasePointers.push_back(BP.getPointer());
7714 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007715 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7716 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007717 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007718 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007719 }
7720 BasePointers.push_back(BP.getPointer());
7721 Pointers.push_back(LB.getPointer());
7722 Size = CGF.Builder.CreatePtrDiff(
7723 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007724 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007725 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007726 Sizes.push_back(
7727 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007728 Types.push_back(Flags);
7729 break;
7730 }
7731 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007732 if (!IsMemberPointer) {
7733 BasePointers.push_back(BP.getPointer());
7734 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007735 Sizes.push_back(
7736 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007737
Alexey Bataevb3638132018-07-19 16:34:13 +00007738 // We need to add a pointer flag for each map that comes from the
7739 // same expression except for the first one. We also need to signal
7740 // this map is the first one that relates with the current capture
7741 // (there is a set of entries for each capture).
7742 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007743 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007744 !IsExpressionFirstInfo || RequiresReference,
7745 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007746
7747 if (!IsExpressionFirstInfo) {
7748 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007749 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
Alexey Bataevb3638132018-07-19 16:34:13 +00007750 if (IsPointer)
7751 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007752 OMP_MAP_DELETE | OMP_MAP_CLOSE);
Alexey Bataevb3638132018-07-19 16:34:13 +00007753
7754 if (ShouldBeMemberOf) {
7755 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7756 // should be later updated with the correct value of MEMBER_OF.
7757 Flags |= OMP_MAP_MEMBER_OF;
7758 // From now on, all subsequent PTR_AND_OBJ entries should not be
7759 // marked as MEMBER_OF.
7760 ShouldBeMemberOf = false;
7761 }
7762 }
7763
7764 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007765 }
7766
Alexey Bataevb3638132018-07-19 16:34:13 +00007767 // If we have encountered a member expression so far, keep track of the
7768 // mapped member. If the parent is "*this", then the value declaration
7769 // is nullptr.
7770 if (EncounteredME) {
7771 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7772 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007773
Alexey Bataevb3638132018-07-19 16:34:13 +00007774 // Update info about the lowest and highest elements for this struct
7775 if (!PartialStruct.Base.isValid()) {
7776 PartialStruct.LowestElem = {FieldIndex, LB};
7777 PartialStruct.HighestElem = {FieldIndex, LB};
7778 PartialStruct.Base = BP;
7779 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7780 PartialStruct.LowestElem = {FieldIndex, LB};
7781 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7782 PartialStruct.HighestElem = {FieldIndex, LB};
7783 }
7784 }
Samuel Antao86ace552016-04-27 22:40:57 +00007785
7786 // If we have a final array section, we are done with this expression.
7787 if (IsFinalArraySection)
7788 break;
7789
7790 // The pointer becomes the base for the next element.
7791 if (Next != CE)
7792 BP = LB;
7793
7794 IsExpressionFirstInfo = false;
7795 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007796 }
7797 }
7798 }
7799
Alexey Bataevb3638132018-07-19 16:34:13 +00007800 /// Return the adjusted map modifiers if the declaration a capture refers to
7801 /// appears in a first-private clause. This is expected to be used only with
7802 /// directives that start with 'target'.
7803 MappableExprsHandler::OpenMPOffloadMappingFlags
7804 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7805 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7806
7807 // A first private variable captured by reference will use only the
7808 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7809 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007810 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7811 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7812 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7813 return MappableExprsHandler::OMP_MAP_ALWAYS |
7814 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007815 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7816 return MappableExprsHandler::OMP_MAP_TO |
7817 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007818 return MappableExprsHandler::OMP_MAP_PRIVATE |
7819 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007820 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007821 return MappableExprsHandler::OMP_MAP_TO |
7822 MappableExprsHandler::OMP_MAP_FROM;
7823 }
7824
7825 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
Michael Krused47b9432019-08-05 18:43:21 +00007826 // Rotate by getFlagMemberOffset() bits.
Alexey Bataevb3638132018-07-19 16:34:13 +00007827 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
Michael Krused47b9432019-08-05 18:43:21 +00007828 << getFlagMemberOffset());
Alexey Bataevb3638132018-07-19 16:34:13 +00007829 }
7830
7831 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7832 OpenMPOffloadMappingFlags MemberOfFlag) {
7833 // If the entry is PTR_AND_OBJ but has not been marked with the special
7834 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7835 // marked as MEMBER_OF.
7836 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7837 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7838 return;
7839
7840 // Reset the placeholder value to prepare the flag for the assignment of the
7841 // proper MEMBER_OF value.
7842 Flags &= ~OMP_MAP_MEMBER_OF;
7843 Flags |= MemberOfFlag;
7844 }
7845
Alexey Bataeve82445f2018-09-20 13:54:02 +00007846 void getPlainLayout(const CXXRecordDecl *RD,
7847 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7848 bool AsBase) const {
7849 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7850
7851 llvm::StructType *St =
7852 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7853
7854 unsigned NumElements = St->getNumElements();
7855 llvm::SmallVector<
7856 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7857 RecordLayout(NumElements);
7858
7859 // Fill bases.
7860 for (const auto &I : RD->bases()) {
7861 if (I.isVirtual())
7862 continue;
7863 const auto *Base = I.getType()->getAsCXXRecordDecl();
7864 // Ignore empty bases.
7865 if (Base->isEmpty() || CGF.getContext()
7866 .getASTRecordLayout(Base)
7867 .getNonVirtualSize()
7868 .isZero())
7869 continue;
7870
7871 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7872 RecordLayout[FieldIndex] = Base;
7873 }
7874 // Fill in virtual bases.
7875 for (const auto &I : RD->vbases()) {
7876 const auto *Base = I.getType()->getAsCXXRecordDecl();
7877 // Ignore empty bases.
7878 if (Base->isEmpty())
7879 continue;
7880 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7881 if (RecordLayout[FieldIndex])
7882 continue;
7883 RecordLayout[FieldIndex] = Base;
7884 }
7885 // Fill in all the fields.
7886 assert(!RD->isUnion() && "Unexpected union.");
7887 for (const auto *Field : RD->fields()) {
7888 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7889 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007890 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007891 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7892 RecordLayout[FieldIndex] = Field;
7893 }
7894 }
7895 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7896 &Data : RecordLayout) {
7897 if (Data.isNull())
7898 continue;
7899 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7900 getPlainLayout(Base, Layout, /*AsBase=*/true);
7901 else
7902 Layout.push_back(Data.get<const FieldDecl *>());
7903 }
7904 }
7905
Alexey Bataevb3638132018-07-19 16:34:13 +00007906public:
7907 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Michael Krused47b9432019-08-05 18:43:21 +00007908 : CurDir(&Dir), CGF(CGF) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007909 // Extract firstprivate clause information.
7910 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7911 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00007912 FirstPrivateDecls.try_emplace(
7913 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00007914 // Extract device pointer clause information.
7915 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7916 for (auto L : C->component_lists())
7917 DevPointersMap[L.first].push_back(L.second);
7918 }
7919
Michael Krused47b9432019-08-05 18:43:21 +00007920 /// Constructor for the declare mapper directive.
7921 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
7922 : CurDir(&Dir), CGF(CGF) {}
7923
Alexey Bataevb3638132018-07-19 16:34:13 +00007924 /// Generate code for the combined entry if we have a partially mapped struct
7925 /// and take care of the mapping flags of the arguments corresponding to
7926 /// individual struct members.
7927 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7928 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7929 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7930 const StructRangeInfoTy &PartialStruct) const {
7931 // Base is the base of the struct
7932 BasePointers.push_back(PartialStruct.Base.getPointer());
7933 // Pointer is the address of the lowest element
7934 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7935 Pointers.push_back(LB);
7936 // Size is (addr of {highest+1} element) - (addr of lowest element)
7937 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7938 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7939 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7940 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7941 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007942 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007943 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00007944 Sizes.push_back(Size);
7945 // Map type is always TARGET_PARAM
7946 Types.push_back(OMP_MAP_TARGET_PARAM);
7947 // Remove TARGET_PARAM flag from the first element
7948 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7949
7950 // All other current entries will be MEMBER_OF the combined entry
7951 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7952 // 0xFFFF in the MEMBER_OF field).
7953 OpenMPOffloadMappingFlags MemberOfFlag =
7954 getMemberOfFlag(BasePointers.size() - 1);
7955 for (auto &M : CurTypes)
7956 setCorrectMemberOfFlag(M, MemberOfFlag);
7957 }
7958
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007959 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007960 /// types for the extracted mappable expressions. Also, for each item that
7961 /// relates with a device pointer, a pair of the relevant declaration and
7962 /// index where it occurs is appended to the device pointers info array.
7963 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007964 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7965 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007966 // We have to process the component lists that relate with the same
7967 // declaration in a single chunk so that we can generate the map flags
7968 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007969 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007970
7971 // Helper function to fill the information map for the different supported
7972 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007973 auto &&InfoGen = [&Info](
7974 const ValueDecl *D,
7975 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007976 OpenMPMapClauseKind MapType,
7977 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007978 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007979 const ValueDecl *VD =
7980 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007981 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007982 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007983 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007984
Michael Krused47b9432019-08-05 18:43:21 +00007985 assert(CurDir.is<const OMPExecutableDirective *>() &&
7986 "Expect a executable directive");
7987 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
7988 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007989 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007990 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007991 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007992 }
Michael Krused47b9432019-08-05 18:43:21 +00007993 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007994 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007995 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007996 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007997 }
Michael Krused47b9432019-08-05 18:43:21 +00007998 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007999 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00008000 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008001 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00008002 }
Samuel Antao86ace552016-04-27 22:40:57 +00008003
Samuel Antaocc10b852016-07-28 14:23:26 +00008004 // Look at the use_device_ptr clause information and mark the existing map
8005 // entries as such. If there is no map information for an entry in the
8006 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00008007 // section. It is the user fault if that was not mapped before. If there is
8008 // no map information and the pointer is a struct member, then we defer the
8009 // emission of that entry until the whole struct has been processed.
8010 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
8011 DeferredInfo;
8012
Alexey Bataevb3638132018-07-19 16:34:13 +00008013 for (const auto *C :
Michael Krused47b9432019-08-05 18:43:21 +00008014 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008015 for (const auto &L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00008016 assert(!L.second.empty() && "Not expecting empty list of components!");
8017 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
8018 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008019 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00008020 // If the first component is a member expression, we have to look into
8021 // 'this', which maps to null in the map of map information. Otherwise
8022 // look directly for the information.
8023 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8024
8025 // We potentially have map information for this declaration already.
8026 // Look for the first set of components that refer to it.
8027 if (It != Info.end()) {
8028 auto CI = std::find_if(
8029 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
8030 return MI.Components.back().getAssociatedDeclaration() == VD;
8031 });
8032 // If we found a map entry, signal that the pointer has to be returned
8033 // and move on to the next declaration.
8034 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008035 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00008036 continue;
8037 }
8038 }
8039
8040 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00008041 // size array section - if the pointer is a struct member we defer this
8042 // action until the whole struct has been processed.
Alexey Bataevb3638132018-07-19 16:34:13 +00008043 if (isa<MemberExpr>(IE)) {
8044 // Insert the pointer into Info to be processed by
8045 // generateInfoForComponentList. Because it is a member pointer
8046 // without a pointee, no entry will be generated for it, therefore
8047 // we need to generate one after the whole struct has been processed.
8048 // Nonetheless, generateInfoForComponentList must be called to take
8049 // the pointer into account for the calculation of the range of the
8050 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00008051 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008052 /*ReturnDevicePointer=*/false, C->isImplicit());
8053 DeferredInfo[nullptr].emplace_back(IE, VD);
8054 } else {
Michael Krused47b9432019-08-05 18:43:21 +00008055 llvm::Value *Ptr =
8056 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
Alexey Bataevb3638132018-07-19 16:34:13 +00008057 BasePointers.emplace_back(Ptr, VD);
8058 Pointers.push_back(Ptr);
Michael Krused47b9432019-08-05 18:43:21 +00008059 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008060 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8061 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008062 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008063 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008064
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008065 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00008066 // We need to know when we generate information for the first component
8067 // associated with a capture, because the mapping flags depend on it.
8068 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00008069
8070 // Temporary versions of arrays
8071 MapBaseValuesArrayTy CurBasePointers;
8072 MapValuesArrayTy CurPointers;
8073 MapValuesArrayTy CurSizes;
8074 MapFlagsArrayTy CurTypes;
8075 StructRangeInfoTy PartialStruct;
8076
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008077 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008078 assert(!L.Components.empty() &&
8079 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008080
8081 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008082 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Michael Krused47b9432019-08-05 18:43:21 +00008083 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8084 CurBasePointers, CurPointers, CurSizes,
8085 CurTypes, PartialStruct,
8086 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008087
8088 // If this entry relates with a device pointer, set the relevant
8089 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008090 if (L.ReturnDevicePointer) {
8091 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008092 "Unexpected number of mapped base pointers.");
8093
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008094 const ValueDecl *RelevantVD =
8095 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008096 assert(RelevantVD &&
8097 "No relevant declaration related with device pointer??");
8098
Alexey Bataevb3638132018-07-19 16:34:13 +00008099 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8100 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008101 }
Samuel Antao86ace552016-04-27 22:40:57 +00008102 IsFirstComponentList = false;
8103 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008104
8105 // Append any pending zero-length pointers which are struct members and
8106 // used with use_device_ptr.
8107 auto CI = DeferredInfo.find(M.first);
8108 if (CI != DeferredInfo.end()) {
8109 for (const DeferredDevicePtrEntryTy &L : CI->second) {
8110 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer();
8111 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8112 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8113 CurBasePointers.emplace_back(BasePtr, L.VD);
8114 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008115 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008116 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8117 // value MEMBER_OF=FFFF so that the entry is later updated with the
8118 // correct value of MEMBER_OF.
8119 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8120 OMP_MAP_MEMBER_OF);
8121 }
8122 }
8123
8124 // If there is an entry in PartialStruct it means we have a struct with
8125 // individual members mapped. Emit an extra combined entry.
8126 if (PartialStruct.Base.isValid())
8127 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8128 PartialStruct);
8129
8130 // We need to append the results of this capture to what we already have.
8131 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8132 Pointers.append(CurPointers.begin(), CurPointers.end());
8133 Sizes.append(CurSizes.begin(), CurSizes.end());
8134 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008135 }
8136 }
8137
Michael Krused47b9432019-08-05 18:43:21 +00008138 /// Generate all the base pointers, section pointers, sizes and map types for
8139 /// the extracted map clauses of user-defined mapper.
8140 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8141 MapValuesArrayTy &Pointers,
8142 MapValuesArrayTy &Sizes,
8143 MapFlagsArrayTy &Types) const {
8144 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
8145 "Expect a declare mapper directive");
8146 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8147 // We have to process the component lists that relate with the same
8148 // declaration in a single chunk so that we can generate the map flags
8149 // correctly. Therefore, we organize all lists in a map.
8150 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8151
8152 // Helper function to fill the information map for the different supported
8153 // clauses.
8154 auto &&InfoGen = [&Info](
8155 const ValueDecl *D,
8156 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8157 OpenMPMapClauseKind MapType,
8158 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8159 bool ReturnDevicePointer, bool IsImplicit) {
8160 const ValueDecl *VD =
8161 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8162 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8163 IsImplicit);
8164 };
8165
8166 for (const auto *C : CurMapperDir->clauselists()) {
8167 const auto *MC = cast<OMPMapClause>(C);
8168 for (const auto &L : MC->component_lists()) {
8169 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8170 /*ReturnDevicePointer=*/false, MC->isImplicit());
8171 }
8172 }
8173
8174 for (const auto &M : Info) {
8175 // We need to know when we generate information for the first component
8176 // associated with a capture, because the mapping flags depend on it.
8177 bool IsFirstComponentList = true;
8178
8179 // Temporary versions of arrays
8180 MapBaseValuesArrayTy CurBasePointers;
8181 MapValuesArrayTy CurPointers;
8182 MapValuesArrayTy CurSizes;
8183 MapFlagsArrayTy CurTypes;
8184 StructRangeInfoTy PartialStruct;
8185
8186 for (const MapInfo &L : M.second) {
8187 assert(!L.Components.empty() &&
8188 "Not expecting declaration with no component lists.");
8189 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8190 CurBasePointers, CurPointers, CurSizes,
8191 CurTypes, PartialStruct,
8192 IsFirstComponentList, L.IsImplicit);
8193 IsFirstComponentList = false;
8194 }
8195
8196 // If there is an entry in PartialStruct it means we have a struct with
8197 // individual members mapped. Emit an extra combined entry.
8198 if (PartialStruct.Base.isValid())
8199 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8200 PartialStruct);
8201
8202 // We need to append the results of this capture to what we already have.
8203 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8204 Pointers.append(CurPointers.begin(), CurPointers.end());
8205 Sizes.append(CurSizes.begin(), CurSizes.end());
8206 Types.append(CurTypes.begin(), CurTypes.end());
8207 }
8208 }
8209
Alexey Bataev60705422018-10-30 15:50:12 +00008210 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008211 void generateInfoForLambdaCaptures(
8212 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8213 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8214 MapFlagsArrayTy &Types,
8215 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008216 const auto *RD = VD->getType()
8217 .getCanonicalType()
8218 .getNonReferenceType()
8219 ->getAsCXXRecordDecl();
8220 if (!RD || !RD->isLambda())
8221 return;
8222 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8223 LValue VDLVal = CGF.MakeAddrLValue(
8224 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8225 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8226 FieldDecl *ThisCapture = nullptr;
8227 RD->getCaptureFields(Captures, ThisCapture);
8228 if (ThisCapture) {
8229 LValue ThisLVal =
8230 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008231 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
8232 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer());
8233 BasePointers.push_back(ThisLVal.getPointer());
8234 Pointers.push_back(ThisLValVal.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008235 Sizes.push_back(
8236 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8237 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008238 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008239 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8240 }
8241 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008242 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008243 continue;
8244 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008245 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8246 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008247 auto It = Captures.find(VD);
8248 assert(It != Captures.end() && "Found lambda capture without field.");
8249 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008250 if (LC.getCaptureKind() == LCK_ByRef) {
8251 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8252 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8253 BasePointers.push_back(VarLVal.getPointer());
8254 Pointers.push_back(VarLValVal.getPointer());
8255 Sizes.push_back(CGF.Builder.CreateIntCast(
8256 CGF.getTypeSize(
8257 VD->getType().getCanonicalType().getNonReferenceType()),
8258 CGF.Int64Ty, /*isSigned=*/true));
8259 } else {
8260 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
8261 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8262 BasePointers.push_back(VarLVal.getPointer());
8263 Pointers.push_back(VarRVal.getScalarVal());
8264 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8265 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008266 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008267 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8268 }
8269 }
8270
8271 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008272 void adjustMemberOfForLambdaCaptures(
8273 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8274 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8275 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008276 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8277 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008278 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008279 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8280 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008281 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8282 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008283 int TgtIdx = -1;
8284 for (unsigned J = I; J > 0; --J) {
8285 unsigned Idx = J - 1;
8286 if (Pointers[Idx] != BasePtr)
8287 continue;
8288 TgtIdx = Idx;
8289 break;
8290 }
8291 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8292 // All other current entries will be MEMBER_OF the combined entry
8293 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8294 // 0xFFFF in the MEMBER_OF field).
8295 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8296 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8297 }
8298 }
8299
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008300 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008301 /// associated to a given capture.
8302 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008303 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008304 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008305 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008306 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8307 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008308 assert(!Cap->capturesVariableArrayType() &&
8309 "Not expecting to generate map info for a variable array type!");
8310
Samuel Antao6890b092016-07-28 14:25:09 +00008311 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008312 const ValueDecl *VD = Cap->capturesThis()
8313 ? nullptr
8314 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008315
Samuel Antao6890b092016-07-28 14:25:09 +00008316 // If this declaration appears in a is_device_ptr clause we just have to
8317 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008318 // pass its value.
8319 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008320 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008321 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008322 Sizes.push_back(
8323 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8324 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008325 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008326 return;
8327 }
8328
Alexey Bataeve82445f2018-09-20 13:54:02 +00008329 using MapData =
8330 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008331 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008332 SmallVector<MapData, 4> DeclComponentLists;
Michael Krused47b9432019-08-05 18:43:21 +00008333 assert(CurDir.is<const OMPExecutableDirective *>() &&
8334 "Expect a executable directive");
8335 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8336 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008337 for (const auto &L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008338 assert(L.first == VD &&
8339 "We got information for the wrong declaration??");
8340 assert(!L.second.empty() &&
8341 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008342 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008343 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008344 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008345 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008346 }
8347
8348 // Find overlapping elements (including the offset from the base element).
8349 llvm::SmallDenseMap<
8350 const MapData *,
8351 llvm::SmallVector<
8352 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8353 4>
8354 OverlappedData;
8355 size_t Count = 0;
8356 for (const MapData &L : DeclComponentLists) {
8357 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8358 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008359 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008360 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008361 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008362 ++Count;
8363 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8364 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008365 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008366 auto CI = Components.rbegin();
8367 auto CE = Components.rend();
8368 auto SI = Components1.rbegin();
8369 auto SE = Components1.rend();
8370 for (; CI != CE && SI != SE; ++CI, ++SI) {
8371 if (CI->getAssociatedExpression()->getStmtClass() !=
8372 SI->getAssociatedExpression()->getStmtClass())
8373 break;
8374 // Are we dealing with different variables/fields?
8375 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8376 break;
8377 }
8378 // Found overlapping if, at least for one component, reached the head of
8379 // the components list.
8380 if (CI == CE || SI == SE) {
8381 assert((CI != CE || SI != SE) &&
8382 "Unexpected full match of the mapping components.");
8383 const MapData &BaseData = CI == CE ? L : L1;
8384 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8385 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008386 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8387 OverlappedElements.getSecond().push_back(SubData);
8388 }
8389 }
8390 }
8391 // Sort the overlapped elements for each item.
8392 llvm::SmallVector<const FieldDecl *, 4> Layout;
8393 if (!OverlappedData.empty()) {
8394 if (const auto *CRD =
8395 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8396 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8397 else {
8398 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8399 Layout.append(RD->field_begin(), RD->field_end());
8400 }
8401 }
8402 for (auto &Pair : OverlappedData) {
8403 llvm::sort(
8404 Pair.getSecond(),
8405 [&Layout](
8406 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8407 OMPClauseMappableExprCommon::MappableExprComponentListRef
8408 Second) {
8409 auto CI = First.rbegin();
8410 auto CE = First.rend();
8411 auto SI = Second.rbegin();
8412 auto SE = Second.rend();
8413 for (; CI != CE && SI != SE; ++CI, ++SI) {
8414 if (CI->getAssociatedExpression()->getStmtClass() !=
8415 SI->getAssociatedExpression()->getStmtClass())
8416 break;
8417 // Are we dealing with different variables/fields?
8418 if (CI->getAssociatedDeclaration() !=
8419 SI->getAssociatedDeclaration())
8420 break;
8421 }
Richard Trieu5061e832018-09-21 21:20:33 +00008422
8423 // Lists contain the same elements.
8424 if (CI == CE && SI == SE)
8425 return false;
8426
8427 // List with less elements is less than list with more elements.
8428 if (CI == CE || SI == SE)
8429 return CI == CE;
8430
Alexey Bataeve82445f2018-09-20 13:54:02 +00008431 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8432 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8433 if (FD1->getParent() == FD2->getParent())
8434 return FD1->getFieldIndex() < FD2->getFieldIndex();
8435 const auto It =
8436 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8437 return FD == FD1 || FD == FD2;
8438 });
8439 return *It == FD1;
8440 });
8441 }
8442
8443 // Associated with a capture, because the mapping flags depend on it.
8444 // Go through all of the elements with the overlapped elements.
8445 for (const auto &Pair : OverlappedData) {
8446 const MapData &L = *Pair.getFirst();
8447 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8448 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008449 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008450 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008451 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008452 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8453 OverlappedComponents = Pair.getSecond();
8454 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008455 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008456 BasePointers, Pointers, Sizes, Types,
8457 PartialStruct, IsFirstComponentList,
8458 IsImplicit, OverlappedComponents);
8459 }
8460 // Go through other elements without overlapped elements.
8461 bool IsFirstComponentList = OverlappedData.empty();
8462 for (const MapData &L : DeclComponentLists) {
8463 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8464 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008465 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008466 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008467 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008468 auto It = OverlappedData.find(&L);
8469 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008470 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008471 BasePointers, Pointers, Sizes, Types,
8472 PartialStruct, IsFirstComponentList,
8473 IsImplicit);
8474 IsFirstComponentList = false;
8475 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008476 }
Samuel Antao86ace552016-04-27 22:40:57 +00008477
Alexey Bataevb3638132018-07-19 16:34:13 +00008478 /// Generate the base pointers, section pointers, sizes and map types
8479 /// associated with the declare target link variables.
8480 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8481 MapValuesArrayTy &Pointers,
8482 MapValuesArrayTy &Sizes,
8483 MapFlagsArrayTy &Types) const {
Michael Krused47b9432019-08-05 18:43:21 +00008484 assert(CurDir.is<const OMPExecutableDirective *>() &&
8485 "Expect a executable directive");
8486 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
Alexey Bataevb3638132018-07-19 16:34:13 +00008487 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008488 // but "declare target link" global variables.
Michael Krused47b9432019-08-05 18:43:21 +00008489 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008490 for (const auto &L : C->component_lists()) {
8491 if (!L.first)
8492 continue;
8493 const auto *VD = dyn_cast<VarDecl>(L.first);
8494 if (!VD)
8495 continue;
8496 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008497 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008498 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8499 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008500 continue;
8501 StructRangeInfoTy PartialStruct;
8502 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008503 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008504 Pointers, Sizes, Types, PartialStruct,
8505 /*IsFirstComponentList=*/true, C->isImplicit());
8506 assert(!PartialStruct.Base.isValid() &&
8507 "No partial structs for declare target link expected.");
8508 }
8509 }
Samuel Antao86ace552016-04-27 22:40:57 +00008510 }
Samuel Antaod486f842016-05-26 16:53:38 +00008511
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008512 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008513 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008514 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8515 const FieldDecl &RI, llvm::Value *CV,
8516 MapBaseValuesArrayTy &CurBasePointers,
8517 MapValuesArrayTy &CurPointers,
8518 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008519 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008520 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008521 // Do the default mapping.
8522 if (CI.capturesThis()) {
8523 CurBasePointers.push_back(CV);
8524 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008525 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008526 CurSizes.push_back(
8527 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8528 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008529 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008530 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008531 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008532 CurBasePointers.push_back(CV);
8533 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008534 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008535 // We have to signal to the runtime captures passed by value that are
8536 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008537 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008538 CurSizes.push_back(CGF.Builder.CreateIntCast(
8539 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008540 } else {
8541 // Pointers are implicitly mapped with a zero size and no flags
8542 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008543 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008544 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008545 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008546 const VarDecl *VD = CI.getCapturedVar();
8547 auto I = FirstPrivateDecls.find(VD);
8548 if (I != FirstPrivateDecls.end())
8549 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008550 } else {
8551 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008552 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008553 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008554 CurSizes.push_back(CGF.Builder.CreateIntCast(
8555 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008556 // The default map type for a scalar/complex type is 'to' because by
8557 // default the value doesn't have to be retrieved. For an aggregate
8558 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008559 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008560 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008561 auto I = FirstPrivateDecls.find(VD);
8562 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008563 VD->getType().isConstant(CGF.getContext())) {
8564 llvm::Constant *Addr =
8565 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8566 // Copy the value of the original variable to the new global copy.
8567 CGF.Builder.CreateMemCpy(
8568 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(),
8569 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008570 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008571 // Use new global variable as the base pointers.
8572 CurBasePointers.push_back(Addr);
8573 CurPointers.push_back(Addr);
8574 } else {
8575 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008576 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008577 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8578 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8579 AlignmentSource::Decl));
8580 CurPointers.push_back(PtrAddr.getPointer());
8581 } else {
8582 CurPointers.push_back(CV);
8583 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008584 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008585 if (I != FirstPrivateDecls.end())
8586 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008587 }
George Rokos065755d2017-11-07 18:27:04 +00008588 // Every default map produces a single argument which is a target parameter.
8589 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008590
8591 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008592 if (IsImplicit)
8593 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008594 }
Samuel Antao86ace552016-04-27 22:40:57 +00008595};
Samuel Antaodf158d52016-04-27 22:58:19 +00008596} // anonymous namespace
8597
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008598/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008599/// offloading runtime library. If there is no map or capture information,
8600/// return nullptr by reference.
8601static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008602emitOffloadingArrays(CodeGenFunction &CGF,
8603 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008604 MappableExprsHandler::MapValuesArrayTy &Pointers,
8605 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008606 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8607 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008608 CodeGenModule &CGM = CGF.CGM;
8609 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008610
Samuel Antaocc10b852016-07-28 14:23:26 +00008611 // Reset the array information.
8612 Info.clearArrayInfo();
8613 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008614
Samuel Antaocc10b852016-07-28 14:23:26 +00008615 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008616 // Detect if we have any capture size requiring runtime evaluation of the
8617 // size so that a constant array could be eventually used.
8618 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008619 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008620 if (!isa<llvm::Constant>(S)) {
8621 hasRuntimeEvaluationCaptureSize = true;
8622 break;
8623 }
8624
Samuel Antaocc10b852016-07-28 14:23:26 +00008625 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Samuel Antaodf158d52016-04-27 22:58:19 +00008626 QualType PointerArrayType =
8627 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
8628 /*IndexTypeQuals=*/0);
8629
Samuel Antaocc10b852016-07-28 14:23:26 +00008630 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008631 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008632 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008633 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8634
8635 // If we don't have any VLA types or other types that require runtime
8636 // evaluation, we can use a constant array for the map sizes, otherwise we
8637 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008638 QualType Int64Ty =
8639 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008640 if (hasRuntimeEvaluationCaptureSize) {
Alexey Bataeva90fc662019-06-25 16:00:43 +00008641 QualType SizeArrayType =
8642 Ctx.getConstantArrayType(Int64Ty, PointerNumAP, ArrayType::Normal,
8643 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008644 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008645 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8646 } else {
8647 // We expect all the sizes to be constant, so we collect them to create
8648 // a constant array.
8649 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008650 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008651 ConstSizes.push_back(cast<llvm::Constant>(S));
8652
8653 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008654 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008655 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008656 auto *SizesArrayGbl = new llvm::GlobalVariable(
8657 CGM.getModule(), SizesArrayInit->getType(),
8658 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008659 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008660 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008661 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008662 }
8663
8664 // The map types are always constant so we don't need to generate code to
8665 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008666 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8667 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008668 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008669 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008670 std::string MaptypesName =
8671 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008672 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8673 CGM.getModule(), MapTypesArrayInit->getType(),
8674 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008675 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008676 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008677 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008678
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008679 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8680 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008681 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008682 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008683 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008684 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8685 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008686 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8687 CGF.Builder.CreateStore(BPVal, BPAddr);
8688
Samuel Antaocc10b852016-07-28 14:23:26 +00008689 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008690 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008691 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008692
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008693 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008694 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008695 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008696 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008697 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8698 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008699 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8700 CGF.Builder.CreateStore(PVal, PAddr);
8701
8702 if (hasRuntimeEvaluationCaptureSize) {
8703 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008704 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008705 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008706 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008707 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008708 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008709 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008710 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008711 SAddr);
8712 }
8713 }
8714 }
8715}
Michael Krused47b9432019-08-05 18:43:21 +00008716
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008717/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008718/// arrays of pointers, sizes and map types.
8719static void emitOffloadingArraysArgument(
8720 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8721 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008722 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008723 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008724 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008725 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008726 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8727 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008728 /*Idx0=*/0, /*Idx1=*/0);
8729 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008730 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8731 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008732 /*Idx0=*/0,
8733 /*Idx1=*/0);
8734 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008735 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008736 /*Idx0=*/0, /*Idx1=*/0);
8737 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008738 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008739 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008740 /*Idx0=*/0,
8741 /*Idx1=*/0);
8742 } else {
8743 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8744 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008745 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008746 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008747 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008748 }
Samuel Antao86ace552016-04-27 22:40:57 +00008749}
8750
Alexey Bataev7bb33532019-01-07 21:30:43 +00008751/// Check for inner distribute directive.
8752static const OMPExecutableDirective *
8753getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8754 const auto *CS = D.getInnermostCapturedStmt();
8755 const auto *Body =
8756 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008757 const Stmt *ChildStmt =
8758 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008759
Alexey Bataev5c427362019-04-10 19:11:33 +00008760 if (const auto *NestedDir =
8761 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008762 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8763 switch (D.getDirectiveKind()) {
8764 case OMPD_target:
8765 if (isOpenMPDistributeDirective(DKind))
8766 return NestedDir;
8767 if (DKind == OMPD_teams) {
8768 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8769 /*IgnoreCaptured=*/true);
8770 if (!Body)
8771 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008772 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8773 if (const auto *NND =
8774 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008775 DKind = NND->getDirectiveKind();
8776 if (isOpenMPDistributeDirective(DKind))
8777 return NND;
8778 }
8779 }
8780 return nullptr;
8781 case OMPD_target_teams:
8782 if (isOpenMPDistributeDirective(DKind))
8783 return NestedDir;
8784 return nullptr;
8785 case OMPD_target_parallel:
8786 case OMPD_target_simd:
8787 case OMPD_target_parallel_for:
8788 case OMPD_target_parallel_for_simd:
8789 return nullptr;
8790 case OMPD_target_teams_distribute:
8791 case OMPD_target_teams_distribute_simd:
8792 case OMPD_target_teams_distribute_parallel_for:
8793 case OMPD_target_teams_distribute_parallel_for_simd:
8794 case OMPD_parallel:
8795 case OMPD_for:
8796 case OMPD_parallel_for:
8797 case OMPD_parallel_sections:
8798 case OMPD_for_simd:
8799 case OMPD_parallel_for_simd:
8800 case OMPD_cancel:
8801 case OMPD_cancellation_point:
8802 case OMPD_ordered:
8803 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008804 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008805 case OMPD_task:
8806 case OMPD_simd:
8807 case OMPD_sections:
8808 case OMPD_section:
8809 case OMPD_single:
8810 case OMPD_master:
8811 case OMPD_critical:
8812 case OMPD_taskyield:
8813 case OMPD_barrier:
8814 case OMPD_taskwait:
8815 case OMPD_taskgroup:
8816 case OMPD_atomic:
8817 case OMPD_flush:
8818 case OMPD_teams:
8819 case OMPD_target_data:
8820 case OMPD_target_exit_data:
8821 case OMPD_target_enter_data:
8822 case OMPD_distribute:
8823 case OMPD_distribute_simd:
8824 case OMPD_distribute_parallel_for:
8825 case OMPD_distribute_parallel_for_simd:
8826 case OMPD_teams_distribute:
8827 case OMPD_teams_distribute_simd:
8828 case OMPD_teams_distribute_parallel_for:
8829 case OMPD_teams_distribute_parallel_for_simd:
8830 case OMPD_target_update:
8831 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00008832 case OMPD_declare_variant:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008833 case OMPD_declare_target:
8834 case OMPD_end_declare_target:
8835 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008836 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008837 case OMPD_taskloop:
8838 case OMPD_taskloop_simd:
8839 case OMPD_requires:
8840 case OMPD_unknown:
8841 llvm_unreachable("Unexpected directive.");
8842 }
8843 }
8844
8845 return nullptr;
8846}
8847
Michael Krused47b9432019-08-05 18:43:21 +00008848/// Emit the user-defined mapper function. The code generation follows the
8849/// pattern in the example below.
8850/// \code
8851/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8852/// void *base, void *begin,
8853/// int64_t size, int64_t type) {
8854/// // Allocate space for an array section first.
8855/// if (size > 1 && !maptype.IsDelete)
8856/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8857/// size*sizeof(Ty), clearToFrom(type));
8858/// // Map members.
8859/// for (unsigned i = 0; i < size; i++) {
8860/// // For each component specified by this mapper:
8861/// for (auto c : all_components) {
8862/// if (c.hasMapper())
8863/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
8864/// c.arg_type);
8865/// else
8866/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
8867/// c.arg_begin, c.arg_size, c.arg_type);
8868/// }
8869/// }
8870/// // Delete the array section.
8871/// if (size > 1 && maptype.IsDelete)
8872/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8873/// size*sizeof(Ty), clearToFrom(type));
8874/// }
8875/// \endcode
8876void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
8877 CodeGenFunction *CGF) {
8878 if (UDMMap.count(D) > 0)
8879 return;
8880 ASTContext &C = CGM.getContext();
8881 QualType Ty = D->getType();
8882 QualType PtrTy = C.getPointerType(Ty).withRestrict();
8883 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
8884 auto *MapperVarDecl =
8885 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
8886 SourceLocation Loc = D->getLocation();
8887 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
8888
8889 // Prepare mapper function arguments and attributes.
8890 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8891 C.VoidPtrTy, ImplicitParamDecl::Other);
8892 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
8893 ImplicitParamDecl::Other);
8894 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8895 C.VoidPtrTy, ImplicitParamDecl::Other);
8896 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8897 ImplicitParamDecl::Other);
8898 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8899 ImplicitParamDecl::Other);
8900 FunctionArgList Args;
8901 Args.push_back(&HandleArg);
8902 Args.push_back(&BaseArg);
8903 Args.push_back(&BeginArg);
8904 Args.push_back(&SizeArg);
8905 Args.push_back(&TypeArg);
8906 const CGFunctionInfo &FnInfo =
8907 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
8908 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
8909 SmallString<64> TyStr;
8910 llvm::raw_svector_ostream Out(TyStr);
8911 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
8912 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
8913 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
8914 Name, &CGM.getModule());
8915 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
8916 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
8917 // Start the mapper function code generation.
8918 CodeGenFunction MapperCGF(CGM);
8919 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
8920 // Compute the starting and end addreses of array elements.
8921 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
8922 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
8923 C.getPointerType(Int64Ty), Loc);
8924 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
8925 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
8926 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
8927 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
8928 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
8929 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
8930 C.getPointerType(Int64Ty), Loc);
8931 // Prepare common arguments for array initiation and deletion.
8932 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
8933 MapperCGF.GetAddrOfLocalVar(&HandleArg),
8934 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8935 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
8936 MapperCGF.GetAddrOfLocalVar(&BaseArg),
8937 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8938 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
8939 MapperCGF.GetAddrOfLocalVar(&BeginArg),
8940 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8941
8942 // Emit array initiation if this is an array section and \p MapType indicates
8943 // that memory allocation is required.
8944 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
8945 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
8946 ElementSize, HeadBB, /*IsInit=*/true);
8947
8948 // Emit a for loop to iterate through SizeArg of elements and map all of them.
8949
8950 // Emit the loop header block.
8951 MapperCGF.EmitBlock(HeadBB);
8952 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
8953 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
8954 // Evaluate whether the initial condition is satisfied.
8955 llvm::Value *IsEmpty =
8956 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
8957 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
8958 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
8959
8960 // Emit the loop body block.
8961 MapperCGF.EmitBlock(BodyBB);
8962 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
8963 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
8964 PtrPHI->addIncoming(PtrBegin, EntryBB);
8965 Address PtrCurrent =
8966 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
8967 .getAlignment()
8968 .alignmentOfArrayElement(ElementSize));
8969 // Privatize the declared variable of mapper to be the current array element.
8970 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
8971 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
8972 return MapperCGF
8973 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
8974 .getAddress();
8975 });
8976 (void)Scope.Privatize();
8977
8978 // Get map clause information. Fill up the arrays with all mapped variables.
8979 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8980 MappableExprsHandler::MapValuesArrayTy Pointers;
8981 MappableExprsHandler::MapValuesArrayTy Sizes;
8982 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8983 MappableExprsHandler MEHandler(*D, MapperCGF);
8984 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
8985
8986 // Call the runtime API __tgt_mapper_num_components to get the number of
8987 // pre-existing components.
8988 llvm::Value *OffloadingArgs[] = {Handle};
8989 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
8990 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
8991 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
8992 PreviousSize,
8993 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
8994
8995 // Fill up the runtime mapper handle for all components.
8996 for (unsigned I = 0; I < BasePointers.size(); ++I) {
8997 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
8998 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8999 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
9000 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9001 llvm::Value *CurSizeArg = Sizes[I];
9002
9003 // Extract the MEMBER_OF field from the map type.
9004 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
9005 MapperCGF.EmitBlock(MemberBB);
9006 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
9007 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
9008 OriMapType,
9009 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
9010 llvm::BasicBlock *MemberCombineBB =
9011 MapperCGF.createBasicBlock("omp.member.combine");
9012 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
9013 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
9014 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
9015 // Add the number of pre-existing components to the MEMBER_OF field if it
9016 // is valid.
9017 MapperCGF.EmitBlock(MemberCombineBB);
9018 llvm::Value *CombinedMember =
9019 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
9020 // Do nothing if it is not a member of previous components.
9021 MapperCGF.EmitBlock(TypeBB);
9022 llvm::PHINode *MemberMapType =
9023 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
9024 MemberMapType->addIncoming(OriMapType, MemberBB);
9025 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
9026
9027 // Combine the map type inherited from user-defined mapper with that
9028 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
9029 // bits of the \a MapType, which is the input argument of the mapper
9030 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
9031 // bits of MemberMapType.
9032 // [OpenMP 5.0], 1.2.6. map-type decay.
9033 // | alloc | to | from | tofrom | release | delete
9034 // ----------------------------------------------------------
9035 // alloc | alloc | alloc | alloc | alloc | release | delete
9036 // to | alloc | to | alloc | to | release | delete
9037 // from | alloc | alloc | from | from | release | delete
9038 // tofrom | alloc | to | from | tofrom | release | delete
9039 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9040 MapType,
9041 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9042 MappableExprsHandler::OMP_MAP_FROM));
9043 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9044 llvm::BasicBlock *AllocElseBB =
9045 MapperCGF.createBasicBlock("omp.type.alloc.else");
9046 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9047 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9048 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9049 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9050 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9051 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9052 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9053 MapperCGF.EmitBlock(AllocBB);
9054 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9055 MemberMapType,
9056 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9057 MappableExprsHandler::OMP_MAP_FROM)));
9058 MapperCGF.Builder.CreateBr(EndBB);
9059 MapperCGF.EmitBlock(AllocElseBB);
9060 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9061 LeftToFrom,
9062 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9063 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9064 // In case of to, clear OMP_MAP_FROM.
9065 MapperCGF.EmitBlock(ToBB);
9066 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9067 MemberMapType,
9068 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9069 MapperCGF.Builder.CreateBr(EndBB);
9070 MapperCGF.EmitBlock(ToElseBB);
9071 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9072 LeftToFrom,
9073 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9074 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9075 // In case of from, clear OMP_MAP_TO.
9076 MapperCGF.EmitBlock(FromBB);
9077 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9078 MemberMapType,
9079 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9080 // In case of tofrom, do nothing.
9081 MapperCGF.EmitBlock(EndBB);
9082 llvm::PHINode *CurMapType =
9083 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9084 CurMapType->addIncoming(AllocMapType, AllocBB);
9085 CurMapType->addIncoming(ToMapType, ToBB);
9086 CurMapType->addIncoming(FromMapType, FromBB);
9087 CurMapType->addIncoming(MemberMapType, ToElseBB);
9088
9089 // TODO: call the corresponding mapper function if a user-defined mapper is
9090 // associated with this map clause.
9091 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9092 // data structure.
9093 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9094 CurSizeArg, CurMapType};
9095 MapperCGF.EmitRuntimeCall(
9096 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9097 OffloadingArgs);
9098 }
9099
9100 // Update the pointer to point to the next element that needs to be mapped,
9101 // and check whether we have mapped all elements.
9102 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9103 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9104 PtrPHI->addIncoming(PtrNext, BodyBB);
9105 llvm::Value *IsDone =
9106 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9107 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9108 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9109
9110 MapperCGF.EmitBlock(ExitBB);
9111 // Emit array deletion if this is an array section and \p MapType indicates
9112 // that deletion is required.
9113 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9114 ElementSize, DoneBB, /*IsInit=*/false);
9115
9116 // Emit the function exit block.
9117 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9118 MapperCGF.FinishFunction();
9119 UDMMap.try_emplace(D, Fn);
9120 if (CGF) {
9121 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9122 Decls.second.push_back(D);
9123 }
9124}
9125
9126/// Emit the array initialization or deletion portion for user-defined mapper
9127/// code generation. First, it evaluates whether an array section is mapped and
9128/// whether the \a MapType instructs to delete this section. If \a IsInit is
9129/// true, and \a MapType indicates to not delete this array, array
9130/// initialization code is generated. If \a IsInit is false, and \a MapType
9131/// indicates to not this array, array deletion code is generated.
9132void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9133 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9134 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9135 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9136 StringRef Prefix = IsInit ? ".init" : ".del";
9137
9138 // Evaluate if this is an array section.
9139 llvm::BasicBlock *IsDeleteBB =
9140 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete");
9141 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix);
9142 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9143 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9144 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9145
9146 // Evaluate if we are going to delete this section.
9147 MapperCGF.EmitBlock(IsDeleteBB);
9148 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9149 MapType,
9150 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9151 llvm::Value *DeleteCond;
9152 if (IsInit) {
9153 DeleteCond = MapperCGF.Builder.CreateIsNull(
9154 DeleteBit, "omp.array" + Prefix + ".delete");
9155 } else {
9156 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9157 DeleteBit, "omp.array" + Prefix + ".delete");
9158 }
9159 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9160
9161 MapperCGF.EmitBlock(BodyBB);
9162 // Get the array size by multiplying element size and element number (i.e., \p
9163 // Size).
9164 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9165 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9166 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9167 // memory allocation/deletion purpose only.
9168 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9169 MapType,
9170 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9171 MappableExprsHandler::OMP_MAP_FROM)));
9172 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9173 // data structure.
9174 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9175 MapperCGF.EmitRuntimeCall(
9176 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9177}
9178
Alexey Bataev7bb33532019-01-07 21:30:43 +00009179void CGOpenMPRuntime::emitTargetNumIterationsCall(
Alexey Bataevec7946e2019-09-23 14:06:51 +00009180 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9181 llvm::Value *DeviceID,
9182 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9183 const OMPLoopDirective &D)>
9184 SizeEmitter) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00009185 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9186 const OMPExecutableDirective *TD = &D;
9187 // Get nested teams distribute kind directive, if any.
9188 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9189 TD = getNestedDistributeDirective(CGM.getContext(), D);
9190 if (!TD)
9191 return;
9192 const auto *LD = cast<OMPLoopDirective>(TD);
Alexey Bataevec7946e2019-09-23 14:06:51 +00009193 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
Alexey Bataev7bb33532019-01-07 21:30:43 +00009194 PrePostActionTy &) {
Alexey Bataevec7946e2019-09-23 14:06:51 +00009195 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9196 llvm::Value *Args[] = {DeviceID, NumIterations};
9197 CGF.EmitRuntimeCall(
9198 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9199 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00009200 };
9201 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9202}
9203
Alexey Bataevec7946e2019-09-23 14:06:51 +00009204void CGOpenMPRuntime::emitTargetCall(
9205 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9206 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9207 const Expr *Device,
9208 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9209 const OMPLoopDirective &D)>
9210 SizeEmitter) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00009211 if (!CGF.HaveInsertPoint())
9212 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00009213
Samuel Antaoee8fb302016-01-06 13:42:12 +00009214 assert(OutlinedFn && "Invalid outlined function!");
9215
Alexey Bataev8451efa2018-01-15 19:06:12 +00009216 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9217 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00009218 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009219 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9220 PrePostActionTy &) {
9221 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9222 };
9223 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00009224
Alexey Bataev8451efa2018-01-15 19:06:12 +00009225 CodeGenFunction::OMPTargetDataInfo InputInfo;
9226 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00009227 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009228 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
Alexey Bataevec7946e2019-09-23 14:06:51 +00009229 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9230 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009231 // On top of the arrays that were filled up, the target offloading call
9232 // takes as arguments the device id as well as the host pointer. The host
9233 // pointer is used by the runtime library to identify the current target
9234 // region, so it only has to be unique and not necessarily point to
9235 // anything. It could be the pointer to the outlined function that
9236 // implements the target region, but we aren't using that so that the
9237 // compiler doesn't need to keep that, and could therefore inline the host
9238 // function if proven worthwhile during optimization.
9239
Samuel Antaoee8fb302016-01-06 13:42:12 +00009240 // From this point on, we need to have an ID of the target region defined.
9241 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00009242
9243 // Emit device ID if any.
9244 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00009245 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009246 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009247 CGF.Int64Ty, /*isSigned=*/true);
9248 } else {
9249 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9250 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009251
Samuel Antaodf158d52016-04-27 22:58:19 +00009252 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009253 llvm::Value *PointerNum =
9254 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00009255
Samuel Antaob68e2db2016-03-03 16:20:23 +00009256 // Return value of the runtime offloading call.
9257 llvm::Value *Return;
9258
Alexey Bataev5c427362019-04-10 19:11:33 +00009259 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9260 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009261
Alexey Bataevec7946e2019-09-23 14:06:51 +00009262 // Emit tripcount for the target loop-based directive.
9263 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9264
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009265 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009266 // The target region is an outlined function launched by the runtime
9267 // via calls __tgt_target() or __tgt_target_teams().
9268 //
9269 // __tgt_target() launches a target region with one team and one thread,
9270 // executing a serial region. This master thread may in turn launch
9271 // more threads within its team upon encountering a parallel region,
9272 // however, no additional teams can be launched on the device.
9273 //
9274 // __tgt_target_teams() launches a target region with one or more teams,
9275 // each with one or more threads. This call is required for target
9276 // constructs such as:
9277 // 'target teams'
9278 // 'target' / 'teams'
9279 // 'target teams distribute parallel for'
9280 // 'target parallel'
9281 // and so on.
9282 //
9283 // Note that on the host and CPU targets, the runtime implementation of
9284 // these calls simply call the outlined function without forking threads.
9285 // The outlined functions themselves have runtime calls to
9286 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9287 // the compiler in emitTeamsCall() and emitParallelCall().
9288 //
9289 // In contrast, on the NVPTX target, the implementation of
9290 // __tgt_target_teams() launches a GPU kernel with the requested number
9291 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00009292 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009293 // If we have NumTeams defined this means that we have an enclosed teams
9294 // region. Therefore we also expect to have NumThreads defined. These two
9295 // values should be defined in the presence of a teams directive,
9296 // regardless of having any clauses associated. If the user is using teams
9297 // but no clauses, these two values will be the default that should be
9298 // passed to the runtime library - a 32-bit integer with the value zero.
9299 assert(NumThreads && "Thread limit expression should be available along "
9300 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00009301 llvm::Value *OffloadingArgs[] = {DeviceID,
9302 OutlinedFnID,
9303 PointerNum,
9304 InputInfo.BasePointersArray.getPointer(),
9305 InputInfo.PointersArray.getPointer(),
9306 InputInfo.SizesArray.getPointer(),
9307 MapTypesArray,
9308 NumTeams,
9309 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00009310 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009311 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9312 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009313 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009314 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009315 llvm::Value *OffloadingArgs[] = {DeviceID,
9316 OutlinedFnID,
9317 PointerNum,
9318 InputInfo.BasePointersArray.getPointer(),
9319 InputInfo.PointersArray.getPointer(),
9320 InputInfo.SizesArray.getPointer(),
9321 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009322 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009323 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9324 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009325 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009326 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009327
Alexey Bataev2a007e02017-10-02 14:20:58 +00009328 // Check the error code and execute the host version if required.
9329 llvm::BasicBlock *OffloadFailedBlock =
9330 CGF.createBasicBlock("omp_offload.failed");
9331 llvm::BasicBlock *OffloadContBlock =
9332 CGF.createBasicBlock("omp_offload.cont");
9333 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9334 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9335
9336 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009337 if (RequiresOuterTask) {
9338 CapturedVars.clear();
9339 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9340 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009341 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00009342 CGF.EmitBranch(OffloadContBlock);
9343
9344 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00009345 };
9346
Samuel Antaoee8fb302016-01-06 13:42:12 +00009347 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009348 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9349 RequiresOuterTask](CodeGenFunction &CGF,
9350 PrePostActionTy &) {
9351 if (RequiresOuterTask) {
9352 CapturedVars.clear();
9353 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9354 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009355 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009356 };
9357
9358 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9359 &CapturedVars, RequiresOuterTask,
9360 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9361 // Fill up the arrays with all the captured variables.
9362 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9363 MappableExprsHandler::MapValuesArrayTy Pointers;
9364 MappableExprsHandler::MapValuesArrayTy Sizes;
9365 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9366
Alexey Bataev8451efa2018-01-15 19:06:12 +00009367 // Get mappable expression information.
9368 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00009369 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009370
9371 auto RI = CS.getCapturedRecordDecl()->field_begin();
9372 auto CV = CapturedVars.begin();
9373 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9374 CE = CS.capture_end();
9375 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00009376 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9377 MappableExprsHandler::MapValuesArrayTy CurPointers;
9378 MappableExprsHandler::MapValuesArrayTy CurSizes;
9379 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9380 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009381
9382 // VLA sizes are passed to the outlined region by copy and do not have map
9383 // information associated.
9384 if (CI->capturesVariableArrayType()) {
9385 CurBasePointers.push_back(*CV);
9386 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00009387 CurSizes.push_back(CGF.Builder.CreateIntCast(
9388 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00009389 // Copy to the device as an argument. No need to retrieve it.
9390 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00009391 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9392 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009393 } else {
9394 // If we have any information in the map clause, we use it, otherwise we
9395 // just do a default mapping.
9396 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00009397 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009398 if (CurBasePointers.empty())
9399 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9400 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00009401 // Generate correct mapping for variables captured by reference in
9402 // lambdas.
9403 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00009404 MEHandler.generateInfoForLambdaCaptures(
9405 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9406 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009407 }
9408 // We expect to have at least an element of information for this capture.
9409 assert(!CurBasePointers.empty() &&
9410 "Non-existing map pointer for capture!");
9411 assert(CurBasePointers.size() == CurPointers.size() &&
9412 CurBasePointers.size() == CurSizes.size() &&
9413 CurBasePointers.size() == CurMapTypes.size() &&
9414 "Inconsistent map information sizes!");
9415
Alexey Bataevb3638132018-07-19 16:34:13 +00009416 // If there is an entry in PartialStruct it means we have a struct with
9417 // individual members mapped. Emit an extra combined entry.
9418 if (PartialStruct.Base.isValid())
9419 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9420 CurMapTypes, PartialStruct);
9421
Alexey Bataev8451efa2018-01-15 19:06:12 +00009422 // We need to append the results of this capture to what we already have.
9423 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9424 Pointers.append(CurPointers.begin(), CurPointers.end());
9425 Sizes.append(CurSizes.begin(), CurSizes.end());
9426 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9427 }
Alexey Bataev60705422018-10-30 15:50:12 +00009428 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00009429 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9430 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00009431 // Map other list items in the map clause which are not captured variables
9432 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00009433 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9434 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009435
9436 TargetDataInfo Info;
9437 // Fill up the arrays and create the arguments.
9438 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9439 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9440 Info.PointersArray, Info.SizesArray,
9441 Info.MapTypesArray, Info);
9442 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9443 InputInfo.BasePointersArray =
9444 Address(Info.BasePointersArray, CGM.getPointerAlign());
9445 InputInfo.PointersArray =
9446 Address(Info.PointersArray, CGM.getPointerAlign());
9447 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9448 MapTypesArray = Info.MapTypesArray;
9449 if (RequiresOuterTask)
9450 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9451 else
9452 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9453 };
9454
9455 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9456 CodeGenFunction &CGF, PrePostActionTy &) {
9457 if (RequiresOuterTask) {
9458 CodeGenFunction::OMPTargetDataInfo InputInfo;
9459 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9460 } else {
9461 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9462 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009463 };
9464
9465 // If we have a target function ID it means that we need to support
9466 // offloading, otherwise, just execute on the host. We need to execute on host
9467 // regardless of the conditional in the if clause if, e.g., the user do not
9468 // specify target triples.
9469 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009470 if (IfCond) {
9471 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
9472 } else {
9473 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009474 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009475 }
9476 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009477 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009478 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009479 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009480}
Samuel Antaoee8fb302016-01-06 13:42:12 +00009481
9482void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9483 StringRef ParentName) {
9484 if (!S)
9485 return;
9486
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009487 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009488 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009489 isa<OMPExecutableDirective>(S) &&
9490 isOpenMPTargetExecutionDirective(
9491 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009492
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009493 if (RequiresDeviceCodegen) {
9494 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009495 unsigned DeviceID;
9496 unsigned FileID;
9497 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009498 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009499 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009500
9501 // Is this a target region that should not be emitted as an entry point? If
9502 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009503 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9504 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009505 return;
9506
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009507 switch (E.getDirectiveKind()) {
9508 case OMPD_target:
9509 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9510 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009511 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009512 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009513 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009514 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009515 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009516 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009517 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009518 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009519 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009520 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009521 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009522 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009523 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009524 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009525 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009526 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009527 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009528 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009529 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009530 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009531 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009532 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009533 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009534 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009535 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009536 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009537 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009538 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009539 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009540 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009541 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9542 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009543 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009544 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009545 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009546 CodeGenFunction::
9547 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9548 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009549 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009550 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009551 case OMPD_parallel:
9552 case OMPD_for:
9553 case OMPD_parallel_for:
9554 case OMPD_parallel_sections:
9555 case OMPD_for_simd:
9556 case OMPD_parallel_for_simd:
9557 case OMPD_cancel:
9558 case OMPD_cancellation_point:
9559 case OMPD_ordered:
9560 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009561 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009562 case OMPD_task:
9563 case OMPD_simd:
9564 case OMPD_sections:
9565 case OMPD_section:
9566 case OMPD_single:
9567 case OMPD_master:
9568 case OMPD_critical:
9569 case OMPD_taskyield:
9570 case OMPD_barrier:
9571 case OMPD_taskwait:
9572 case OMPD_taskgroup:
9573 case OMPD_atomic:
9574 case OMPD_flush:
9575 case OMPD_teams:
9576 case OMPD_target_data:
9577 case OMPD_target_exit_data:
9578 case OMPD_target_enter_data:
9579 case OMPD_distribute:
9580 case OMPD_distribute_simd:
9581 case OMPD_distribute_parallel_for:
9582 case OMPD_distribute_parallel_for_simd:
9583 case OMPD_teams_distribute:
9584 case OMPD_teams_distribute_simd:
9585 case OMPD_teams_distribute_parallel_for:
9586 case OMPD_teams_distribute_parallel_for_simd:
9587 case OMPD_target_update:
9588 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00009589 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009590 case OMPD_declare_target:
9591 case OMPD_end_declare_target:
9592 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009593 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009594 case OMPD_taskloop:
9595 case OMPD_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009596 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009597 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009598 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9599 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009600 return;
9601 }
9602
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009603 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009604 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009605 return;
9606
9607 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009608 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009609 return;
9610 }
9611
9612 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009613 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009614 S = L->getBody();
9615
9616 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009617 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009618 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009619}
9620
9621bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009622 // If emitting code for the host, we do not process FD here. Instead we do
9623 // the normal code generation.
Alexey Bataev729e2422019-08-23 16:11:14 +00009624 if (!CGM.getLangOpts().OpenMPIsDevice) {
9625 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9626 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9627 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9628 // Do not emit device_type(nohost) functions for the host.
9629 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9630 return true;
9631 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009632 return false;
Alexey Bataev729e2422019-08-23 16:11:14 +00009633 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009634
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009635 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009636 StringRef Name = CGM.getMangledName(GD);
9637 // Try to detect target regions in the function.
Alexey Bataev729e2422019-08-23 16:11:14 +00009638 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009639 scanForTargetRegionsFunctions(FD->getBody(), Name);
Alexey Bataev729e2422019-08-23 16:11:14 +00009640 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9641 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9642 // Do not emit device_type(nohost) functions for the host.
9643 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9644 return true;
9645 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009646
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009647 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009648 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009649 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009650}
9651
9652bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9653 if (!CGM.getLangOpts().OpenMPIsDevice)
9654 return false;
9655
9656 // Check if there are Ctors/Dtors in this declaration and look for target
9657 // regions in it. We use the complete variant to produce the kernel name
9658 // mangling.
9659 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009660 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9661 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009662 StringRef ParentName =
9663 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9664 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9665 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009666 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009667 StringRef ParentName =
9668 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9669 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9670 }
9671 }
9672
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009673 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009674 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009675 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9676 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009677 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9678 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9679 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009680 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009681 return true;
9682 }
9683 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009684}
9685
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009686llvm::Constant *
9687CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9688 const VarDecl *VD) {
9689 assert(VD->getType().isConstant(CGM.getContext()) &&
9690 "Expected constant variable.");
9691 StringRef VarName;
9692 llvm::Constant *Addr;
9693 llvm::GlobalValue::LinkageTypes Linkage;
9694 QualType Ty = VD->getType();
9695 SmallString<128> Buffer;
9696 {
9697 unsigned DeviceID;
9698 unsigned FileID;
9699 unsigned Line;
9700 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9701 FileID, Line);
9702 llvm::raw_svector_ostream OS(Buffer);
9703 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9704 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9705 VarName = OS.str();
9706 }
9707 Linkage = llvm::GlobalValue::InternalLinkage;
9708 Addr =
9709 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9710 getDefaultFirstprivateAddressSpace());
9711 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9712 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9713 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9714 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9715 VarName, Addr, VarSize,
9716 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9717 return Addr;
9718}
9719
Alexey Bataev03f270c2018-03-30 18:31:07 +00009720void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9721 llvm::Constant *Addr) {
Alexey Bataev4db9dc62019-09-23 15:53:51 +00009722 if (CGM.getLangOpts().OMPTargetTriples.empty())
9723 return;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009724 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9725 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9726 if (!Res) {
9727 if (CGM.getLangOpts().OpenMPIsDevice) {
9728 // Register non-target variables being emitted in device code (debug info
9729 // may cause this).
9730 StringRef VarName = CGM.getMangledName(VD);
9731 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009732 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009733 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009734 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009735 // Register declare target variables.
9736 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9737 StringRef VarName;
9738 CharUnits VarSize;
9739 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009740
9741 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9742 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009743 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9744 VarName = CGM.getMangledName(VD);
9745 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9746 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9747 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9748 } else {
9749 VarSize = CharUnits::Zero();
9750 }
9751 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9752 // Temp solution to prevent optimizations of the internal variables.
9753 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9754 std::string RefName = getName({VarName, "ref"});
9755 if (!CGM.GetGlobalValue(RefName)) {
9756 llvm::Constant *AddrRef =
9757 getOrCreateInternalVariable(Addr->getType(), RefName);
9758 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9759 GVAddrRef->setConstant(/*Val=*/true);
9760 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9761 GVAddrRef->setInitializer(Addr);
9762 CGM.addCompilerUsedGlobal(GVAddrRef);
9763 }
9764 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009765 } else {
9766 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9767 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9768 HasRequiresUnifiedSharedMemory)) &&
9769 "Declare target attribute must link or to with unified memory.");
9770 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9771 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9772 else
9773 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9774
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009775 if (CGM.getLangOpts().OpenMPIsDevice) {
9776 VarName = Addr->getName();
9777 Addr = nullptr;
9778 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009779 VarName = getAddrOfDeclareTargetVar(VD).getName();
9780 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009781 }
9782 VarSize = CGM.getPointerSize();
9783 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009784 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009785
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009786 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9787 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009788}
9789
Samuel Antaoee8fb302016-01-06 13:42:12 +00009790bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009791 if (isa<FunctionDecl>(GD.getDecl()) ||
9792 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009793 return emitTargetFunctions(GD);
9794
9795 return emitTargetGlobalVariable(GD);
9796}
9797
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009798void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9799 for (const VarDecl *VD : DeferredGlobalVariables) {
9800 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009801 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009802 if (!Res)
9803 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009804 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9805 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009806 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009807 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009808 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9809 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9810 HasRequiresUnifiedSharedMemory)) &&
9811 "Expected link clause or to clause with unified memory.");
9812 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009813 }
9814 }
9815}
9816
Alexey Bataev60705422018-10-30 15:50:12 +00009817void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9818 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9819 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9820 " Expected target-based directive.");
9821}
9822
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009823void CGOpenMPRuntime::checkArchForUnifiedAddressing(
9824 const OMPRequiresDecl *D) {
9825 for (const OMPClause *Clause : D->clauselists()) {
9826 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9827 HasRequiresUnifiedSharedMemory = true;
9828 break;
9829 }
9830 }
9831}
9832
Alexey Bataevc5687252019-03-21 19:35:27 +00009833bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9834 LangAS &AS) {
9835 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9836 return false;
9837 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9838 switch(A->getAllocatorType()) {
9839 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9840 // Not supported, fallback to the default mem space.
9841 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9842 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9843 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9844 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9845 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9846 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9847 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9848 AS = LangAS::Default;
9849 return true;
9850 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9851 llvm_unreachable("Expected predefined allocator for the variables with the "
9852 "static storage.");
9853 }
9854 return false;
9855}
9856
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009857bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9858 return HasRequiresUnifiedSharedMemory;
9859}
9860
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009861CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9862 CodeGenModule &CGM)
9863 : CGM(CGM) {
9864 if (CGM.getLangOpts().OpenMPIsDevice) {
9865 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9866 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9867 }
9868}
9869
9870CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9871 if (CGM.getLangOpts().OpenMPIsDevice)
9872 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9873}
9874
Alexey Bataev6d944102018-05-02 15:45:28 +00009875bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009876 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9877 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009878
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009879 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009880 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009881 // Do not to emit function if it is marked as declare target as it was already
9882 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009883 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009884 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9885 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009886 return !F->isDeclaration();
9887 return false;
9888 }
9889 return true;
9890 }
9891
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009892 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009893}
9894
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009895llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9896 // If we don't have entries or if we are emitting code for the device, we
9897 // don't need to do anything.
9898 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9899 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9900 (OffloadEntriesInfoManager.empty() &&
9901 !HasEmittedDeclareTargetRegion &&
9902 !HasEmittedTargetRegion))
9903 return nullptr;
9904
9905 // Create and register the function that handles the requires directives.
9906 ASTContext &C = CGM.getContext();
9907
9908 llvm::Function *RequiresRegFn;
9909 {
9910 CodeGenFunction CGF(CGM);
9911 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
9912 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
9913 std::string ReqName = getName({"omp_offloading", "requires_reg"});
9914 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
9915 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
9916 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
9917 // TODO: check for other requires clauses.
9918 // The requires directive takes effect only when a target region is
9919 // present in the compilation unit. Otherwise it is ignored and not
9920 // passed to the runtime. This avoids the runtime from throwing an error
9921 // for mismatching requires clauses across compilation units that don't
9922 // contain at least 1 target region.
9923 assert((HasEmittedTargetRegion ||
9924 HasEmittedDeclareTargetRegion ||
9925 !OffloadEntriesInfoManager.empty()) &&
9926 "Target or declare target region expected.");
9927 if (HasRequiresUnifiedSharedMemory)
9928 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
9929 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
9930 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
9931 CGF.FinishFunction();
9932 }
9933 return RequiresRegFn;
9934}
9935
Samuel Antaoee8fb302016-01-06 13:42:12 +00009936llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
9937 // If we have offloading in the current module, we need to emit the entries
9938 // now and register the offloading descriptor.
9939 createOffloadEntriesAndInfoMetadata();
9940
9941 // Create and register the offloading binary descriptors. This is the main
9942 // entity that captures all the information about offloading in the current
9943 // compilation unit.
9944 return createOffloadingBinaryDescriptorRegistration();
9945}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009946
9947void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9948 const OMPExecutableDirective &D,
9949 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009950 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009951 ArrayRef<llvm::Value *> CapturedVars) {
9952 if (!CGF.HaveInsertPoint())
9953 return;
9954
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009955 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009956 CodeGenFunction::RunCleanupsScope Scope(CGF);
9957
9958 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9959 llvm::Value *Args[] = {
9960 RTLoc,
9961 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9962 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9963 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9964 RealArgs.append(std::begin(Args), std::end(Args));
9965 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9966
James Y Knight9871db02019-02-05 16:42:33 +00009967 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009968 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9969}
9970
9971void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009972 const Expr *NumTeams,
9973 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009974 SourceLocation Loc) {
9975 if (!CGF.HaveInsertPoint())
9976 return;
9977
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009978 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009979
Carlo Bertollic6872252016-04-04 15:55:02 +00009980 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009981 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009982 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9983 CGF.CGM.Int32Ty, /* isSigned = */ true)
9984 : CGF.Builder.getInt32(0);
9985
9986 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009987 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009988 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9989 CGF.CGM.Int32Ty, /* isSigned = */ true)
9990 : CGF.Builder.getInt32(0);
9991
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009992 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009993 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9994 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009995 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9996 PushNumTeamsArgs);
9997}
Samuel Antaodf158d52016-04-27 22:58:19 +00009998
Samuel Antaocc10b852016-07-28 14:23:26 +00009999void CGOpenMPRuntime::emitTargetDataCalls(
10000 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10001 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010002 if (!CGF.HaveInsertPoint())
10003 return;
10004
Samuel Antaocc10b852016-07-28 14:23:26 +000010005 // Action used to replace the default codegen action and turn privatization
10006 // off.
10007 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +000010008
10009 // Generate the code for the opening of the data environment. Capture all the
10010 // arguments of the runtime call by reference because they are used in the
10011 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010012 auto &&BeginThenGen = [this, &D, Device, &Info,
10013 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010014 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +000010015 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +000010016 MappableExprsHandler::MapValuesArrayTy Pointers;
10017 MappableExprsHandler::MapValuesArrayTy Sizes;
10018 MappableExprsHandler::MapFlagsArrayTy MapTypes;
10019
10020 // Get map clause information.
10021 MappableExprsHandler MCHandler(D, CGF);
10022 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +000010023
10024 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +000010025 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010026
10027 llvm::Value *BasePointersArrayArg = nullptr;
10028 llvm::Value *PointersArrayArg = nullptr;
10029 llvm::Value *SizesArrayArg = nullptr;
10030 llvm::Value *MapTypesArrayArg = nullptr;
10031 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010032 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010033
10034 // Emit device ID if any.
10035 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010036 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010037 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010038 CGF.Int64Ty, /*isSigned=*/true);
10039 } else {
10040 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10041 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010042
10043 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010044 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010045
10046 llvm::Value *OffloadingArgs[] = {
10047 DeviceID, PointerNum, BasePointersArrayArg,
10048 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010049 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +000010050 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +000010051
10052 // If device pointer privatization is required, emit the body of the region
10053 // here. It will have to be duplicated: with and without privatization.
10054 if (!Info.CaptureDeviceAddrMap.empty())
10055 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010056 };
10057
10058 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010059 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10060 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010061 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +000010062
10063 llvm::Value *BasePointersArrayArg = nullptr;
10064 llvm::Value *PointersArrayArg = nullptr;
10065 llvm::Value *SizesArrayArg = nullptr;
10066 llvm::Value *MapTypesArrayArg = nullptr;
10067 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010068 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010069
10070 // Emit device ID if any.
10071 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010072 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010073 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010074 CGF.Int64Ty, /*isSigned=*/true);
10075 } else {
10076 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10077 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010078
10079 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010080 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010081
10082 llvm::Value *OffloadingArgs[] = {
10083 DeviceID, PointerNum, BasePointersArrayArg,
10084 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010085 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +000010086 OffloadingArgs);
10087 };
10088
Samuel Antaocc10b852016-07-28 14:23:26 +000010089 // If we need device pointer privatization, we need to emit the body of the
10090 // region with no privatization in the 'else' branch of the conditional.
10091 // Otherwise, we don't have to do anything.
10092 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10093 PrePostActionTy &) {
10094 if (!Info.CaptureDeviceAddrMap.empty()) {
10095 CodeGen.setAction(NoPrivAction);
10096 CodeGen(CGF);
10097 }
10098 };
10099
10100 // We don't have to do anything to close the region if the if clause evaluates
10101 // to false.
10102 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +000010103
10104 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010105 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010106 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010107 RegionCodeGenTy RCG(BeginThenGen);
10108 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010109 }
10110
Samuel Antaocc10b852016-07-28 14:23:26 +000010111 // If we don't require privatization of device pointers, we emit the body in
10112 // between the runtime calls. This avoids duplicating the body code.
10113 if (Info.CaptureDeviceAddrMap.empty()) {
10114 CodeGen.setAction(NoPrivAction);
10115 CodeGen(CGF);
10116 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010117
10118 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010119 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010120 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010121 RegionCodeGenTy RCG(EndThenGen);
10122 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010123 }
10124}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010125
Samuel Antao8d2d7302016-05-26 18:30:22 +000010126void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +000010127 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10128 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010129 if (!CGF.HaveInsertPoint())
10130 return;
10131
Samuel Antao8dd66282016-04-27 23:14:30 +000010132 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +000010133 isa<OMPTargetExitDataDirective>(D) ||
10134 isa<OMPTargetUpdateDirective>(D)) &&
10135 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +000010136
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010137 CodeGenFunction::OMPTargetDataInfo InputInfo;
10138 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010139 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010140 auto &&ThenGen = [this, &D, Device, &InputInfo,
10141 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010142 // Emit device ID if any.
10143 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010144 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010145 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010146 CGF.Int64Ty, /*isSigned=*/true);
10147 } else {
10148 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10149 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010150
10151 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010152 llvm::Constant *PointerNum =
10153 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010154
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010155 llvm::Value *OffloadingArgs[] = {DeviceID,
10156 PointerNum,
10157 InputInfo.BasePointersArray.getPointer(),
10158 InputInfo.PointersArray.getPointer(),
10159 InputInfo.SizesArray.getPointer(),
10160 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +000010161
Samuel Antao8d2d7302016-05-26 18:30:22 +000010162 // Select the right runtime function call for each expected standalone
10163 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010164 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +000010165 OpenMPRTLFunction RTLFn;
10166 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +000010167 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010168 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10169 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010170 break;
10171 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010172 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10173 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010174 break;
10175 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010176 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10177 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010178 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010179 case OMPD_parallel:
10180 case OMPD_for:
10181 case OMPD_parallel_for:
10182 case OMPD_parallel_sections:
10183 case OMPD_for_simd:
10184 case OMPD_parallel_for_simd:
10185 case OMPD_cancel:
10186 case OMPD_cancellation_point:
10187 case OMPD_ordered:
10188 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +000010189 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010190 case OMPD_task:
10191 case OMPD_simd:
10192 case OMPD_sections:
10193 case OMPD_section:
10194 case OMPD_single:
10195 case OMPD_master:
10196 case OMPD_critical:
10197 case OMPD_taskyield:
10198 case OMPD_barrier:
10199 case OMPD_taskwait:
10200 case OMPD_taskgroup:
10201 case OMPD_atomic:
10202 case OMPD_flush:
10203 case OMPD_teams:
10204 case OMPD_target_data:
10205 case OMPD_distribute:
10206 case OMPD_distribute_simd:
10207 case OMPD_distribute_parallel_for:
10208 case OMPD_distribute_parallel_for_simd:
10209 case OMPD_teams_distribute:
10210 case OMPD_teams_distribute_simd:
10211 case OMPD_teams_distribute_parallel_for:
10212 case OMPD_teams_distribute_parallel_for_simd:
10213 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +000010214 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010215 case OMPD_declare_target:
10216 case OMPD_end_declare_target:
10217 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +000010218 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010219 case OMPD_taskloop:
10220 case OMPD_taskloop_simd:
10221 case OMPD_target:
10222 case OMPD_target_simd:
10223 case OMPD_target_teams_distribute:
10224 case OMPD_target_teams_distribute_simd:
10225 case OMPD_target_teams_distribute_parallel_for:
10226 case OMPD_target_teams_distribute_parallel_for_simd:
10227 case OMPD_target_teams:
10228 case OMPD_target_parallel:
10229 case OMPD_target_parallel_for:
10230 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +000010231 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010232 case OMPD_unknown:
10233 llvm_unreachable("Unexpected standalone target data directive.");
10234 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010235 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010236 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010237 };
10238
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010239 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10240 CodeGenFunction &CGF, PrePostActionTy &) {
10241 // Fill up the arrays with all the mapped variables.
10242 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10243 MappableExprsHandler::MapValuesArrayTy Pointers;
10244 MappableExprsHandler::MapValuesArrayTy Sizes;
10245 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010246
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010247 // Get map clause information.
10248 MappableExprsHandler MEHandler(D, CGF);
10249 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10250
10251 TargetDataInfo Info;
10252 // Fill up the arrays and create the arguments.
10253 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10254 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10255 Info.PointersArray, Info.SizesArray,
10256 Info.MapTypesArray, Info);
10257 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10258 InputInfo.BasePointersArray =
10259 Address(Info.BasePointersArray, CGM.getPointerAlign());
10260 InputInfo.PointersArray =
10261 Address(Info.PointersArray, CGM.getPointerAlign());
10262 InputInfo.SizesArray =
10263 Address(Info.SizesArray, CGM.getPointerAlign());
10264 MapTypesArray = Info.MapTypesArray;
10265 if (D.hasClausesOfKind<OMPDependClause>())
10266 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10267 else
Alexey Bataev768f1f22018-01-09 19:59:25 +000010268 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010269 };
10270
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010271 if (IfCond) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010272 emitOMPIfClause(CGF, IfCond, TargetThenGen,
10273 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010274 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010275 RegionCodeGenTy ThenRCG(TargetThenGen);
10276 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010277 }
10278}
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010279
10280namespace {
10281 /// Kind of parameter in a function with 'declare simd' directive.
10282 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10283 /// Attribute set of the parameter.
10284 struct ParamAttrTy {
10285 ParamKindTy Kind = Vector;
10286 llvm::APSInt StrideOrArg;
10287 llvm::APSInt Alignment;
10288 };
10289} // namespace
10290
10291static unsigned evaluateCDTSize(const FunctionDecl *FD,
10292 ArrayRef<ParamAttrTy> ParamAttrs) {
10293 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10294 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10295 // of that clause. The VLEN value must be power of 2.
10296 // In other case the notion of the function`s "characteristic data type" (CDT)
10297 // is used to compute the vector length.
10298 // CDT is defined in the following order:
10299 // a) For non-void function, the CDT is the return type.
10300 // b) If the function has any non-uniform, non-linear parameters, then the
10301 // CDT is the type of the first such parameter.
10302 // c) If the CDT determined by a) or b) above is struct, union, or class
10303 // type which is pass-by-value (except for the type that maps to the
10304 // built-in complex data type), the characteristic data type is int.
10305 // d) If none of the above three cases is applicable, the CDT is int.
10306 // The VLEN is then determined based on the CDT and the size of vector
10307 // register of that ISA for which current vector version is generated. The
10308 // VLEN is computed using the formula below:
10309 // VLEN = sizeof(vector_register) / sizeof(CDT),
10310 // where vector register size specified in section 3.2.1 Registers and the
10311 // Stack Frame of original AMD64 ABI document.
10312 QualType RetType = FD->getReturnType();
10313 if (RetType.isNull())
10314 return 0;
10315 ASTContext &C = FD->getASTContext();
10316 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010317 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010318 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010319 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010320 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010321 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010322 if (ParamAttrs[Offset].Kind == Vector)
10323 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10324 ++Offset;
10325 }
10326 if (CDT.isNull()) {
10327 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10328 if (ParamAttrs[I + Offset].Kind == Vector) {
10329 CDT = FD->getParamDecl(I)->getType();
10330 break;
10331 }
10332 }
10333 }
10334 }
10335 if (CDT.isNull())
10336 CDT = C.IntTy;
10337 CDT = CDT->getCanonicalTypeUnqualified();
10338 if (CDT->isRecordType() || CDT->isUnionType())
10339 CDT = C.IntTy;
10340 return C.getTypeSize(CDT);
10341}
10342
10343static void
10344emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000010345 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010346 ArrayRef<ParamAttrTy> ParamAttrs,
10347 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10348 struct ISADataTy {
10349 char ISA;
10350 unsigned VecRegSize;
10351 };
10352 ISADataTy ISAData[] = {
10353 {
10354 'b', 128
10355 }, // SSE
10356 {
10357 'c', 256
10358 }, // AVX
10359 {
10360 'd', 256
10361 }, // AVX2
10362 {
10363 'e', 512
10364 }, // AVX512
10365 };
10366 llvm::SmallVector<char, 2> Masked;
10367 switch (State) {
10368 case OMPDeclareSimdDeclAttr::BS_Undefined:
10369 Masked.push_back('N');
10370 Masked.push_back('M');
10371 break;
10372 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10373 Masked.push_back('N');
10374 break;
10375 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10376 Masked.push_back('M');
10377 break;
10378 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010379 for (char Mask : Masked) {
10380 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010381 SmallString<256> Buffer;
10382 llvm::raw_svector_ostream Out(Buffer);
10383 Out << "_ZGV" << Data.ISA << Mask;
10384 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +000010385 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10386 assert(NumElts && "Non-zero simdlen/cdtsize expected");
10387 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010388 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010389 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010390 }
10391 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010392 switch (ParamAttr.Kind){
10393 case LinearWithVarStride:
10394 Out << 's' << ParamAttr.StrideOrArg;
10395 break;
10396 case Linear:
10397 Out << 'l';
10398 if (!!ParamAttr.StrideOrArg)
10399 Out << ParamAttr.StrideOrArg;
10400 break;
10401 case Uniform:
10402 Out << 'u';
10403 break;
10404 case Vector:
10405 Out << 'v';
10406 break;
10407 }
10408 if (!!ParamAttr.Alignment)
10409 Out << 'a' << ParamAttr.Alignment;
10410 }
10411 Out << '_' << Fn->getName();
10412 Fn->addFnAttr(Out.str());
10413 }
10414 }
10415}
10416
Alexey Bataeva0a22642019-04-16 13:56:21 +000010417// This are the Functions that are needed to mangle the name of the
10418// vector functions generated by the compiler, according to the rules
10419// defined in the "Vector Function ABI specifications for AArch64",
10420// available at
10421// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10422
10423/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10424///
10425/// TODO: Need to implement the behavior for reference marked with a
10426/// var or no linear modifiers (1.b in the section). For this, we
10427/// need to extend ParamKindTy to support the linear modifiers.
10428static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10429 QT = QT.getCanonicalType();
10430
10431 if (QT->isVoidType())
10432 return false;
10433
10434 if (Kind == ParamKindTy::Uniform)
10435 return false;
10436
10437 if (Kind == ParamKindTy::Linear)
10438 return false;
10439
10440 // TODO: Handle linear references with modifiers
10441
10442 if (Kind == ParamKindTy::LinearWithVarStride)
10443 return false;
10444
10445 return true;
10446}
10447
10448/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10449static bool getAArch64PBV(QualType QT, ASTContext &C) {
10450 QT = QT.getCanonicalType();
10451 unsigned Size = C.getTypeSize(QT);
10452
10453 // Only scalars and complex within 16 bytes wide set PVB to true.
10454 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10455 return false;
10456
10457 if (QT->isFloatingType())
10458 return true;
10459
10460 if (QT->isIntegerType())
10461 return true;
10462
10463 if (QT->isPointerType())
10464 return true;
10465
10466 // TODO: Add support for complex types (section 3.1.2, item 2).
10467
10468 return false;
10469}
10470
10471/// Computes the lane size (LS) of a return type or of an input parameter,
10472/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10473/// TODO: Add support for references, section 3.2.1, item 1.
10474static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10475 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10476 QualType PTy = QT.getCanonicalType()->getPointeeType();
10477 if (getAArch64PBV(PTy, C))
10478 return C.getTypeSize(PTy);
10479 }
10480 if (getAArch64PBV(QT, C))
10481 return C.getTypeSize(QT);
10482
10483 return C.getTypeSize(C.getUIntPtrType());
10484}
10485
10486// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10487// signature of the scalar function, as defined in 3.2.2 of the
10488// AAVFABI.
10489static std::tuple<unsigned, unsigned, bool>
10490getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10491 QualType RetType = FD->getReturnType().getCanonicalType();
10492
10493 ASTContext &C = FD->getASTContext();
10494
10495 bool OutputBecomesInput = false;
10496
10497 llvm::SmallVector<unsigned, 8> Sizes;
10498 if (!RetType->isVoidType()) {
10499 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10500 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10501 OutputBecomesInput = true;
10502 }
10503 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10504 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10505 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10506 }
10507
10508 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10509 // The LS of a function parameter / return value can only be a power
10510 // of 2, starting from 8 bits, up to 128.
10511 assert(std::all_of(Sizes.begin(), Sizes.end(),
10512 [](unsigned Size) {
10513 return Size == 8 || Size == 16 || Size == 32 ||
10514 Size == 64 || Size == 128;
10515 }) &&
10516 "Invalid size");
10517
10518 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10519 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10520 OutputBecomesInput);
10521}
10522
10523/// Mangle the parameter part of the vector function name according to
10524/// their OpenMP classification. The mangling function is defined in
10525/// section 3.5 of the AAVFABI.
10526static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10527 SmallString<256> Buffer;
10528 llvm::raw_svector_ostream Out(Buffer);
10529 for (const auto &ParamAttr : ParamAttrs) {
10530 switch (ParamAttr.Kind) {
10531 case LinearWithVarStride:
10532 Out << "ls" << ParamAttr.StrideOrArg;
10533 break;
10534 case Linear:
10535 Out << 'l';
10536 // Don't print the step value if it is not present or if it is
10537 // equal to 1.
10538 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10539 Out << ParamAttr.StrideOrArg;
10540 break;
10541 case Uniform:
10542 Out << 'u';
10543 break;
10544 case Vector:
10545 Out << 'v';
10546 break;
10547 }
10548
10549 if (!!ParamAttr.Alignment)
10550 Out << 'a' << ParamAttr.Alignment;
10551 }
10552
10553 return Out.str();
10554}
10555
10556// Function used to add the attribute. The parameter `VLEN` is
10557// templated to allow the use of "x" when targeting scalable functions
10558// for SVE.
10559template <typename T>
10560static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10561 char ISA, StringRef ParSeq,
10562 StringRef MangledName, bool OutputBecomesInput,
10563 llvm::Function *Fn) {
10564 SmallString<256> Buffer;
10565 llvm::raw_svector_ostream Out(Buffer);
10566 Out << Prefix << ISA << LMask << VLEN;
10567 if (OutputBecomesInput)
10568 Out << "v";
10569 Out << ParSeq << "_" << MangledName;
10570 Fn->addFnAttr(Out.str());
10571}
10572
10573// Helper function to generate the Advanced SIMD names depending on
10574// the value of the NDS when simdlen is not present.
10575static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10576 StringRef Prefix, char ISA,
10577 StringRef ParSeq, StringRef MangledName,
10578 bool OutputBecomesInput,
10579 llvm::Function *Fn) {
10580 switch (NDS) {
10581 case 8:
10582 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10583 OutputBecomesInput, Fn);
10584 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10585 OutputBecomesInput, Fn);
10586 break;
10587 case 16:
10588 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10589 OutputBecomesInput, Fn);
10590 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10591 OutputBecomesInput, Fn);
10592 break;
10593 case 32:
10594 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10595 OutputBecomesInput, Fn);
10596 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10597 OutputBecomesInput, Fn);
10598 break;
10599 case 64:
10600 case 128:
10601 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10602 OutputBecomesInput, Fn);
10603 break;
10604 default:
10605 llvm_unreachable("Scalar type is too wide.");
10606 }
10607}
10608
10609/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10610static void emitAArch64DeclareSimdFunction(
10611 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10612 ArrayRef<ParamAttrTy> ParamAttrs,
10613 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10614 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10615
10616 // Get basic data for building the vector signature.
10617 const auto Data = getNDSWDS(FD, ParamAttrs);
10618 const unsigned NDS = std::get<0>(Data);
10619 const unsigned WDS = std::get<1>(Data);
10620 const bool OutputBecomesInput = std::get<2>(Data);
10621
10622 // Check the values provided via `simdlen` by the user.
10623 // 1. A `simdlen(1)` doesn't produce vector signatures,
10624 if (UserVLEN == 1) {
10625 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10626 DiagnosticsEngine::Warning,
10627 "The clause simdlen(1) has no effect when targeting aarch64.");
10628 CGM.getDiags().Report(SLoc, DiagID);
10629 return;
10630 }
10631
10632 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10633 // Advanced SIMD output.
10634 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10635 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10636 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10637 "power of 2 when targeting Advanced SIMD.");
10638 CGM.getDiags().Report(SLoc, DiagID);
10639 return;
10640 }
10641
10642 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10643 // limits.
10644 if (ISA == 's' && UserVLEN != 0) {
10645 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10646 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10647 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10648 "lanes in the architectural constraints "
10649 "for SVE (min is 128-bit, max is "
10650 "2048-bit, by steps of 128-bit)");
10651 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10652 return;
10653 }
10654 }
10655
10656 // Sort out parameter sequence.
10657 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10658 StringRef Prefix = "_ZGV";
10659 // Generate simdlen from user input (if any).
10660 if (UserVLEN) {
10661 if (ISA == 's') {
10662 // SVE generates only a masked function.
10663 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10664 OutputBecomesInput, Fn);
10665 } else {
10666 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10667 // Advanced SIMD generates one or two functions, depending on
10668 // the `[not]inbranch` clause.
10669 switch (State) {
10670 case OMPDeclareSimdDeclAttr::BS_Undefined:
10671 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10672 OutputBecomesInput, Fn);
10673 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10674 OutputBecomesInput, Fn);
10675 break;
10676 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10677 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10678 OutputBecomesInput, Fn);
10679 break;
10680 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10681 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10682 OutputBecomesInput, Fn);
10683 break;
10684 }
10685 }
10686 } else {
10687 // If no user simdlen is provided, follow the AAVFABI rules for
10688 // generating the vector length.
10689 if (ISA == 's') {
10690 // SVE, section 3.4.1, item 1.
10691 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10692 OutputBecomesInput, Fn);
10693 } else {
10694 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10695 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10696 // two vector names depending on the use of the clause
10697 // `[not]inbranch`.
10698 switch (State) {
10699 case OMPDeclareSimdDeclAttr::BS_Undefined:
10700 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10701 OutputBecomesInput, Fn);
10702 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10703 OutputBecomesInput, Fn);
10704 break;
10705 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10706 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10707 OutputBecomesInput, Fn);
10708 break;
10709 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10710 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10711 OutputBecomesInput, Fn);
10712 break;
10713 }
10714 }
10715 }
10716}
10717
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010718void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10719 llvm::Function *Fn) {
10720 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010721 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010722 // Map params to their positions in function decl.
10723 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10724 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010725 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010726 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010727 for (const ParmVarDecl *P : FD->parameters()) {
10728 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010729 ++ParamPos;
10730 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010731 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010732 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010733 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10734 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010735 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010736 E = E->IgnoreParenImpCasts();
10737 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010738 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010739 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010740 } else {
10741 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10742 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010743 Pos = ParamPositions[PVD];
10744 }
10745 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010746 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010747 // Get alignment info.
10748 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010749 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010750 E = E->IgnoreParenImpCasts();
10751 unsigned Pos;
10752 QualType ParmTy;
10753 if (isa<CXXThisExpr>(E)) {
10754 Pos = ParamPositions[FD];
10755 ParmTy = E->getType();
10756 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010757 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10758 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010759 Pos = ParamPositions[PVD];
10760 ParmTy = PVD->getType();
10761 }
10762 ParamAttrs[Pos].Alignment =
10763 (*NI)
10764 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010765 : llvm::APSInt::getUnsigned(
10766 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10767 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010768 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010769 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010770 // Mark linear parameters.
10771 auto SI = Attr->steps_begin();
10772 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010773 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010774 E = E->IgnoreParenImpCasts();
10775 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010776 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010777 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010778 } else {
10779 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10780 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010781 Pos = ParamPositions[PVD];
10782 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010783 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010784 ParamAttr.Kind = Linear;
10785 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010786 Expr::EvalResult Result;
10787 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010788 if (const auto *DRE =
10789 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10790 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010791 ParamAttr.Kind = LinearWithVarStride;
10792 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10793 ParamPositions[StridePVD->getCanonicalDecl()]);
10794 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010795 }
Fangrui Song407659a2018-11-30 23:41:18 +000010796 } else {
10797 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010798 }
10799 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010800 ++SI;
10801 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010802 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010803 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010804 SourceLocation ExprLoc;
10805 const Expr *VLENExpr = Attr->getSimdlen();
10806 if (VLENExpr) {
10807 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10808 ExprLoc = VLENExpr->getExprLoc();
10809 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010810 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10811 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010812 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010813 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010814 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10815 unsigned VLEN = VLENVal.getExtValue();
10816 StringRef MangledName = Fn->getName();
10817 if (CGM.getTarget().hasFeature("sve"))
10818 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10819 MangledName, 's', 128, Fn, ExprLoc);
10820 if (CGM.getTarget().hasFeature("neon"))
10821 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10822 MangledName, 'n', 128, Fn, ExprLoc);
10823 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010824 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010825 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010826 }
10827}
Alexey Bataev8b427062016-05-25 12:36:08 +000010828
10829namespace {
10830/// Cleanup action for doacross support.
10831class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10832public:
10833 static const int DoacrossFinArgs = 2;
10834
10835private:
James Y Knight9871db02019-02-05 16:42:33 +000010836 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010837 llvm::Value *Args[DoacrossFinArgs];
10838
10839public:
James Y Knight9871db02019-02-05 16:42:33 +000010840 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10841 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010842 : RTLFn(RTLFn) {
10843 assert(CallArgs.size() == DoacrossFinArgs);
10844 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10845 }
10846 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10847 if (!CGF.HaveInsertPoint())
10848 return;
10849 CGF.EmitRuntimeCall(RTLFn, Args);
10850 }
10851};
10852} // namespace
10853
10854void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010855 const OMPLoopDirective &D,
10856 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010857 if (!CGF.HaveInsertPoint())
10858 return;
10859
10860 ASTContext &C = CGM.getContext();
10861 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10862 RecordDecl *RD;
10863 if (KmpDimTy.isNull()) {
10864 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10865 // kmp_int64 lo; // lower
10866 // kmp_int64 up; // upper
10867 // kmp_int64 st; // stride
10868 // };
10869 RD = C.buildImplicitRecord("kmp_dim");
10870 RD->startDefinition();
10871 addFieldToRecordDecl(C, RD, Int64Ty);
10872 addFieldToRecordDecl(C, RD, Int64Ty);
10873 addFieldToRecordDecl(C, RD, Int64Ty);
10874 RD->completeDefinition();
10875 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010876 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010877 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010878 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010879 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10880 QualType ArrayTy =
10881 C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010882
Alexey Bataevf138fda2018-08-13 19:04:24 +000010883 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10884 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010885 enum { LowerFD = 0, UpperFD, StrideFD };
10886 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010887 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010888 LValue DimsLVal = CGF.MakeAddrLValue(
10889 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010890 // dims.upper = num_iterations;
10891 LValue UpperLVal = CGF.EmitLValueForField(
10892 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10893 llvm::Value *NumIterVal =
10894 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10895 D.getNumIterations()->getType(), Int64Ty,
10896 D.getNumIterations()->getExprLoc());
10897 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10898 // dims.stride = 1;
10899 LValue StrideLVal = CGF.EmitLValueForField(
10900 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10901 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10902 StrideLVal);
10903 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010904
10905 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10906 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010907 llvm::Value *Args[] = {
10908 emitUpdateLocation(CGF, D.getBeginLoc()),
10909 getThreadID(CGF, D.getBeginLoc()),
10910 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10911 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010912 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010913 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010914
James Y Knight9871db02019-02-05 16:42:33 +000010915 llvm::FunctionCallee RTLFn =
10916 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010917 CGF.EmitRuntimeCall(RTLFn, Args);
10918 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010919 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010920 llvm::FunctionCallee FiniRTLFn =
10921 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010922 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10923 llvm::makeArrayRef(FiniArgs));
10924}
10925
10926void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10927 const OMPDependClause *C) {
10928 QualType Int64Ty =
10929 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010930 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10931 QualType ArrayTy = CGM.getContext().getConstantArrayType(
10932 Int64Ty, Size, ArrayType::Normal, 0);
10933 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10934 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10935 const Expr *CounterVal = C->getLoopData(I);
10936 assert(CounterVal);
10937 llvm::Value *CntVal = CGF.EmitScalarConversion(
10938 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10939 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010940 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10941 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010942 }
10943 llvm::Value *Args[] = {
10944 emitUpdateLocation(CGF, C->getBeginLoc()),
10945 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010946 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010947 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010948 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010949 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010950 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010951 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10952 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10953 }
10954 CGF.EmitRuntimeCall(RTLFn, Args);
10955}
10956
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010957void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010958 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010959 ArrayRef<llvm::Value *> Args) const {
10960 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010961 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10962
James Y Knight9871db02019-02-05 16:42:33 +000010963 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010964 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010965 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010966 return;
10967 }
10968 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010969 CGF.EmitRuntimeCall(Callee, Args);
10970}
10971
10972void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010973 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010974 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010975 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010976}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010977
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000010978void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
10979 if (const auto *FD = dyn_cast<FunctionDecl>(D))
10980 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
10981 HasEmittedDeclareTargetRegion = true;
10982}
10983
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010984Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10985 const VarDecl *NativeParam,
10986 const VarDecl *TargetParam) const {
10987 return CGF.GetAddrOfLocalVar(NativeParam);
10988}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010989
Alexey Bataev4f680db2019-03-19 16:41:16 +000010990namespace {
10991/// Cleanup action for allocate support.
10992class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10993public:
10994 static const int CleanupArgs = 3;
10995
10996private:
10997 llvm::FunctionCallee RTLFn;
10998 llvm::Value *Args[CleanupArgs];
10999
11000public:
11001 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
11002 ArrayRef<llvm::Value *> CallArgs)
11003 : RTLFn(RTLFn) {
11004 assert(CallArgs.size() == CleanupArgs &&
11005 "Size of arguments does not match.");
11006 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11007 }
11008 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
11009 if (!CGF.HaveInsertPoint())
11010 return;
11011 CGF.EmitRuntimeCall(RTLFn, Args);
11012 }
11013};
11014} // namespace
11015
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011016Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
11017 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011018 if (!VD)
11019 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000011020 const VarDecl *CVD = VD->getCanonicalDecl();
11021 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
11022 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011023 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
11024 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000011025 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
11026 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011027 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011028 llvm::Value *Size;
11029 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
11030 if (CVD->getType()->isVariablyModifiedType()) {
11031 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000011032 // Align the size: ((size + align - 1) / align) * align
11033 Size = CGF.Builder.CreateNUWAdd(
11034 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
11035 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
11036 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011037 } else {
11038 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011039 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000011040 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011041 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11042 assert(AA->getAllocator() &&
11043 "Expected allocator expression for non-default allocator.");
11044 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000011045 // According to the standard, the original allocator type is a enum (integer).
11046 // Convert to pointer type, if required.
11047 if (Allocator->getType()->isIntegerTy())
11048 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11049 else if (Allocator->getType()->isPointerTy())
11050 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11051 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011052 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11053
11054 llvm::Value *Addr =
11055 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
11056 CVD->getName() + ".void.addr");
11057 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11058 Allocator};
11059 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11060
11061 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11062 llvm::makeArrayRef(FiniArgs));
11063 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11064 Addr,
11065 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
11066 CVD->getName() + ".addr");
11067 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011068}
11069
James Y Knight9871db02019-02-05 16:42:33 +000011070llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011071 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11072 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11073 llvm_unreachable("Not supported in SIMD-only mode");
11074}
11075
James Y Knight9871db02019-02-05 16:42:33 +000011076llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011077 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11078 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11079 llvm_unreachable("Not supported in SIMD-only mode");
11080}
11081
James Y Knight9871db02019-02-05 16:42:33 +000011082llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011083 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11084 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11085 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11086 bool Tied, unsigned &NumberOfParts) {
11087 llvm_unreachable("Not supported in SIMD-only mode");
11088}
11089
11090void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11091 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011092 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011093 ArrayRef<llvm::Value *> CapturedVars,
11094 const Expr *IfCond) {
11095 llvm_unreachable("Not supported in SIMD-only mode");
11096}
11097
11098void CGOpenMPSIMDRuntime::emitCriticalRegion(
11099 CodeGenFunction &CGF, StringRef CriticalName,
11100 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11101 const Expr *Hint) {
11102 llvm_unreachable("Not supported in SIMD-only mode");
11103}
11104
11105void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11106 const RegionCodeGenTy &MasterOpGen,
11107 SourceLocation Loc) {
11108 llvm_unreachable("Not supported in SIMD-only mode");
11109}
11110
11111void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11112 SourceLocation Loc) {
11113 llvm_unreachable("Not supported in SIMD-only mode");
11114}
11115
11116void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11117 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11118 SourceLocation Loc) {
11119 llvm_unreachable("Not supported in SIMD-only mode");
11120}
11121
11122void CGOpenMPSIMDRuntime::emitSingleRegion(
11123 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11124 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11125 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11126 ArrayRef<const Expr *> AssignmentOps) {
11127 llvm_unreachable("Not supported in SIMD-only mode");
11128}
11129
11130void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11131 const RegionCodeGenTy &OrderedOpGen,
11132 SourceLocation Loc,
11133 bool IsThreads) {
11134 llvm_unreachable("Not supported in SIMD-only mode");
11135}
11136
11137void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11138 SourceLocation Loc,
11139 OpenMPDirectiveKind Kind,
11140 bool EmitChecks,
11141 bool ForceSimpleCall) {
11142 llvm_unreachable("Not supported in SIMD-only mode");
11143}
11144
11145void CGOpenMPSIMDRuntime::emitForDispatchInit(
11146 CodeGenFunction &CGF, SourceLocation Loc,
11147 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11148 bool Ordered, const DispatchRTInput &DispatchValues) {
11149 llvm_unreachable("Not supported in SIMD-only mode");
11150}
11151
11152void CGOpenMPSIMDRuntime::emitForStaticInit(
11153 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11154 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11155 llvm_unreachable("Not supported in SIMD-only mode");
11156}
11157
11158void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11159 CodeGenFunction &CGF, SourceLocation Loc,
11160 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11161 llvm_unreachable("Not supported in SIMD-only mode");
11162}
11163
11164void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11165 SourceLocation Loc,
11166 unsigned IVSize,
11167 bool IVSigned) {
11168 llvm_unreachable("Not supported in SIMD-only mode");
11169}
11170
11171void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11172 SourceLocation Loc,
11173 OpenMPDirectiveKind DKind) {
11174 llvm_unreachable("Not supported in SIMD-only mode");
11175}
11176
11177llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11178 SourceLocation Loc,
11179 unsigned IVSize, bool IVSigned,
11180 Address IL, Address LB,
11181 Address UB, Address ST) {
11182 llvm_unreachable("Not supported in SIMD-only mode");
11183}
11184
11185void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11186 llvm::Value *NumThreads,
11187 SourceLocation Loc) {
11188 llvm_unreachable("Not supported in SIMD-only mode");
11189}
11190
11191void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
11192 OpenMPProcBindClauseKind ProcBind,
11193 SourceLocation Loc) {
11194 llvm_unreachable("Not supported in SIMD-only mode");
11195}
11196
11197Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11198 const VarDecl *VD,
11199 Address VDAddr,
11200 SourceLocation Loc) {
11201 llvm_unreachable("Not supported in SIMD-only mode");
11202}
11203
11204llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11205 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11206 CodeGenFunction *CGF) {
11207 llvm_unreachable("Not supported in SIMD-only mode");
11208}
11209
11210Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11211 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11212 llvm_unreachable("Not supported in SIMD-only mode");
11213}
11214
11215void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11216 ArrayRef<const Expr *> Vars,
11217 SourceLocation Loc) {
11218 llvm_unreachable("Not supported in SIMD-only mode");
11219}
11220
11221void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11222 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011223 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011224 QualType SharedsTy, Address Shareds,
11225 const Expr *IfCond,
11226 const OMPTaskDataTy &Data) {
11227 llvm_unreachable("Not supported in SIMD-only mode");
11228}
11229
11230void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11231 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011232 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011233 const Expr *IfCond, const OMPTaskDataTy &Data) {
11234 llvm_unreachable("Not supported in SIMD-only mode");
11235}
11236
11237void CGOpenMPSIMDRuntime::emitReduction(
11238 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11239 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11240 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11241 assert(Options.SimpleReduction && "Only simple reduction is expected.");
11242 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
11243 ReductionOps, Options);
11244}
11245
11246llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
11247 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
11248 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
11249 llvm_unreachable("Not supported in SIMD-only mode");
11250}
11251
11252void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
11253 SourceLocation Loc,
11254 ReductionCodeGen &RCG,
11255 unsigned N) {
11256 llvm_unreachable("Not supported in SIMD-only mode");
11257}
11258
11259Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
11260 SourceLocation Loc,
11261 llvm::Value *ReductionsPtr,
11262 LValue SharedLVal) {
11263 llvm_unreachable("Not supported in SIMD-only mode");
11264}
11265
11266void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
11267 SourceLocation Loc) {
11268 llvm_unreachable("Not supported in SIMD-only mode");
11269}
11270
11271void CGOpenMPSIMDRuntime::emitCancellationPointCall(
11272 CodeGenFunction &CGF, SourceLocation Loc,
11273 OpenMPDirectiveKind CancelRegion) {
11274 llvm_unreachable("Not supported in SIMD-only mode");
11275}
11276
11277void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
11278 SourceLocation Loc, const Expr *IfCond,
11279 OpenMPDirectiveKind CancelRegion) {
11280 llvm_unreachable("Not supported in SIMD-only mode");
11281}
11282
11283void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
11284 const OMPExecutableDirective &D, StringRef ParentName,
11285 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11286 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
11287 llvm_unreachable("Not supported in SIMD-only mode");
11288}
11289
Alexey Bataevec7946e2019-09-23 14:06:51 +000011290void CGOpenMPSIMDRuntime::emitTargetCall(
11291 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11292 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
11293 const Expr *Device,
11294 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
11295 const OMPLoopDirective &D)>
11296 SizeEmitter) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011297 llvm_unreachable("Not supported in SIMD-only mode");
11298}
11299
11300bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
11301 llvm_unreachable("Not supported in SIMD-only mode");
11302}
11303
11304bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
11305 llvm_unreachable("Not supported in SIMD-only mode");
11306}
11307
11308bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
11309 return false;
11310}
11311
11312llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() {
11313 return nullptr;
11314}
11315
11316void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
11317 const OMPExecutableDirective &D,
11318 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011319 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011320 ArrayRef<llvm::Value *> CapturedVars) {
11321 llvm_unreachable("Not supported in SIMD-only mode");
11322}
11323
11324void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
11325 const Expr *NumTeams,
11326 const Expr *ThreadLimit,
11327 SourceLocation Loc) {
11328 llvm_unreachable("Not supported in SIMD-only mode");
11329}
11330
11331void CGOpenMPSIMDRuntime::emitTargetDataCalls(
11332 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11333 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
11334 llvm_unreachable("Not supported in SIMD-only mode");
11335}
11336
11337void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
11338 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11339 const Expr *Device) {
11340 llvm_unreachable("Not supported in SIMD-only mode");
11341}
11342
11343void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000011344 const OMPLoopDirective &D,
11345 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011346 llvm_unreachable("Not supported in SIMD-only mode");
11347}
11348
11349void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11350 const OMPDependClause *C) {
11351 llvm_unreachable("Not supported in SIMD-only mode");
11352}
11353
11354const VarDecl *
11355CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
11356 const VarDecl *NativeParam) const {
11357 llvm_unreachable("Not supported in SIMD-only mode");
11358}
11359
11360Address
11361CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
11362 const VarDecl *NativeParam,
11363 const VarDecl *TargetParam) const {
11364 llvm_unreachable("Not supported in SIMD-only mode");
11365}